From 74a194f9262917b4e2a495850239d7d3f0a00b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Mon, 8 May 2017 10:27:07 +0200 Subject: [PATCH 1/2] Fix unix:// addresses for Unix domain socket (UDS) paths --- README.md | 18 ++++++++++++++++-- src/Connection.php | 16 ++++++++++++++++ src/ConnectionInterface.php | 6 ++++-- src/UnixConnector.php | 5 ++++- tests/UnixConnectorTest.php | 13 +++++++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6c809c2b..65892b47 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,8 @@ 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 address (URI) as a string value, such -as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. +as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, +`unix://example.sock` or `unix:///path/to/example.sock`. Note that individual URI components are application specific and depend on the underlying transport protocol. @@ -176,7 +177,8 @@ 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 address (URI) as a string value, such -as `tcp://127.0.0.1:8080`, `tcp://[::1]:80` or `tls://127.0.0.1:443`. +as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, +`unix://example.sock` or `unix:///path/to/example.sock`. Note that individual URI components are application specific and depend on the underlying transport protocol. @@ -831,6 +833,12 @@ $connector->connect('unix:///tmp/demo.sock')->then(function (ConnectionInterface }); ``` +> The [`getRemoteAddress()`](#getremoteaddress) method will return the target + Unix domain socket (UDS) path as given to the `connect()` method, including + the `unix://` scheme, for example `unix:///tmp/demo.sock`. + The [`getLocalAddress()`](#getlocaladdress) method will most likely return a + `null` value as this value is not applicable to UDS connections here. + Under the hood, the `Connector` is implemented as a *higher-level facade* for the lower-level connectors implemented in this package. This means it also shares all of their features and implementation details. @@ -1209,6 +1217,12 @@ Connecting to Unix domain sockets is an atomic operation, i.e. its promise will settle (either resolve or reject) immediately. As such, calling `cancel()` on the resulting promise has no effect. +> The [`getRemoteAddress()`](#getremoteaddress) method will return the target + Unix domain socket (UDS) path as given to the `connect()` method, prepended + with the `unix://` scheme, for example `unix:///tmp/demo.sock`. + The [`getLocalAddress()`](#getlocaladdress) method will most likely return a + `null` value as this value is not applicable to UDS connections here. + ## Install The recommended way to install this library is [through Composer](http://getcomposer.org). diff --git a/src/Connection.php b/src/Connection.php index 528cb76d..2135b367 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -19,6 +19,13 @@ */ class Connection extends EventEmitter implements ConnectionInterface { + /** + * Internal flag whether this is a Unix domain socket (UDS) connection + * + * @internal + */ + public $unix = false; + /** * Internal flag whether encryption has been enabled on this connection * @@ -138,6 +145,15 @@ private function parseAddress($address) return null; } + if ($this->unix) { + // unknown addresses should not return a NULL-byte string + if ($address === "\x00") { + return null; + } + + return 'unix://' . $address; + } + // 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) !== '[') { diff --git a/src/ConnectionInterface.php b/src/ConnectionInterface.php index 45848bca..64613b58 100644 --- a/src/ConnectionInterface.php +++ b/src/ConnectionInterface.php @@ -66,7 +66,8 @@ interface ConnectionInterface extends DuplexStreamInterface * after the connection 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`. + * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, + * `unix://example.sock` or `unix:///path/to/example.sock`. * Note that individual URI components are application specific and depend * on the underlying transport protocol. * @@ -95,7 +96,8 @@ public function getRemoteAddress(); * after the connection 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`. + * as `tcp://127.0.0.1:8080`, `tcp://[::1]:80`, `tls://127.0.0.1:443`, + * `unix://example.sock` or `unix:///path/to/example.sock`. * Note that individual URI components are application specific and depend * on the underlying transport protocol. * diff --git a/src/UnixConnector.php b/src/UnixConnector.php index bb00f8dd..719db8e9 100644 --- a/src/UnixConnector.php +++ b/src/UnixConnector.php @@ -36,6 +36,9 @@ public function connect($path) return Promise\reject(new RuntimeException('Unable to connect to unix domain socket "' . $path . '": ' . $errstr, $errno)); } - return Promise\resolve(new Connection($resource, $this->loop)); + $connection = new Connection($resource, $this->loop); + $connection->unix = true; + + return Promise\resolve($connection); } } diff --git a/tests/UnixConnectorTest.php b/tests/UnixConnectorTest.php index deb826d7..1c86f616 100644 --- a/tests/UnixConnectorTest.php +++ b/tests/UnixConnectorTest.php @@ -3,6 +3,8 @@ namespace React\Tests\Socket; use React\Socket\UnixConnector; +use Clue\React\Block; +use React\Socket\ConnectionInterface; class UnixConnectorTest extends TestCase { @@ -45,8 +47,19 @@ public function testValid() $promise = $this->connector->connect($path); $promise->then($this->expectCallableOnce()); + // remember remote and local address of this connection and close again + $remote = $local = false; + $promise->then(function(ConnectionInterface $conn) use (&$remote, &$local) { + $remote = $conn->getRemoteAddress(); + $local = $conn->getLocalAddress(); + $conn->close(); + }); + // clean up server fclose($server); unlink($path); + + $this->assertNull($local); + $this->assertEquals('unix://' . $path, $remote); } } From eeec8f2df16b14b7ffc8fd913f750eb2615a8e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Mon, 8 May 2017 13:34:42 +0200 Subject: [PATCH 2/2] Work-around HHVM < 3.19 appending colon to all Unix socket addresses --- src/Connection.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Connection.php b/src/Connection.php index 2135b367..abdf361d 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -146,8 +146,15 @@ private function parseAddress($address) } if ($this->unix) { - // unknown addresses should not return a NULL-byte string - if ($address === "\x00") { + // remove trailing colon from address for HHVM < 3.19: https://3v4l.org/5C1lo + // note that techncially ":" is a valid address, so keep this in place otherwise + if (substr($address, -1) === ':' && defined('HHVM_VERSION_ID') && HHVM_VERSION_ID < 31900) { + $address = (string)substr($address, 0, -1); + } + + // work around unknown addresses should return null value: https://3v4l.org/5C1lo + // PHP uses "\0" string and HHVM uses empty string (colon removed above) + if ($address === "\x00" || $address === '') { return null; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy