8000 Improve error messages for failed connections to include errno by clue · Pull Request #271 · reactphp/socket · GitHub
[go: up one dir, main page]

Skip to content

Improve error messages for failed connections to include errno #271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Me 8000 rged
merged 7 commits into from
Sep 11, 2021
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ $socket->on('error', function (Exception $e) {
Note that this is not a fatal error event, i.e. the server keeps listening for
new connections even after this event.


#### getAddress()

The `getAddress(): ?string` method can be used to
Expand Down
9 changes: 8 additions & 1 deletion examples/01-echo-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// You can also use systemd socket activation and listen on an inherited file descriptor:
//
// $ systemd-socket-activate -l 8000 php examples/01-echo-server.php php://fd/3
// $ telnet localhost 8000

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

Expand All @@ -31,8 +32,14 @@
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) {
echo '[' . $connection->getRemoteAddress() . ' connected]' . PHP_EOL;
$connection->pipe($connection);

$connection->on('close', function () use ($connection) {
echo '[' . $connection->getRemoteAddress() . ' disconnected]' . PHP_EOL;
});
});

$socket->on('error', 'printf');
$socket->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

echo 'Listening on ' . $socket->getAddress() . PHP_EOL;
17 changes: 13 additions & 4 deletions examples/02-chat-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// You can also use systemd socket activation and listen on an inherited file descriptor:
//
// $ systemd-socket-activate -l 8000 php examples/02-chat-server.php php://fd/3
// $ telnet localhost 8000

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

Expand All @@ -30,9 +31,11 @@

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

$socket->on('connection', function (React\Socket\ConnectionInterface $client) use ($socket) {
$socket->on('connection', function (React\Socket\ConnectionInterface $connection) use ($socket) {
echo '[' . $connection->getRemoteAddress() . ' connected]' . PHP_EOL;

// whenever a new message comes in
$client->on('data', function ($data) use ($client, $socket) {
$connection->on('data', function ($data) use ($connection, $socket) {
// remove any non-word characters (just for the demo)
$data = trim(preg_replace('/[^\w\d \.\,\-\!\?]/u', '', $data));

Expand All @@ -42,13 +45,19 @@
}

8000 // prefix with client IP and broadcast to all connected clients
$data = trim(parse_url($client->getRemoteAddress(), PHP_URL_HOST), '[]') . ': ' . $data . PHP_EOL;
$data = trim(parse_url($connection->getRemoteAddress(), PHP_URL_HOST), '[]') . ': ' . $data . PHP_EOL;
foreach ($socket->getConnections() as $connection) {
$connection->write($data);
}
});

$connection->on('close', function () use ($connection) {
echo '[' . $connection->getRemoteAddress() . ' disconnected]' . PHP_EOL;
});
});

$socket->on('error', 'printf');
$socket->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

echo 'Listening on ' . $socket->getAddress() . PHP_EOL;
17 changes: 14 additions & 3 deletions examples/03-http-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
// $ php examples/03-http-server.php 127.0.0.1:8000
// $ curl -v http://localhost:8000/
// $ ab -n1000 -c10 http://localhost:8000/
// $ docker run -it --rm --net=host jordi/ab ab -n1000 -c10 http://localhost:8000/
// $ docker run -it --rm --net=host jordi/ab -n1000 -c10 http://localhost:8000/
//
// You can also run a secure HTTPS echo server like this:
//
// $ php examples/03-http-server.php tls://127.0.0.1:8000 examples/localhost.pem
// $ curl -v --insecure https://localhost:8000/
// $ ab -n1000 -c10 https://localhost:8000/
// $ docker run -it --rm --net=host jordi/ab ab -n1000 -c10 https://localhost:8000/
// $ docker run -it --rm --net=host jordi/ab -n1000 -c10 https://localhost:8000/
//
// You can also run a Unix domain socket (UDS) server like this:
//
Expand All @@ -32,6 +32,9 @@
// You can also use systemd socket activation and listen on an inherited file descriptor:
//
// $ systemd-socket-activate -l 8000 php examples/03-http-server.php php://fd/3
// $ curl -v --insecure https://localhost:8000/
// $ ab -n1000 -c10 https://localhost:8000/
// $ docker run -it --rm --net=host jordi/ab -n1000 -c10 https://localhost:8000/

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

Expand All @@ -42,12 +45,20 @@
));

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

$connection->once('data', function () use ($connection) {
$body = "<html><h1>Hello world!</h1></html>\r\n";
$connection->end("HTTP/1.1 200 OK\r\nContent-Length: " . strlen($body) . "\r\nConnection: close\r\n\r\n" . $body);
});

$connection->on('close', function () use ($connection) {
echo '[' . $connection->getRemoteAddress() . ' disconnected]' . PHP_EOL;
});
});

$socket->on('error', 'printf');
$socket->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

echo 'Listening on ' . strtr($socket->getAddress(), array('tcp:' => 'http:', 'tls:' => 'https:')) . PHP_EOL;
15 changes: 12 additions & 3 deletions examples/91-benchmark-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
// $ php examples/91-benchmark-server.php unix:///tmp/server.sock
// $ nc -N -U /tmp/server.sock
// $ dd if=/dev/zero bs=1M count=1000 | nc -N -U /tmp/server.sock
//
// You can also use systemd socket activation and listen on an inherited file descriptor:
//
// $ systemd-socket-activate -l 8000 php examples/91-benchmark-server.php php://fd/3
// $ telnet localhost 8000
// $ echo hello world | nc -N localhost 8000
// $ dd if=/dev/zero bs=1M count=1000 | nc -N localhost 8000

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

