Skip to content

Commit e02071c

Browse files
committed
Improve TLS 1.3 support by always reading complete receive buffer
Construct underlying stream to always consume complete receive buffer. This avoids stale data in TLS buffers and also works around possible buffering issues in legacy PHP versions. The buffer size is limited due to TCP/IP buffers anyway, so this should not affect usage otherwise. This builds on top of reactphp/stream#139 to work around a bug in PHP where reading from a TLS 1.3 stream resource would hang with 100% CPU usage due to the changed TLS 1.3 handshake.
1 parent bfef257 commit e02071c

File tree

3 files changed

+6
-24
lines changed

3 files changed

+6
-24
lines changed

README.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,19 +1372,6 @@ This library does not take responsibility over these context options, so it's
13721372
up to consumers of this library to take care of setting appropriate context
13731373
options as described above.
13741374

1375-
All versions of PHP prior to 5.6.8 suffered from a buffering issue where reading
1376-
from a streaming TLS connection could be one `data` event behind.
1377-
This library implements a work-around to try to flush the complete incoming
1378-
data buffers on these legacy PHP versions, which has a penalty of around 10% of
1379-
throughput on all connections.
1380-
With this work-around, we have not been able to reproduce this issue anymore,
1381-
but we have seen reports of people saying this could still affect some of the
1382-
older PHP versions (`5.5.23`, `5.6.7`, and `5.6.8`).
1383-
Note that this only affects *some* higher-level streaming protocols, such as
1384-
IRC over TLS, but should not affect HTTP over TLS (HTTPS).
1385-
Further investigation of this issue is needed.
1386-
For more insights, this issue is also covered by our test suite.
1387-
13881375
PHP < 7.1.4 (and PHP < 7.0.18) suffers from a bug when writing big
13891376
chunks of data over TLS streams at once.
13901377
We try to work around this by limiting the write chunk size to 8192

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
99
"react/dns": "^0.4.13",
1010
"react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5",
11-
"react/stream": "^1.0 || ^0.7.1",
11+
"react/stream": "^1.1",
1212
"react/promise": "^2.6.0 || ^1.2.1",
1313
"react/promise-timer": "^1.4.0"
1414
},

src/Connection.php

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ class Connection extends EventEmitter implements ConnectionInterface
4343

4444
public function __construct($resource, LoopInterface $loop)
4545
{
46-
// PHP < 5.6.8 suffers from a buffer indicator bug on secure TLS connections
47-
// as a work-around we always read the complete buffer until its end.
48-
// The buffer size is limited due to TCP/IP buffers anyway, so this
49-
// should not affect usage otherwise.
50-
// See https://bugs.php.net/bug.php?id=65137
51-
// https://bugs.php.net/bug.php?id=41631
52-
// https://github.com/reactphp/socket-client/issues/24
53-
$clearCompleteBuffer = \PHP_VERSION_ID < 50608;
54-
5546
// PHP < 7.1.4 (and PHP < 7.0.18) suffers from a bug when writing big
5647
// chunks of data over TLS streams at once.
5748
// We try to work around this by limiting the write chunk size to 8192
@@ -62,10 +53,14 @@ public function __construct($resource, LoopInterface $loop)
6253
// See https://github.com/reactphp/socket/issues/105
6354
$limitWriteChunks = (\PHP_VERSION_ID < 70018 || (\PHP_VERSION_ID >= 70100 && \PHP_VERSION_ID < 70104));
6455

56+
// Construct underlying stream to always consume complete receive buffer.
57+
// This avoids stale data in TLS buffers and also works around possible
58+
// buffering issues in legacy PHP versions. The buffer size is limited
59+
// due to TCP/IP buffers anyway, so this should not affect usage otherwise.
6560
$this->input = new DuplexResourceStream(
6661
$resource,
6762
$loop,
68-
$clearCompleteBuffer ? -1 : null,
63+
-1,
6964
new WritableResourceStream($resource, $loop, null, $limitWriteChunks ? 8192 : null)
7065
);
7166

0 commit comments

Comments
 (0)