Skip to content

Commit

Permalink
Fix closing connection when cancelling during TLS handshake
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Jul 29, 2020
1 parent 842dcd7 commit 02d8980
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/StreamEncryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ public function toggle(Connection $stream, $toggle)
// TODO: add write() event to make sure we're not sending any excessive data

// cancelling this leaves this stream in an inconsistent state…
$deferred = new Deferred();
$deferred = new Deferred(function () {
throw new \RuntimeException();
});

// get actual stream socket from stream instance
$socket = $stream->stream;
Expand Down
34 changes: 34 additions & 0 deletions tests/FunctionalConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Clue\React\Block;
use React\EventLoop\Factory;
use React\Promise\Deferred;
use React\Socket\ConnectionInterface;
use React\Socket\Connector;
use React\Socket\ConnectorInterface;
Expand Down Expand Up @@ -127,6 +128,39 @@ public function connectionToRemoteTCP6ServerShouldResultInOurIP()
$this->assertSame($ip, filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6), $ip);
}

public function testCancelPendingTlsConnectionDuringTlsHandshakeShouldCloseTcpConnectionToServer()
{
$loop = Factory::create();

$server = new TcpServer(0, $loop);
$uri = str_replace('tcp://', '', $server->getAddress());

$connector = new Connector($loop);
$promise = $connector->connect('tls://' . $uri);

$deferred = new Deferred();
$server->on('connection', function (ConnectionInterface $connection) use ($promise, $deferred, $loop) {
$connection->on('close', function () use ($deferred) {
$deferred->resolve();
});

$loop->futureTick(function () use ($promise) {
$promise->cancel();
});
});

Block\await($deferred->promise(), $loop, self::TIMEOUT);
$server->close();

try {
Block\await($promise, $loop, self::TIMEOUT);
$this->fail();
} catch (\Exception $e) {
$this->assertInstanceOf('RuntimeException', $e);
$this->assertEquals('Connection to ' . $uri . ' cancelled during TLS handshake', $e->getMessage());
}
}

/**
* @internal
*/
Expand Down

0 comments on commit 02d8980

Please sign in to comment.