Skip to content

Commit 46f4499

Browse files
committed
Avoid unneeded shutdown timer on already closed connection
1 parent edd1c2d commit 46f4499

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

src/Server.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,10 @@ public function onConnection(ConnectionInterface $connection)
119119
{
120120
$that = $this;
121121
$handling = $this->handleSocks($connection)->then(null, function () use ($connection, $that) {
122-
// SOCKS failed => close connection
123-
$that->endConnection($connection);
122+
// SOCKS failed => close connection (unless already closed)
123+
if ($connection->isWritable()) {
124+
$that->endConnection($connection);
125+
}
124126
});
125127

126128
$connection->on('close', function () use ($handling) {

tests/ServerTest.php

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ public function testConnectWillReturnMappedSocks5ErrorCodeFromConnector($error,
225225

226226
public function testHandleSocksConnectionWillEndOnInvalidData()
227227
{
228-
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
228+
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'isWritable'))->getMock();
229229
$connection->expects($this->once())->method('pause');
230230
$connection->expects($this->once())->method('end');
231+
$connection->expects($this->once())->method('isWritable')->willReturn(true);
231232

232233
$this->server->onConnection($connection);
233234

@@ -290,7 +291,8 @@ public function testHandleSocks4aConnectionWithSecureTlsSourceAddressWillEstabli
290291

291292
public function testHandleSocks4aConnectionWithInvalidHostnameWillNotEstablishOutgoingConnection()
292293
{
293-
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
294+
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'isWritable'))->getMock();
295+
$connection->expects($this->once())->method('isWritable')->willReturn(true);
294296

295297
$this->connector->expects($this->never())->method('connect');
296298

@@ -368,7 +370,8 @@ public function testHandleSocks5ConnectionWithHostnameWillEstablishOutgoingConne
368370

369371
public function testHandleSocks5ConnectionWithConnectorRefusedWillReturnReturnRefusedError()
370372
{
371-
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
373+
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write', 'isWritable'))->getMock();
374+
$connection->expects($this->once())->method('isWritable')->willReturn(true);
372375

373376
$promise = \React\Promise\reject(new \RuntimeException('Connection refused'));
374377

@@ -383,7 +386,8 @@ public function testHandleSocks5ConnectionWithConnectorRefusedWillReturnReturnRe
383386

384387
public function testHandleSocks5UdpCommandWillNotEstablishOutgoingConnectionAndReturnCommandError()
385388
{
386-
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
389+
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write', 'isWritable'))->getMock();
390+
$connection->expects($this->once())->method('isWritable')->willReturn(true);
387391

388392
$this->connector->expects($this->never())->method('connect');
389393

@@ -396,7 +400,8 @@ public function testHandleSocks5UdpCommandWillNotEstablishOutgoingConnectionAndR
396400

397401
public function testHandleSocks5ConnectionWithInvalidHostnameWillNotEstablishOutgoingConnectionAndReturnGeneralError()
398402
{
399-
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
403+
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write', 'isWritable'))->getMock();
404+
$connection->expects($this->once())->method('isWritable')->willReturn(true);
400405

401406
$this->connector->expects($this->never())->method('connect');
402407

@@ -420,4 +425,23 @@ public function testHandleSocksConnectionWillCancelOutputConnectionIfIncomingClo
420425
$connection->emit('data', array("\x04\x01" . "\x00\x50" . pack('N', ip2long('127.0.0.1')) . "\x00"));
421426
$connection->emit('close');
422427
}
428+
429+
public function testHandleSocksConnectionWillNotEndIfAlreadyClosed()
430+
{
431+
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'isWritable'))->getMock();
432+
$connection->expects($this->never())->method('pause');
433+
$connection->expects($this->once())->method('end');
434+
$connection->expects($this->once())->method('isWritable')->willReturn(false);
435+
436+
$promise = new Promise(function () { }, function () {
437+
throw new \RuntimeException();
438+
});
439+
440+
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise);
441+
442+
$this->server->onConnection($connection);
443+
444+
$connection->emit('data', array("\x04\x01" . "\x00\x50" . pack('N', ip2long('127.0.0.1')) . "\x00"));
445+
$connection->emit('close');
446+
}
423447
}

0 commit comments

Comments
 (0)