Skip to content

Commit a992631

Browse files
authored
Merge pull request #271 from clue-labs/errno
2 parents dd77705 + 95bce45 commit a992631

35 files changed

+521
-136
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ $socket->on('error', function (Exception $e) {
238238
Note that this is not a fatal error event, i.e. the server keeps listening for
239239
new connections even after this event.
240240

241-
242241
#### getAddress()
243242

244243
The `getAddress(): ?string` method can be used to

examples/01-echo-server.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// You can also use systemd socket activation and listen on an inherited file descriptor:
2020
//
2121
// $ systemd-socket-activate -l 8000 php examples/01-echo-server.php php://fd/3
22+
// $ telnet localhost 8000
2223

2324
require __DIR__ . '/../vendor/autoload.php';
2425

@@ -31,8 +32,14 @@
3132
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
3233
echo '[' . $connection->getRemoteAddress() . ' connected]' . PHP_EOL;
3334
$connection->pipe($connection);
35+
36+
$connection->on('close', function () use ($connection) {
37+
echo '[' . $connection->getRemoteAddress() . ' disconnected]' . PHP_EOL;
38+
});
3439
});
3540

36-
$socket->on('error', 'printf');
41+
$socket->on('error', function (Exception $e) {
42+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
43+
});
3744

3845
echo 'Listening on ' . $socket->getAddress() . PHP_EOL;

examples/02-chat-server.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// You can also use systemd socket activation and listen on an inherited file descriptor:
2020
//
2121
// $ systemd-socket-activate -l 8000 php examples/02-chat-server.php php://fd/3
22+
// $ telnet localhost 8000
2223

2324
require __DIR__ . '/../vendor/autoload.php';
2425

@@ -30,9 +31,11 @@
3031

3132
$socket = new React\Socket\LimitingServer($socket, null);
3233

33-
$socket->on('connection', function (React\Socket\ConnectionInterface $client) use ($socket) {
34+
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) use ($socket) {
35+
echo '[' . $connection->getRemoteAddress() . ' connected]' . PHP_EOL;
36+
3437
// whenever a new message comes in
35-
$client->on('data', function ($data) use ($client, $socket) {
38+
$connection->on('data', function ($data) use ($connection, $socket) {
3639
// remove any non-word characters (just for the demo)
3740
$data = trim(preg_replace('/[^\w\d \.\,\-\!\?]/u', '', $data));
3841

@@ -42,13 +45,19 @@
4245
}
4346

4447
// prefix with client IP and broadcast to all connected clients
45-
$data = trim(parse_url($client->getRemoteAddress(), PHP_URL_HOST), '[]') . ': ' . $data . PHP_EOL;
48+
$data = trim(parse_url($connection->getRemoteAddress(), PHP_URL_HOST), '[]') . ': ' . $data . PHP_EOL;
4649
foreach ($socket->getConnections() as $connection) {
4750
$connection->write($data);
4851
}
4952
});
53+
54+
$connection->on('close', function () use ($connection) {
55+
echo '[' . $connection->getRemoteAddress() . ' disconnected]' . PHP_EOL;
56+
});
5057
});
5158

52-
$socket->on('error', 'printf');
59+
$socket->on('error', function (Exception $e) {
60+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
61+
});
5362

5463
echo 'Listening on ' . $socket->getAddress() . PHP_EOL;

examples/03-http-server.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
// $ php examples/03-http-server.php 127.0.0.1:8000
1616
// $ curl -v http://localhost:8000/
1717
// $ ab -n1000 -c10 http://localhost:8000/
18-
// $ docker run -it --rm --net=host jordi/ab ab -n1000 -c10 http://localhost:8000/
18+
// $ docker run -it --rm --net=host jordi/ab -n1000 -c10 http://localhost:8000/
1919
//
2020
// You can also run a secure HTTPS echo server like this:
2121
//
2222
// $ php examples/03-http-server.php tls://127.0.0.1:8000 examples/localhost.pem
2323
// $ curl -v --insecure https://localhost:8000/
2424
// $ ab -n1000 -c10 https://localhost:8000/
25-
// $ docker run -it --rm --net=host jordi/ab ab -n1000 -c10 https://localhost:8000/
25+
// $ docker run -it --rm --net=host jordi/ab -n1000 -c10 https://localhost:8000/
2626
//
2727
// You can also run a Unix domain socket (UDS) server like this:
2828
//
@@ -32,6 +32,9 @@
3232
// You can also use systemd socket activation and listen on an inherited file descriptor:
3333
//
3434
// $ systemd-socket-activate -l 8000 php examples/03-http-server.php php://fd/3
35+
// $ curl -v --insecure https://localhost:8000/
36+
// $ ab -n1000 -c10 https://localhost:8000/
37+
// $ docker run -it --rm --net=host jordi/ab -n1000 -c10 https://localhost:8000/
3538

3639
require __DIR__ . '/../vendor/autoload.php';
3740

@@ -42,12 +45,20 @@
4245
));
4346

