Skip to content

Commit 234c84a

Browse files
authored
Merge pull request #70 from clue-labs/no-master
Do not expose $master property and accept any ServerInterface for SecureServer
2 parents ca73095 + e4fb0f2 commit 234c84a

File tree

6 files changed

+50
-49
lines changed

6 files changed

+50
-49
lines changed

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,19 @@ Note that the `SecureServer` class is a concrete implementation for TLS sockets.
295295
If you want to typehint in your higher-level protocol implementation, you SHOULD
296296
use the generic [`ServerInterface`](#serverinterface) instead.
297297

298-
> Advanced usage: Internally, the `SecureServer` has to set the required
299-
context options on the underlying stream resources.
300-
It should therefor be used with an unmodified `Server` instance as first
301-
parameter so that it can allocate an empty context resource which this
302-
class uses to set required TLS context options.
303-
Failing to do so may result in some hard to trace race conditions,
304-
because all stream resources will use a single, shared default context
305-
resource otherwise.
298+
> Advanced usage: Despite allowing any `ServerInterface` as first parameter,
299+
you SHOULD pass an unmodified `Server` instance as first parameter, unless you
300+
know what you're doing.
301+
Internally, the `SecureServer` has to set the required TLS context options on
302+
the underlying stream resources.
303+
These resources are not exposed through any of the interfaces defined in this
304+
package, but only through the `React\Stream\Stream` class.
305+
The unmodified `Server` class is guaranteed to emit connections that implement
306+
the `ConnectionInterface` and also extend the `Stream` class in order to
307+
expose these underlying resources.
308+
If you use a custom `ServerInterface` and its `connection` event does not
309+
meet this requirement, the `SecureServer` will emit an `error` event and
310+
then close the underlying connection.
306311

307312
### ConnectionInterface
308313

src/SecureServer.php

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class SecureServer extends EventEmitter implements ServerInterface
5656
{
5757
private $tcp;
5858
private $encryption;
59+
private $context;
5960

6061
/**
6162
* Creates a secure TLS server and starts waiting for incoming connections
@@ -94,39 +95,36 @@ class SecureServer extends EventEmitter implements ServerInterface
9495
* and/or PHP version.
9596
* Passing unknown context options has no effect.
9697
*
97-
* Advanced usage: Internally, the `SecureServer` has to set the required
98-
* context options on the underlying stream resources.
99-
* It should therefor be used with an unmodified `Server` instance as first
100-
* parameter so that it can allocate an empty context resource which this
101-
* class uses to set required TLS context options.
102-
* Failing to do so may result in some hard to trace race conditions,
103-
* because all stream resources will use a single, shared default context
104-
* resource otherwise.
98+
* Advanced usage: Despite allowing any `ServerInterface` as first parameter,
99+
* you SHOULD pass an unmodified `Server` instance as first parameter, unless you
100+
* know what you're doing.
101+
* Internally, the `SecureServer` has to set the required TLS context options on
102+
* the underlying stream resources.
103+
* These resources are not exposed through any of the interfaces defined in this
104+
* package, but only through the `React\Stream\Stream` class.
105+
* The unmodified `Server` class is guaranteed to emit connections that implement
106+
* the `ConnectionInterface` and also extend the `Stream` class in order to
107+
* expose these underlying resources.
108+
* If you use a custom `ServerInterface` and its `connection` event does not
109+
* meet this requirement, the `SecureServer` will emit an `error` event and
110+
* then close the underlying connection.
105111
*
106-
* @param Server $tcp
112+
* @param ServerInterface|Server $tcp
107113
* @param LoopInterface $loop
108114
* @param array $context
109-
* @throws ConnectionException
110115
* @see Server
111116
* @link http://php.net/manual/en/context.ssl.php for TLS context options
112117
*/
113-
public function __construct(Server $tcp, LoopInterface $loop, array $context)
118+
public function __construct(ServerInterface $tcp, LoopInterface $loop, array $context)
114119
{
115-
if (!is_resource($tcp->master)) {
116-
throw new ConnectionException('TCP server already shut down');
117-
}
118-
119120
// default to empty passphrase to surpress blocking passphrase prompt
120121
$context += array(
121122
'passphrase' => ''
122123
);
123124

124-
foreach ($context as $name => $value) {
125-
stream_context_set_option($tcp->master, 'ssl', $name, $value);
126-
}
127-
128125
$this->tcp = $tcp;
129126
$this->encryption = new StreamEncryption($loop);
127+
$this->context = $context;
130128

131129
$that = $this;
132130
$this->tcp->on('connection', function ($connection) use ($that) {
@@ -156,6 +154,10 @@ public function handleConnection(ConnectionInterface $connection)
156154
return;
157155
}
158156

157+
foreach ($this->context as $name => $value) {
158+
stream_context_set_option($connection->stream, 'ssl', $name, $value);
159+
}
160+
159161
$that = $this;
160162

161163
$this->encryption->enable($connection)->then(

src/Server.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*/
3737
class Server extends EventEmitter implements ServerInterface
3838
{
39-
public $master;
39+
private $master;
4040
private $loop;
4141

4242
/**

tests/FunctionalSecureServerTest.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -368,19 +368,6 @@ public function testEmitsErrorIfConnectionIsNotSecureHandshake()
368368
Block\sleep(self::TIMEOUT, $loop);
369369
}
370370

371-
/**
372-
* @expectedException React\Socket\ConnectionException
373-
*/
374-
public function testFailsToCreateSecureServerOnClosedSocket()
375-
{
376-
$loop = Factory::create();
377-
378-
$server = new Server(0, $loop);
379-
$server->close();
380-
381-
new SecureServer($server, $loop, array());
382-
}
383-
384371
private function getPort(ServerInterface $server)
385372
{
386373
return parse_url($server->getAddress(), PHP_URL_PORT);

tests/FunctionalServerTest.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public function testEmitsConnectionWithLocalIpv6()
229229
$this->assertEquals($server->getAddress(), $local);
230230
}
231231

232-
public function testAppliesContextOptionsToSocketStreamResource()
232+
public function testEmitsConnectionWithInheritedContextOptions()
233233
{
234234
if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.13', '<')) {
235235
// https://3v4l.org/hB4Tc
@@ -242,7 +242,18 @@ public function testAppliesContextOptionsToSocketStreamResource()
242242
'backlog' => 4
243243
));
244244

245-
$all = stream_context_get_options($server->master);
245+
$all = null;
246+
$server->on('connection', function (ConnectionInterface $conn) use (&$all) {
247+
$all = stream_context_get_options($conn->stream);
248+
});
249+
$port = $this->getPort($server);
250+
251+
$connector = new TcpConnector($loop);
252+
$promise = $connector->create('127.0.0.1', $port);
253+
254+
$promise->then($this->expectCallableOnce());
255+
256+
Block\sleep(0.1, $loop);
246257

247258
$this->assertEquals(array('socket' => array('backlog' => 4)), $all);
248259
}

tests/SecureServerTest.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ public function setUp()
1515

1616
public function testGetAddressWillBePassedThroughToTcpServer()
1717
{
18-
$tcp = $this->getMockBuilder('React\Socket\Server')->disableOriginalConstructor()->getMock();
18+
$tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
1919
$tcp->expects($this->once())->method('getAddress')->willReturn('127.0.0.1:1234');
20-
$tcp->master = stream_socket_server('tcp://localhost:0');
2120

2221
$loop = $this->getMock('React\EventLoop\LoopInterface');
2322

@@ -28,9 +27,8 @@ public function testGetAddressWillBePassedThroughToTcpServer()
2827

2928
public function testCloseWillBePassedThroughToTcpServer()
3029
{
31-
$tcp = $this->getMockBuilder('React\Socket\Server')->disableOriginalConstructor()->getMock();
30+
$tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
3231
$tcp->expects($this->once())->method('close');
33-
$tcp->master = stream_socket_server('tcp://localhost:0');
3432

3533
$loop = $this->getMock('React\EventLoop\LoopInterface');
3634

@@ -42,7 +40,6 @@ public function testCloseWillBePassedThroughToTcpServer()
4240
public function testConnectionWillBeEndedWithErrorIfItIsNotAStream()
4341
{
4442
$tcp = $this->getMockBuilder('React\Socket\Server')->disableOriginalConstructor()->setMethods(null)->getMock();
45-
$tcp->master = stream_socket_server('tcp://localhost:0');
4643

4744
$loop = $this->getMock('React\EventLoop\LoopInterface');
4845

@@ -59,7 +56,6 @@ public function testConnectionWillBeEndedWithErrorIfItIsNotAStream()
5956
public function testSocketErrorWillBeForwarded()
6057
{
6158
$tcp = $this->getMockBuilder('React\Socket\Server')->disableOriginalConstructor()->setMethods(null)->getMock();
62-
$tcp->master = stream_socket_server('tcp://localhost:0');
6359

6460
$loop = $this->getMock('React\EventLoop\LoopInterface');
6561

0 commit comments

Comments
 (0)
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