From b0c8d3717692793f725a1ba63964b2248be69f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Wed, 1 Feb 2017 17:04:43 +0100 Subject: [PATCH] Replace getPort() with getAddress() --- README.md | 27 ++++++++++++------ examples/01-echo.php | 2 +- examples/02-chat-server.php | 2 +- examples/03-benchmark.php | 2 +- src/SecureServer.php | 4 +-- src/Server.php | 15 +++++++--- src/ServerInterface.php | 23 +++++++++++++-- tests/FunctionalSecureServerTest.php | 42 ++++++++++++++++------------ tests/FunctionalServerTest.php | 24 ++++++++++------ tests/SecureServerTest.php | 6 ++-- tests/ServerTest.php | 10 +++---- tests/Stub/ServerStub.php | 4 +-- 12 files changed, 103 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 19da8ad8..2e1126b1 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ For the code of the current stable 0.4.x release, checkout the * [ServerInterface](#serverinterface) * [connection event](#connection-event) * [error event](#error-event) - * [getPort()](#getport) + * [getAddress()](#getaddress) * [close()](#close) * [Server](#server) * [SecureServer](#secureserver) @@ -115,18 +115,27 @@ Note that this is not a fatal error event, i.e. the server keeps listening for new connections even after this event. -#### getPort() +#### getAddress() -The `getPort(): ?int` method can be used to -return the port this server is currently listening on. +The `getAddress(): ?string` method can be used to +return the full address (IP and port) this server is currently listening on. ```php -$port = $server->getPort(); -echo 'Server listening on port ' . $port . PHP_EOL; +$address = $server->getAddress(); +echo 'Server listening on ' . $address . PHP_EOL; ``` -It will return the port number or `NULL` if it is unknown (not applicable to -this server socket or already closed). +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 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); +echo 'Server listening on port ' . $port . PHP_EOL; +``` #### close() @@ -159,7 +168,7 @@ In order to use a random port assignment, you can use the port `0`: ```php $server = new Server(0, $loop); -$port = $server->getPort(); +$address = $server->getAddress(); ``` In order to change the host the socket is listening on, you can provide an IP diff --git a/examples/01-echo.php b/examples/01-echo.php index 744aea2d..fbb6c59b 100644 --- a/examples/01-echo.php +++ b/examples/01-echo.php @@ -36,6 +36,6 @@ $server->on('error', 'printf'); -echo 'bound to ' . $server->getPort() . PHP_EOL; +echo 'Listening on ' . $server->getAddress() . PHP_EOL; $loop->run(); diff --git a/examples/02-chat-server.php b/examples/02-chat-server.php index beb159d9..87737c1f 100644 --- a/examples/02-chat-server.php +++ b/examples/02-chat-server.php @@ -58,6 +58,6 @@ $server->on('error', 'printf'); -echo 'Listening on ' . $server->getPort() . PHP_EOL; +echo 'Listening on ' . $server->getAddress() . PHP_EOL; $loop->run(); diff --git a/examples/03-benchmark.php b/examples/03-benchmark.php index 712c1e07..2485c1f7 100644 --- a/examples/03-benchmark.php +++ b/examples/03-benchmark.php @@ -53,6 +53,6 @@ $server->on('error', 'printf'); -echo 'bound to ' . $server->getPort() . PHP_EOL; +echo 'Listening on ' . $server->getAddress() . PHP_EOL; $loop->run(); diff --git a/src/SecureServer.php b/src/SecureServer.php index 5fcc4e20..20d8171e 100644 --- a/src/SecureServer.php +++ b/src/SecureServer.php @@ -68,9 +68,9 @@ public function __construct(Server $tcp, LoopInterface $loop, array $context) }); } - public function getPort() + public function getAddress() { - return $this->tcp->getPort(); + return $this->tcp->getAddress(); } public function close() diff --git a/src/Server.php b/src/Server.php index 8f6452ee..36a4eba4 100644 --- a/src/Server.php +++ b/src/Server.php @@ -58,7 +58,7 @@ class Server extends EventEmitter implements ServerInterface * * ```php * $server = new Server(0, $loop); - * $port = $server->getPort(); + * $address = $server->getAddress(); * ``` * * In order to change the host the socket is listening on, you can provide an IP @@ -174,15 +174,22 @@ public function handleConnection($socket) $this->emit('connection', array($client)); } - public function getPort() + public function getAddress() { if (!is_resource($this->master)) { return null; } - $name = stream_socket_get_name($this->master, false); + $address = stream_socket_get_name($this->master, false); - return (int) substr(strrchr($name, ':'), 1); + // check if this is an IPv6 address which includes multiple colons but no square brackets + $pos = strrpos($address, ':'); + if ($pos !== false && strpos($address, ':') < $pos && substr($address, 0, 1) !== '[') { + $port = substr($address, $pos + 1); + $address = '[' . substr($address, 0, $pos) . ']:' . $port; + } + + return $address; } public function close() diff --git a/src/ServerInterface.php b/src/ServerInterface.php index c562f18b..2d5ab829 100644 --- a/src/ServerInterface.php +++ b/src/ServerInterface.php @@ -49,11 +49,28 @@ interface ServerInterface extends EventEmitterInterface { /** - * Returns the port this server is currently listening on + * Returns the full address (IP and port) this server is currently listening on * - * @return ?int the port number or NULL if it is unknown (not applicable to this server socket or already closed) + * ```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 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); + * 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) */ - public function getPort(); + public function getAddress(); /** * Shuts down this listening socket diff --git a/tests/FunctionalSecureServerTest.php b/tests/FunctionalSecureServerTest.php index dff5723f..f41e122c 100644 --- a/tests/FunctionalSecureServerTest.php +++ b/tests/FunctionalSecureServerTest.php @@ -3,13 +3,14 @@ namespace React\Tests\Socket; use React\EventLoop\Factory; -use React\SocketClient\TcpConnector; -use Clue\React\Block; -use React\Socket\SecureServer; -use React\SocketClient\SecureConnector; use React\Stream\Stream; +use React\Socket\SecureServer; use React\Socket\ConnectionInterface; use React\Socket\Server; +use React\Socket\ServerInterface; +use React\SocketClient\TcpConnector; +use React\SocketClient\SecureConnector; +use Clue\React\Block; class FunctionalSecureServerTest extends TestCase { @@ -31,7 +32,7 @@ public function testEmitsConnectionForNewConnection() 'local_cert' => __DIR__ . '/../examples/localhost.pem' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => false @@ -50,7 +51,7 @@ public function testWritesDataToConnection() 'local_cert' => __DIR__ . '/../examples/localhost.pem' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $server->on('connection', function (ConnectionInterface $conn) { $conn->write('foo'); @@ -78,7 +79,7 @@ public function testWritesDataInMultipleChunksToConnection() 'local_cert' => __DIR__ . '/../examples/localhost.pem' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $server->on('connection', function (ConnectionInterface $conn) { $conn->write(str_repeat('*', 400000)); @@ -111,7 +112,7 @@ public function testEmitsDataFromConnection() 'local_cert' => __DIR__ . '/../examples/localhost.pem' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $once = $this->expectCallableOnceWith('foo'); $server->on('connection', function (ConnectionInterface $conn) use ($once) { @@ -140,7 +141,7 @@ public function testEmitsDataInMultipleChunksFromConnection() 'local_cert' => __DIR__ . '/../examples/localhost.pem' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $received = 0; $server->on('connection', function (ConnectionInterface $conn) use (&$received) { @@ -173,7 +174,7 @@ public function testPipesDataBackInMultipleChunksFromConnection() 'local_cert' => __DIR__ . '/../examples/localhost.pem' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $server->on('connection', function (ConnectionInterface $conn) use (&$received) { $conn->pipe($conn); @@ -209,7 +210,7 @@ public function testEmitsConnectionForNewConnectionWithEncryptedCertificate() 'passphrase' => 'swordfish' )); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => false @@ -229,7 +230,7 @@ public function testEmitsErrorForServerWithInvalidCertificate() )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => false @@ -250,7 +251,7 @@ public function testEmitsErrorForServerWithEncryptedCertificateMissingPassphrase )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => false @@ -272,7 +273,7 @@ public function testEmitsErrorForServerWithEncryptedCertificateWithInvalidPassph )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => false @@ -293,7 +294,7 @@ public function testEmitsErrorForConnectionWithPeerVerification() )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => true @@ -314,7 +315,7 @@ public function testEmitsErrorIfConnectionIsCancelled() )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new SecureConnector(new TcpConnector($loop), $loop, array( 'verify_peer' => false @@ -336,7 +337,7 @@ public function testEmitsNothingIfConnectionIsIdle() )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableNever()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -355,7 +356,7 @@ public function testEmitsErrorIfConnectionIsNotSecureHandshake() )); $server->on('connection', $this->expectCallableNever()); $server->on('error', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -379,4 +380,9 @@ public function testFailsToCreateSecureServerOnClosedSocket() new SecureServer($server, $loop, array()); } + + private function getPort(ServerInterface $server) + { + return parse_url($server->getAddress(), PHP_URL_PORT); + } } diff --git a/tests/FunctionalServerTest.php b/tests/FunctionalServerTest.php index 8b993906..9e0678cb 100644 --- a/tests/FunctionalServerTest.php +++ b/tests/FunctionalServerTest.php @@ -3,11 +3,12 @@ namespace React\Tests\Socket; use React\EventLoop\Factory; -use React\SocketClient\TcpConnector; use React\Socket\Server; -use Clue\React\Block; use React\Socket\ConnectionException; use React\Socket\ConnectionInterface; +use React\Socket\ServerInterface; +use React\SocketClient\TcpConnector; +use Clue\React\Block; class FunctionalServerTest extends TestCase { @@ -17,7 +18,7 @@ public function testEmitsConnectionForNewConnection() $server = new Server(0, $loop); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -36,7 +37,7 @@ public function testEmitsConnectionWithRemoteIp() $server->on('connection', function (ConnectionInterface $conn) use (&$peer) { $peer = $conn->getRemoteAddress(); }); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -59,7 +60,7 @@ public function testEmitsConnectionWithRemoteIpAfterConnectionIsClosedByPeer() $peer = $conn->getRemoteAddress(); }); }); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -82,7 +83,7 @@ public function testEmitsConnectionWithRemoteNullAddressAfterConnectionIsClosedL $conn->close(); $peer = $conn->getRemoteAddress(); }); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -100,7 +101,7 @@ public function testEmitsConnectionEvenIfConnectionIsCancelled() $server = new Server(0, $loop); $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('127.0.0.1', $port); @@ -122,7 +123,7 @@ public function testEmitsConnectionForNewIpv6Connection() } $server->on('connection', $this->expectCallableOnce()); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('::1', $port); @@ -146,7 +147,7 @@ public function testEmitsConnectionWithRemoteIpv6() $server->on('connection', function (ConnectionInterface $conn) use (&$peer) { $peer = $conn->getRemoteAddress(); }); - $port = $server->getPort(); + $port = $this->getPort($server); $connector = new TcpConnector($loop); $promise = $connector->create('::1', $port); @@ -215,4 +216,9 @@ public function testFailsToListenOnUriWIthHostname() new Server('localhost:8080', $loop); } + + private function getPort(ServerInterface $server) + { + return parse_url('tcp://' . $server->getAddress(), PHP_URL_PORT); + } } diff --git a/tests/SecureServerTest.php b/tests/SecureServerTest.php index df1843e3..5e00a6dd 100644 --- a/tests/SecureServerTest.php +++ b/tests/SecureServerTest.php @@ -13,17 +13,17 @@ public function setUp() } } - public function testGetPortWillBePassedThroughToTcpServer() + public function testGetAddressWillBePassedThroughToTcpServer() { $tcp = $this->getMockBuilder('React\Socket\Server')->disableOriginalConstructor()->getMock(); - $tcp->expects($this->once())->method('getPort')->willReturn(1234); + $tcp->expects($this->once())->method('getAddress')->willReturn('127.0.0.1:1234'); $tcp->master = stream_socket_server('tcp://localhost:0'); $loop = $this->getMock('React\EventLoop\LoopInterface'); $server = new SecureServer($tcp, $loop, array()); - $this->assertEquals(1234, $server->getPort()); + $this->assertEquals('127.0.0.1:1234', $server->getAddress()); } public function testCloseWillBePassedThroughToTcpServer() diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 167b2622..cbe5e141 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -2,9 +2,9 @@ namespace React\Tests\Socket; -use React\Socket\Server; use React\EventLoop\StreamSelectLoop; use React\Stream\Stream; +use React\Socket\Server; class ServerTest extends TestCase { @@ -19,14 +19,14 @@ private function createLoop() /** * @covers React\Socket\Server::__construct - * @covers React\Socket\Server::getPort + * @covers React\Socket\Server::getAddress */ public function setUp() { $this->loop = $this->createLoop(); $this->server = new Server(0, $this->loop); - $this->port = $this->server->getPort(); + $this->port = parse_url($this->server->getAddress(), PHP_URL_PORT); } /** @@ -145,10 +145,10 @@ public function testCloseTwiceIsNoOp() $this->server->close(); } - public function testGetPortAfterCloseReturnsNull() + public function testGetAddressAfterCloseReturnsNull() { $this->server->close(); - $this->assertNull($this->server->getPort()); + $this->assertNull($this->server->getAddress()); } public function testLoopWillEndWhenServerIsClosedAfterSingleConnection() diff --git a/tests/Stub/ServerStub.php b/tests/Stub/ServerStub.php index d385db00..d9e74f47 100644 --- a/tests/Stub/ServerStub.php +++ b/tests/Stub/ServerStub.php @@ -7,9 +7,9 @@ class ServerStub extends EventEmitter implements ServerInterface { - public function getPort() + public function getAddress() { - return 80; + return '127.0.0.1:80'; } public function close()