4447
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
48+
echo '[' . $connection->getRemoteAddress() . ' connected]' . PHP_EOL;
49+
4550
$connection->once('data', function () use ($connection) {
4651
$body = "<html><h1>Hello world!</h1></html>\r\n";
4752
$connection->end("HTTP/1.1 200 OK\r\nContent-Length: " . strlen($body) . "\r\nConnection: close\r\n\r\n" . $body);
4853
});
54+
55+
$connection->on('close', function () use ($connection) {
56+
echo '[' . $connection->getRemoteAddress() . ' disconnected]' . PHP_EOL;
57+
});
4958
});
5059

51-
$socket->on('error', 'printf');
60+
$socket->on('error', function (Exception $e) {
61+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
62+
});
5263

5364
echo 'Listening on ' . strtr($socket->getAddress(), array('tcp:' => 'http:', 'tls:' => 'https:')) . PHP_EOL;

examples/91-benchmark-server.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
// $ php examples/91-benchmark-server.php unix:///tmp/server.sock
2222
// $ nc -N -U /tmp/server.sock
2323
// $ dd if=/dev/zero bs=1M count=1000 | nc -N -U /tmp/server.sock
24+
//
25+
// You can also use systemd socket activation and listen on an inherited file descriptor:
26+
//
27+
// $ systemd-socket-activate -l 8000 php examples/91-benchmark-server.php php://fd/3
28+
// $ telnet localhost 8000
29+
// $ echo hello world | nc -N localhost 8000
30+
// $ dd if=/dev/zero bs=1M count=1000 | nc -N localhost 8000
2431

2532
require __DIR__ . '/../vendor/autoload.php';
2633

@@ -31,7 +38,7 @@
3138
));
3239

3340
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
34-
echo '[connected]' . PHP_EOL;
41+
echo '[' . $connection->getRemoteAddress() . ' connected]' . PHP_EOL;
3542

3643
// count the number of bytes received from this connection
3744
$bytes = 0;
@@ -43,10 +50,12 @@
4350
$t = microtime(true);
4451
$connection->on('close', function () use ($connection, $t, &$bytes) {
4552
$t = microtime(true) - $t;
46-
echo '[disconnected after receiving ' . $bytes . ' bytes in ' . round($t, 3) . 's => ' . round($bytes / $t / 1024 / 1024, 1) . ' MiB/s]' . PHP_EOL;
53+
echo '[' . $connection->getRemoteAddress() . ' disconnected after receiving ' . $bytes . ' bytes in ' . round($t, 3) . 's => ' . round($bytes / $t / 1024 / 1024, 1) . ' MiB/s]' . PHP_EOL;
4754
});
4855
});
4956

50-
$socket->on('error', 'printf');
57+
$socket->on('error', function (Exception $e) {
58+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
59+
});
5160

5261
echo 'Listening on ' . $socket->getAddress() . PHP_EOL;

src/Connector.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ public function connect($uri)
169169

170170
if (!isset($this->connectors[$scheme])) {
171171
return \React\Promise\reject(new \RuntimeException(
172-
'No connector available for URI scheme "' . $scheme . '"'
172+
'No connector available for URI scheme "' . $scheme . '" (EINVAL)',
173+
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
173174
));
174175
}
175176

src/DnsConnector.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ public function connect($uri)
2929
}
3030

3131
if (!$parts || !isset($parts['host'])) {
32-
return Promise\reject(new \InvalidArgumentException('Given URI "' . $original . '" is invalid'));
32+
return Promise\reject(new \InvalidArgumentException(
33+
'Given URI "' . $original . '" is invalid (EINVAL)',
34+
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
35+
));
3336
}
3437

3538
$host = \trim($parts['host'], '[]');
@@ -91,7 +94,10 @@ function ($_, $reject) use (&$promise, &$resolved, $uri) {
9194
// cancellation should reject connection attempt
9295
// reject DNS resolution with custom reason, otherwise rely on connection cancellation below
9396
if ($resolved === null) {
94-
$reject(new \RuntimeException('Connection to ' . $uri . ' cancelled during DNS lookup'));
97+
$reject(new \RuntimeException(
98+
'Connection to ' . $uri . ' cancelled during DNS lookup (ECONNABORTED)',
99+
\defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103
100+
));
95101
}
96102

97103
// (try to) cancel pending DNS lookup / connection attempt

src/FdServer.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ public function __construct($fd, LoopInterface $loop = null)
8181
$fd = (int) $m[1];
8282
}
8383
if (!\is_int($fd) || $fd < 0 || $fd >= \PHP_INT_MAX) {
84-
throw new \InvalidArgumentException('Invalid FD number given');
84+
throw new \InvalidArgumentException(
85+
'Invalid FD number given (EINVAL)',
86+
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
87+
);
8588
}
8689