Expand All @@ -31,7 +38,7 @@
));

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

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

$socket->on('error', 'printf');
$socket->on('error', function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

echo 'Listening on ' . $socket->getAddress() . PHP_EOL;
3 changes: 2 additions & 1 deletion src/Connector.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ public function connect($uri)

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

Expand Down
10 changes: 8 additions & 2 deletions src/DnsConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ public function connect($uri)
}

if (!$parts || !isset($parts['host'])) {
return Promise\reject(new \InvalidArgumentException('Given URI "' . $original . '" is invalid'));
return Promise\reject(new \InvalidArgumentException(
'Given URI "' . $original . '" is invalid (EINVAL)',
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
));
}

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

// (try to) cancel pending DNS lookup / connection attempt
Expand Down
20 changes: 16 additions & 4 deletions src/FdServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ public function __construct($fd, LoopInterface $loop = null)
$fd = (int) $m[1];
}
if (!\is_int($fd) || $fd < 0 || $fd >= \PHP_INT_MAX) {
throw new \InvalidArgumentException('Invalid FD number given');
throw new \InvalidArgumentException(
'Invalid FD number given (EINVAL)',
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
);
}

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

throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr, $errno);
throw new \RuntimeException(
'Failed to listen on FD ' . $fd . ': ' . $errstr . SocketServer::errconst($errno),
$errno
);
}

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

throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr, $errno);
throw new \RuntimeException(
'Failed to listen on FD ' . $fd . ': ' . $errstr . ' (ENOTSOCK)',
$errno
);
}

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

throw new \RuntimeException('Failed to listen on FD ' . $fd . ': ' . $errstr, $errno);
throw new \RuntimeException(
'Failed to listen on FD ' . $fd . ': ' . $errstr . ' (EISCONN)',
$errno
);
}

// Assume this is a Unix domain socket (UDS) when its listening address doesn't parse as a valid URL with a port.
Expand Down
17 changes: 14 additions & 3 deletions src/HappyEyeBallsConnectionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ public function connect()
return $deferred->promise();
})->then($lookupResolve(Message::TYPE_A));
}, function ($_, $reject) use ($that, &$timer) {
$reject(new \RuntimeException('Connection to ' . $that->uri . ' cancelled' . (!$that->connectionPromises ? ' during DNS lookup' : '')));
$reject(new \RuntimeException(
'Connection to ' . $that->uri . ' cancelled F987 9; . (!$that->connectionPromises ? ' during DNS lookup' : '') . ' (ECONNABORTED)',
\defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103
));
$_ = $reject = null;

$that->cleanUp();
Expand Down Expand Up @@ -143,7 +146,11 @@ public function resolve($type, $reject)
}

if ($that->hasBeenResolved() && $that->ipsCount === 0) {
$reject(new \RuntimeException($that->error()));
$reject(new \RuntimeException(
$that->error(),
0,
$e
));
}

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

$reject(new \RuntimeException($that->error()));
$reject(new \RuntimeException(
$that->error(),
$e->getCode(),
$e
));
}
});

Expand Down
5 changes: 4 additions & 1 deletion src/HappyEyeBallsConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ public function connect($uri)
}

if (!$parts || !isset($parts['host'])) {
return Promise\reject(new \InvalidArgumentException('Given URI "' . $original . '" is invalid'));
return Promise\reject(new \InvalidArgumentException(
'Given URI "' . $original . '" is invalid (EINVAL)',
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
));
}

$host = \trim($parts['host'], '[]');
Expand Down
10 changes: 8 additions & 2 deletions src/SecureConnector.php
< 859A td id="diff-4006337f1a7aa55217c1021d9eba2c379dd88b0593cddf1f3392b54bf87cb29bL37" data-line-number="37" class="blob-num blob-num-deletion js-linkable-line-number">
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ public function connect($uri)

$parts = \parse_url($uri);
if (!$parts || !isset($parts['scheme']) || $parts['scheme'] !== 'tls') {
return Promise\reject(new \InvalidArgumentException('Given URI "' . $uri . '" is invalid'));
return Promise\reject(new \InvalidArgumentException(
'Given URI "' . $uri . '" is invalid (EINVAL)',
\defined('SOCKET_EINVAL') ? \SOCKET_EINVAL : 22
));
}

$context = $this->context;
Expand Down Expand Up @@ -105,7 +108,10 @@ function ($resolve, $reject) use ($promise) {
},
function ($_, $reject) use (&$promise, $uri, &$connected) {
if ($connected) {
$reject(new \RuntimeException('Connection to ' . $uri . ' cancelled during TLS handshake'));
$reject(new \RuntimeException(
'Connection to ' . $uri . ' cancelled during TLS handshake (ECONNABORTED)',
\defined('SOCKET_ECONNABORTED') ? \SOCKET_ECONNABORTED : 103
));
}

$promise->cancel();
Expand Down
Loading
0