Skip to content

Commit 2536462

Browse files
committed
Add support for Unix domain sockets (UDS)
1 parent 3cc3f86 commit 2536462

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,18 @@ $secureConnector->create('www.google.com', 443)->then(function (React\Stream\Str
6666

6767
$loop->run();
6868
```
69+
70+
### Unix domain sockets
71+
72+
Similarly, the `UnixConnector` class can be used to connect to Unix domain socket (UDS)
73+
paths like this:
74+
75+
```php
76+
$connector = new React\SocketClient\UnixConnector($loop);
77+
78+
$connector->create('/tmp/demo.sock')->then(function (React\Stream\Stream $stream) {
79+
$stream->write("HELLO\n");
80+
});
81+
82+
$loop->run();
83+
```

src/UnixConnector.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace React\SocketClient;
4+
5+
use React\SocketClient\ConnectorInterface;
6+
use React\Stream\Stream;
7+
use React\EventLoop\LoopInterface;
8+
use React\Promise;
9+
use RuntimeException;
10+
11+
/**
12+
* Unix domain socket connector
13+
*
14+
* Unix domain sockets use atomic operations, so we can as well emulate
15+
* async behavior.
16+
*/
17+
class UnixConnector implements ConnectorInterface
18+
{
19+
private $loop;
20+
21+
public function __construct(LoopInterface $loop)
22+
{
23+
$this->loop = $loop;
24+
}
25+
26+
public function create($path, $unusedPort = 0)
27+
{
28+
$resource = @stream_socket_client('unix://' . $path, $errno, $errstr, 1.0);
29+
30+
if (!$resource) {
31+
return Promise\reject(new RuntimeException('Unable to connect to unix domain socket "' . $path . '": ' . $errstr, $errno));
32+
}
33+
34+
return Promise\resolve(new Stream($resource, $this->loop));
35+
}
36+
}

tests/UnixConnectorTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace React\Tests\SocketClient;
4+
5+
use React\SocketClient\UnixConnector;
6+
7+
class UnixConnectorTest extends TestCase
8+
{
9+
private $loop;
10+
private $connector;
11+
12+
public function setUp()
13+
{
14+
$this->loop = $this->getMock('React\EventLoop\LoopInterface');
15+
$this->connector = new UnixConnector($this->loop);
16+
}
17+
18+
public function testInvalid()
19+
{
20+
$promise = $this->connector->create('google.com', 80);
21+
$promise->then(null, $this->expectCallableOnce());
22+
}
23+
24+
public function testValid()
25+
{
26+
// random unix domain socket path
27+
$path = sys_get_temp_dir() . '/test' . uniqid() . '.sock';
28+
29+
// temporarily create unix domain socket server to connect to
30+
$server = stream_socket_server('unix://' . $path, $errno, $errstr);
31+
32+
// skip test if we can not create a test server (Windows etc.)
33+
if (!$server) {
34+
$this->markTestSkipped('Unable to create socket "' . $path . '": ' . $errstr . '(' . $errno .')');
35+
return;
36+
}
37+
38+
// tests succeeds if we get notified of successful connection
39+
$promise = $this->connector->create($path, 0);
40+
$promise->then($this->expectCallableOnce());
41+
42+
// clean up server
43+
fclose($server);
44+
unlink($path);
45+
}
46+
}

0 commit comments

Comments
 (0)