8790
$this->loop = $loop ?: Loop::get();
@@ -95,7 +98,10 @@ public function __construct($fd, LoopInterface $loop = null)
9598
$errno = isset($m[1]) ? (int) $m[1] : 0;
9699
$errstr = isset($m[2]) ? $m[2] : $error['message'];
97100

98-
throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr, $errno);
101+
throw new \RuntimeException(
102+
'Failed to listen on FD ' . $fd . ': ' . $errstr . SocketServer::errconst($errno),
103+
$errno
104+
);
99105
}
100106

101107
$meta = \stream_get_meta_data($this->master);
@@ -105,7 +111,10 @@ public function __construct($fd, LoopInterface $loop = null)
105111
$errno = \defined('SOCKET_ENOTSOCK') ? \SOCKET_ENOTSOCK : 88;
106112
$errstr = \function_exists('socket_strerror') ? \socket_strerror($errno) : 'Not a socket';
107113

108-
throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr, $errno);
114+
throw new \RuntimeException(
115+
'Failed to listen on FD ' . $fd . ': ' . $errstr . ' (ENOTSOCK)',
116+
$errno
117+
);
109118
}
110119

111120
// Socket should not have a peer address if this is a listening socket.
@@ -116,7 +125,10 @@ public function __construct($fd, LoopInterface $loop = null)
116125
$errno = \defined('SOCKET_EISCONN') ? \SOCKET_EISCONN : 106;
117126
$errstr = \function_exists('socket_strerror') ? \socket_strerror($errno) : 'Socket is connected';
118127

119-
throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr, $errno);
128+
throw new \RuntimeException(
129+
'Failed to listen on FD ' . $fd . ': ' . $errstr . ' (EISCONN)',
130+
$errno
131+
);
120132
}
121133

122134
// Assume this is a Unix domain socket (UDS) when its listening address doesn't parse as a valid URL with a port.

src/HappyEyeBallsConnectionBuilder.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ public function connect()
103103
return $deferred->promise();
104104
})->then($lookupResolve(Message::TYPE_A));
105105
}, function ($_, $reject) use ($that, &$timer) {
106-
$reject(new \RuntimeException('Connection to ' . $that->uri . ' cancelled' . (!$that->connectionPromises ? ' during DNS lookup' : '')));
106+
$reject(new \RuntimeException(
107+
'Connection to ' . $that->uri . ' cancelled' . (!$that->connectionPromises ? ' during DNS lookup' : '') . ' (ECONNABORTED)',
108+
\defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103
109+
));
107110
$_ = $reject = null;
108111

109112
$that->cleanUp();
@@ -143,7 +146,11 @@ public function resolve($type, $reject)
143146
}
144147

145148
if ($that->hasBeenResolved() && $that->ipsCount === 0) {
146-
$reject(new \RuntimeException($that->error()));
149+
$reject(new \RuntimeException(
150+
$that->error(),
151+
0,
152+
$e
153+
));
147154
}
148155

149156
// Exception already handled above, so don't throw an unhandled rejection here
@@ -201,7 +208,11 @@ public function check($resolve, $reject)
201208
if ($that->ipsCount === $that->failureCount) {
202209
$that->cleanUp();
203210

204-
$reject(new \RuntimeException($that->error()));
211+
$reject(new \RuntimeException(
212+
$that->error(),
213+
$e->getCode(),
214+
$e
215+
));
205216
}
206217
});
207218

src/HappyEyeBallsConnector.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ public function connect($uri)
4141
}
4242

4343
if (!$parts || !isset($parts['host'])) {
44-
return Promise\reject(new \InvalidArgumentException('Given URI "' . $original . '" is invalid'));
44+
return Promise\reject(new \InvalidArgumentException(
45+
'Given URI "' . $original . '" is invalid (EINVAL)',
46+
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
47+
));
4548
}
4649

4750
$host = \trim($parts['host'], '[]');

src/SecureConnector.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ public function connect($uri)
3434

3535
$parts = \parse_url($uri);
3636
if (!$parts || !isset($parts['scheme']) || $parts['scheme'] !== 'tls') {
37-
return Promise\reject(new \InvalidArgumentException('Given URI "' . $uri . '" is invalid'));
37+
return Promise\reject(new \InvalidArgumentException(
38+
'Given URI "' . $uri . '" is invalid (EINVAL)',
39+
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
40+
));
3841
}
3942

4043
$context = $this->context;
@@ -105,7 +108,10 @@ function ($resolve, $reject) use ($promise) {
105108
},
106109
function ($_, $reject) use (&$promise, $uri, &$connected) {
107110
if ($connected) {
108-
$reject(new \RuntimeException('Connection to ' . $uri . ' cancelled during TLS handshake'));
111+
$reject(new \RuntimeException(
112+
'Connection to ' . $uri . ' cancelled during TLS handshake (ECONNABORTED)',
113+
\defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103
114+
));
109115
}
110116

111117
$promise->cancel();

0 commit comments

Comments
 (0)