From ea73bc39887753b609e7f521ff8bfca215e49d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 28 Apr 2017 15:56:01 +0200 Subject: [PATCH] All addresses are now URIs that include the URI scheme --- README.md | 31 ++++++++++++++++++++-------- examples/01-echo.php | 2 +- examples/02-chat-server.php | 2 +- src/Connection.php | 12 ++++++++++- src/ConnectionInterface.php | 21 ++++++++++++------- src/SecureServer.php | 2 +- src/ServerInterface.php | 15 +++++++++----- src/StreamEncryption.php | 10 ++++----- src/TcpServer.php | 2 +- tests/FunctionalSecureServerTest.php | 4 ++-- tests/LimitingServerTest.php | 10 ++++----- tests/ServerTest.php | 2 +- tests/TcpConnectorTest.php | 12 +++++------ 13 files changed, 80 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index f78683e2..996e0ee9 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ For more details, see the #### getRemoteAddress() The `getRemoteAddress(): ?string` method returns the full remote address -(client IP and port) where this connection has been established with. +(URI) where this connection has been established with. ```php $address = $connection->getRemoteAddress(); @@ -148,20 +148,24 @@ echo 'Connection with ' . $address . PHP_EOL; If the remote address can not be determined or is unknown at this time (such as after the connection has been closed), it MAY return a `NULL` value instead. -Otherwise, it will return the full remote address as a string value. +Otherwise, it will return the full address (URI) as a string value, such +as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. +Note that individual URI components are application specific and depend +on the underlying transport protocol. + If this is a TCP/IP based connection and you only want the remote IP, you may use something like this: ```php $address = $connection->getRemoteAddress(); -$ip = trim(parse_url('tcp://' . $address, PHP_URL_HOST), '[]'); +$ip = trim(parse_url($address, PHP_URL_HOST), '[]'); echo 'Connection with ' . $ip . PHP_EOL; ``` #### getLocalAddress() The `getLocalAddress(): ?string` method returns the full local address -(client IP and port) where this connection has been established with. +(URI) where this connection has been established with. ```php $address = $connection->getLocalAddress(); @@ -171,10 +175,14 @@ echo 'Connection with ' . $address . PHP_EOL; If the local address can not be determined or is unknown at this time (such as after the connection has been closed), it MAY return a `NULL` value instead. -Otherwise, it will return the full local address as a string value. +Otherwise, it will return the full address (URI) as a string value, such +as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. +Note that individual URI components are application specific and depend +on the underlying transport protocol. This method complements the [`getRemoteAddress()`](#getremoteaddress) method, so they should not be confused. + If your `TcpServer` instance is listening on multiple interfaces (e.g. using the address `0.0.0.0`), you can use this method to find out which interface actually accepted this connection (such as a public or local interface). @@ -233,22 +241,27 @@ new connections even after this event. #### getAddress() The `getAddress(): ?string` method can be used to -return the full address (IP and port) this server is currently listening on. +return the full address (URI) this server is currently listening on. ```php $address = $server->getAddress(); echo 'Server listening on ' . $address . PHP_EOL; ``` -It will return the full address (IP and port) or `NULL` if it is unknown -(not applicable to this server socket or already closed). +If the address can not be determined or is unknown at this time (such as +after the socket has been closed), it MAY return a `NULL` value instead. + +Otherwise, it will return the full address (URI) as a string value, such +as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. +Note that individual URI components are application specific and depend +on the underlying transport protocol. If this is a TCP/IP based server and you only want the local port, you may use something like this: ```php $address = $server->getAddress(); -$port = parse_url('tcp://' . $address, PHP_URL_PORT); +$port = parse_url($address, PHP_URL_PORT); echo 'Server listening on port ' . $port . PHP_EOL; ``` diff --git a/examples/01-echo.php b/examples/01-echo.php index 96ec74d9..18bf9d3b 100644 --- a/examples/01-echo.php +++ b/examples/01-echo.php @@ -26,7 +26,7 @@ )); $server->on('connection', function (ConnectionInterface $conn) { - echo '[connected]' . PHP_EOL; + echo '[' . $conn->getRemoteAddress() . ' connected]' . PHP_EOL; $conn->pipe($conn); }); diff --git a/examples/02-chat-server.php b/examples/02-chat-server.php index a3bc59cf..43d0c576 100644 --- a/examples/02-chat-server.php +++ b/examples/02-chat-server.php @@ -40,7 +40,7 @@ } // prefix with client IP and broadcast to all connected clients - $data = $client->getRemoteAddress() . ': ' . $data . PHP_EOL; + $data = trim(parse_url($client->getRemoteAddress(), PHP_URL_HOST), '[]') . ': ' . $data . PHP_EOL; foreach ($server->getConnections() as $connection) { $connection->write($data); } diff --git a/src/Connection.php b/src/Connection.php index 8d68aa9b..ad22025c 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -14,6 +14,16 @@ */ class Connection extends Stream implements ConnectionInterface { + /** + * Internal flag whether encryption has been enabled on this connection + * + * Mostly used by internal StreamEncryption so that connection returns + * `tls://` scheme for encrypted connections instead of `tcp://`. + * + * @internal + */ + public $encryptionEnabled = false; + public function handleClose() { if (!is_resource($this->stream)) { @@ -52,6 +62,6 @@ private function parseAddress($address) $address = '[' . substr($address, 0, $pos) . ']:' . $port; } - return $address; + return ($this->encryptionEnabled ? 'tls' : 'tcp') . '://' . $address; } } diff --git a/src/ConnectionInterface.php b/src/ConnectionInterface.php index e3cc1701..45848bca 100644 --- a/src/ConnectionInterface.php +++ b/src/ConnectionInterface.php @@ -55,7 +55,7 @@ interface ConnectionInterface extends DuplexStreamInterface { /** - * Returns the remote address (client IP and port) where this connection has been established with + * Returns the full remote address (URI) where this connection has been established with * * ```php * $address = $connection->getRemoteAddress(); @@ -65,22 +65,26 @@ interface ConnectionInterface extends DuplexStreamInterface * If the remote address can not be determined or is unknown at this time (such as * after the connection has been closed), it MAY return a `NULL` value instead. * - * Otherwise, it will return the full remote address as a string value. + * Otherwise, it will return the full address (URI) as a string value, such + * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. + * Note that individual URI components are application specific and depend + * on the underlying transport protocol. + * * If this is a TCP/IP based connection and you only want the remote IP, you may * use something like this: * * ```php * $address = $connection->getRemoteAddress(); - * $ip = trim(parse_url('tcp://' . $address, PHP_URL_HOST), '[]'); + * $ip = trim(parse_url($address, PHP_URL_HOST), '[]'); * echo 'Connection with ' . $ip . PHP_EOL; * ``` * - * @return ?string remote address (client IP and port) or null if unknown + * @return ?string remote address (URI) or null if unknown */ public function getRemoteAddress(); /** - * Returns the full local address (client IP and port) where this connection has been established with + * Returns the full local address (full URI with scheme, IP and port) where this connection has been established with * * ```php * $address = $connection->getLocalAddress(); @@ -90,7 +94,10 @@ public function getRemoteAddress(); * If the local address can not be determined or is unknown at this time (such as * after the connection has been closed), it MAY return a `NULL` value instead. * - * Otherwise, it will return the full local address as a string value. + * Otherwise, it will return the full address (URI) as a string value, such + * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. + * Note that individual URI components are application specific and depend + * on the underlying transport protocol. * * This method complements the [`getRemoteAddress()`](#getremoteaddress) method, * so they should not be confused. @@ -103,7 +110,7 @@ public function getRemoteAddress(); * you can use this method to find out which interface was actually * used for this connection. * - * @return ?string local address (client IP and port) or null if unknown + * @return ?string local address (URI) or null if unknown * @see self::getRemoteAddress() */ public function getLocalAddress(); diff --git a/src/SecureServer.php b/src/SecureServer.php index 3c5c32e7..64cbeda9 100644 --- a/src/SecureServer.php +++ b/src/SecureServer.php @@ -142,7 +142,7 @@ public function __construct(ServerInterface $tcp, LoopInterface $loop, array $co public function getAddress() { - return $this->tcp->getAddress(); + return str_replace('tcp://' , 'tls://', $this->tcp->getAddress()); } public function pause() diff --git a/src/ServerInterface.php b/src/ServerInterface.php index 4d7d0beb..53196783 100644 --- a/src/ServerInterface.php +++ b/src/ServerInterface.php @@ -49,26 +49,31 @@ interface ServerInterface extends EventEmitterInterface { /** - * Returns the full address (IP and port) this server is currently listening on + * Returns the full address (URI) this server is currently listening on * * ```php * $address = $server->getAddress(); * echo 'Server listening on ' . $address . PHP_EOL; * ``` * - * It will return the full address (IP and port) or `NULL` if it is unknown - * (not applicable to this server socket or already closed). + * If the address can not be determined or is unknown at this time (such as + * after the socket has been closed), it MAY return a `NULL` value instead. + * + * Otherwise, it will return the full address (URI) as a string value, such + * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. + * Note that individual URI components are application specific and depend + * on the underlying transport protocol. * * If this is a TCP/IP based server and you only want the local port, you may * use something like this: * * ```php * $address = $server->getAddress(); - * $port = parse_url('tcp://' . $address, PHP_URL_PORT); + * $port = parse_url($address, PHP_URL_PORT); * echo 'Server listening on port ' . $port . PHP_EOL; * ``` * - * @return ?string the full listening address (IP and port) or NULL if it is unknown (not applicable to this server socket or already closed) + * @return ?string the full listening address (URI) or NULL if it is unknown (not applicable to this server socket or already closed) */ public function getAddress(); diff --git a/src/StreamEncryption.php b/src/StreamEncryption.php index ff804699..e73d9416 100644 --- a/src/StreamEncryption.php +++ b/src/StreamEncryption.php @@ -3,7 +3,6 @@ namespace React\Socket; use React\Promise\Deferred; -use React\Stream\Stream; use React\EventLoop\LoopInterface; use UnexpectedValueException; @@ -65,17 +64,17 @@ public function __construct(LoopInterface $loop, $server = true) } } - public function enable(Stream $stream) + public function enable(Connection $stream) { return $this->toggle($stream, true); } - public function disable(Stream $stream) + public function disable(Connection $stream) { return $this->toggle($stream, false); } - public function toggle(Stream $stream, $toggle) + public function toggle(Connection $stream, $toggle) { // pause actual stream instance to continue operation on raw stream socket $stream->pause(); @@ -104,13 +103,14 @@ public function toggle(Stream $stream, $toggle) $wrap = $this->wrapSecure && $toggle; $loop = $this->loop; - return $deferred->promise()->then(function () use ($stream, $socket, $wrap, $loop) { + return $deferred->promise()->then(function () use ($stream, $socket, $wrap, $loop, $toggle) { $loop->removeReadStream($socket); if ($wrap) { $stream->bufferSize = null; } + $stream->encryptionEnabled = $toggle; $stream->resume(); return $stream; diff --git a/src/TcpServer.php b/src/TcpServer.php index 576b450e..db01904e 100644 --- a/src/TcpServer.php +++ b/src/TcpServer.php @@ -183,7 +183,7 @@ public function getAddress() $address = '[' . substr($address, 0, $pos) . ']:' . $port; } - return $address; + return 'tcp://' . $address; } public function pause() diff --git a/tests/FunctionalSecureServerTest.php b/tests/FunctionalSecureServerTest.php index cfac1722..b591cbf9 100644 --- a/tests/FunctionalSecureServerTest.php +++ b/tests/FunctionalSecureServerTest.php @@ -326,7 +326,7 @@ public function testEmitsNothingIfConnectionIsIdle() $server->on('error', $this->expectCallableNever()); $connector = new TcpConnector($loop); - $promise = $connector->connect($server->getAddress()); + $promise = $connector->connect(str_replace('tls://', '', $server->getAddress())); $promise->then($this->expectCallableOnce()); Block\sleep(self::TIMEOUT, $loop); @@ -344,7 +344,7 @@ public function testEmitsErrorIfConnectionIsNotSecureHandshake() $server->on('error', $this->expectCallableOnce()); $connector = new TcpConnector($loop); - $promise = $connector->connect($server->getAddress()); + $promise = $connector->connect(str_replace('tls://', '', $server->getAddress())); $promise->then(function (Stream $stream) { $stream->write("GET / HTTP/1.0\r\n\r\n"); diff --git a/tests/LimitingServerTest.php b/tests/LimitingServerTest.php index 6257c35b..0484a147 100644 --- a/tests/LimitingServerTest.php +++ b/tests/LimitingServerTest.php @@ -143,7 +143,7 @@ public function testSocketDisconnectionWillRemoveFromList() $tcp = new TcpServer(0, $loop); - $socket = stream_socket_client('tcp://' . $tcp->getAddress()); + $socket = stream_socket_client($tcp->getAddress()); fclose($socket); $server = new LimitingServer($tcp, 100); @@ -164,8 +164,8 @@ public function testPausingServerWillEmitOnlyOneButAcceptTwoConnectionsDueToOper $server->on('connection', $this->expectCallableOnce()); $server->on('error', $this->expectCallableNever()); - $first = stream_socket_client('tcp://' . $server->getAddress()); - $second = stream_socket_client('tcp://' . $server->getAddress()); + $first = stream_socket_client($server->getAddress()); + $second = stream_socket_client($server->getAddress()); Block\sleep(0.1, $loop); @@ -185,9 +185,9 @@ public function testPausingServerWillEmitTwoConnectionsFromBacklog() $server->on('connection', $twice); $server->on('error', $this->expectCallableNever()); - $first = stream_socket_client('tcp://' . $server->getAddress()); + $first = stream_socket_client($server->getAddress()); fclose($first); - $second = stream_socket_client('tcp://' . $server->getAddress()); + $second = stream_socket_client($server->getAddress()); fclose($second); Block\sleep(0.1, $loop); diff --git a/tests/ServerTest.php b/tests/ServerTest.php index dfff30ef..5c24e6ca 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -123,7 +123,7 @@ public function testDoesNotEmitSecureConnectionForNewPlainConnection() )); $server->on('connection', $this->expectCallableNever()); - $client = stream_socket_client($server->getAddress()); + $client = stream_socket_client(str_replace('tls://', '', $server->getAddress())); Block\sleep(0.1, $loop); } diff --git a/tests/TcpConnectorTest.php b/tests/TcpConnectorTest.php index e1fa702e..9d824ce7 100644 --- a/tests/TcpConnectorTest.php +++ b/tests/TcpConnectorTest.php @@ -55,7 +55,7 @@ public function connectionToTcpServerShouldSucceedWithRemoteAdressSameAsTarget() $connection = Block\await($connector->connect('127.0.0.1:9999'), $loop, self::TIMEOUT); /* @var $connection ConnectionInterface */ - $this->assertEquals('127.0.0.1:9999', $connection->getRemoteAddress()); + $this->assertEquals('tcp://127.0.0.1:9999', $connection->getRemoteAddress()); $connection->close(); } @@ -73,8 +73,8 @@ public function connectionToTcpServerShouldSucceedWithLocalAdressOnLocalhost() $connection = Block\await($connector->connect('127.0.0.1:9999'), $loop, self::TIMEOUT); /* @var $connection ConnectionInterface */ - $this->assertContains('127.0.0.1:', $connection->getLocalAddress()); - $this->assertNotEquals('127.0.0.1:9999', $connection->getLocalAddress()); + $this->assertContains('tcp://127.0.0.1:', $connection->getLocalAddress()); + $this->assertNotEquals('tcp://127.0.0.1:9999', $connection->getLocalAddress()); $connection->close(); } @@ -130,10 +130,10 @@ public function connectionToIp6TcpServerShouldSucceed() $connection = Block\await($connector->connect('[::1]:9999'), $loop, self::TIMEOUT); /* @var $connection ConnectionInterface */ - $this->assertEquals('[::1]:9999', $connection->getRemoteAddress()); + $this->assertEquals('tcp://[::1]:9999', $connection->getRemoteAddress()); - $this->assertContains('[::1]:', $connection->getLocalAddress()); - $this->assertNotEquals('[::1]:9999', $connection->getLocalAddress()); + $this->assertContains('tcp://[::1]:', $connection->getLocalAddress()); + $this->assertNotEquals('tcp://[::1]:9999', $connection->getLocalAddress()); $connection->close(); }