From 02d89808a10a863a7d36a9c1af9005aa723cf248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 28 Jul 2020 21:06:10 +0200 Subject: [PATCH] Fix closing connection when cancelling during TLS handshake --- src/StreamEncryption.php | 4 +++- tests/FunctionalConnectorTest.php | 34 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/StreamEncryption.php b/src/StreamEncryption.php index 61777640..8321b699 100644 --- a/src/StreamEncryption.php +++ b/src/StreamEncryption.php @@ -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; diff --git a/tests/FunctionalConnectorTest.php b/tests/FunctionalConnectorTest.php index be2e6240..9944dd74 100644 --- a/tests/FunctionalConnectorTest.php +++ b/tests/FunctionalConnectorTest.php @@ -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; @@ -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 */