Skip to content

Commit 5151b9d

Browse files
committed
Add test for so_reuseport stream socket option
1 parent f900035 commit 5151b9d

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
--TEST--
2+
stream_socket_server() SO_REUSEPORT context option test
3+
--SKIPIF--
4+
<?php
5+
if (substr(PHP_OS, 0, 3) == "WIN") {
6+
die('skip SO_REUSEPORT not available on Windows');
7+
}
8+
?>
9+
--FILE--
10+
<?php
11+
// SO_REUSEPORT enabled - should allow multiple servers on same port
12+
$context1 = stream_context_create(['socket' => ['so_reuseport' => true]]);
13+
$server1 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr,
14+
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context1);
15+
16+
if (!$server1) {
17+
die('Unable to create server1');
18+
}
19+
20+
$addr = stream_socket_get_name($server1, false);
21+
$port = (int)substr(strrchr($addr, ':'), 1);
22+
23+
// Establish actual connection on server1
24+
$client1 = stream_socket_client("tcp://127.0.0.1:$port");
25+
$accepted1 = stream_socket_accept($server1, 1);
26+
27+
// Force real TCP connection with data
28+
fwrite($client1, "test");
29+
fread($accepted1, 4);
30+
fwrite($accepted1, "response");
31+
fread($client1, 8);
32+
33+
// Try to bind second server to SAME port with SO_REUSEPORT (while server1 still active)
34+
$context2 = stream_context_create(['socket' => ['so_reuseport' => true]]);
35+
$server2 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr,
36+
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context2);
37+
38+
if ($server2) {
39+
echo "SO_REUSEPORT enabled: Multiple servers succeeded\n";
40+
41+
// Verify server2 can also accept connections
42+
$client2 = stream_socket_client("tcp://127.0.0.1:$port");
43+
$accepted2_on_srv1 = @stream_socket_accept($server1, 0.1);
44+
$accepted2_on_srv2 = @stream_socket_accept($server2, 0.1);
45+
46+
if ($accepted2_on_srv1 || $accepted2_on_srv2) {
47+
echo "SO_REUSEPORT enabled: Connections accepted\n";
48+
}
49+
50+
if ($accepted2_on_srv1) fclose($accepted2_on_srv1);
51+
if ($accepted2_on_srv2) fclose($accepted2_on_srv2);
52+
if ($client2) fclose($client2);
53+
54+
fclose($server2);
55+
} else {
56+
echo "SO_REUSEPORT enabled: Multiple servers failed\n";
57+
}
58+
59+
fclose($accepted1);
60+
fclose($client1);
61+
fclose($server1);
62+
63+
// SO_REUSEPORT disabled (default) - should NOT allow multiple servers
64+
$server3 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr,
65+
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
66+
67+
if (!$server3) {
68+
die('Unable to create server3');
69+
}
70+
71+
$addr = stream_socket_get_name($server3, false);
72+
$port = (int)substr(strrchr($addr, ':'), 1);
73+
74+
$client3 = stream_socket_client("tcp://127.0.0.1:$port");
75+
$accepted3 = stream_socket_accept($server3, 1);
76+
77+
fwrite($client3, "test");
78+
fread($accepted3, 4);
79+
fwrite($accepted3, "response");
80+
fread($client3, 8);
81+
82+
// Try to bind second server WITHOUT SO_REUSEPORT (while server3 still active)
83+
$server4 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr,
84+
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
85+
86+
if ($server4) {
87+
echo "SO_REUSEPORT disabled: Multiple servers succeeded\n";
88+
fclose($server4);
89+
} else {
90+
echo "SO_REUSEPORT disabled: Multiple servers failed\n";
91+
}
92+
93+
fclose($accepted3);
94+
fclose($client3);
95+
fclose($server3);
96+
97+
// SO_REUSEPORT explicitly disabled
98+
$context3 = stream_context_create(['socket' => ['so_reuseport' => false]]);
99+
$server5 = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr,
100+
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context3);
101+
102+
if (!$server5) {
103+
die('Unable to create server5');
104+
}
105+
106+
$addr = stream_socket_get_name($server5, false);
107+
$port = (int)substr(strrchr($addr, ':'), 1);
108+
109+
$client5 = stream_socket_client("tcp://127.0.0.1:$port");
110+
$accepted5 = stream_socket_accept($server5, 1);
111+
112+
fwrite($client5, "test");
113+
fread($accepted5, 4);
114+
fwrite($accepted5, "response");
115+
fread($client5, 8);
116+
117+
$context4 = stream_context_create(['socket' => ['so_reuseport' => false]]);
118+
$server6 = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr,
119+
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context4);
120+
121+
if ($server6) {
122+
echo "SO_REUSEPORT explicitly disabled: Multiple servers succeeded\n";
123+
fclose($server6);
124+
} else {
125+
echo "SO_REUSEPORT explicitly disabled: Multiple servers failed\n";
126+
}
127+
128+
fclose($accepted5);
129+
fclose($client5);
130+
fclose($server5);
131+
?>
132+
--EXPECT--
133+
SO_REUSEPORT enabled: Multiple servers succeeded
134+
SO_REUSEPORT enabled: Connections accepted
135+
SO_REUSEPORT disabled: Multiple servers failed
136+
SO_REUSEPORT explicitly disabled: Multiple servers failed

0 commit comments

Comments
 (0)