From e1c3e1ee6f175186001188506592b9c4dad838a9 Mon Sep 17 00:00:00 2001 From: Aaron Piotrowski Date: Tue, 10 Dec 2024 00:04:10 -0600 Subject: [PATCH] Fix issue #371 --- src/Driver/Http1Driver.php | 9 ++++++++- src/Driver/Http2Driver.php | 13 +++++++++++-- src/Driver/Internal/TimeoutQueue.php | 10 +++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/Driver/Http1Driver.php b/src/Driver/Http1Driver.php index caf11c81..917dd470 100644 --- a/src/Driver/Http1Driver.php +++ b/src/Driver/Http1Driver.php @@ -412,6 +412,8 @@ public function handleClient( continue; } + $this->suspendTimeout(); + $this->currentBuffer = $buffer; $this->handleRequest($request); $this->pendingResponseCount--; @@ -740,7 +742,7 @@ static function (int $bodySize) use (&$bodySizeLimit): void { $this->bodyQueue = null; $queue->complete(); - $this->updateTimeout(); + $this->suspendTimeout(); if ($this->http2driver) { continue; @@ -802,6 +804,11 @@ private function updateTimeout(): void self::getTimeoutQueue()->update($this->client, 0, $this->connectionTimeout); } + private function suspendTimeout(): void + { + self::getTimeoutQueue()->suspend($this->client, 0); + } + private function removeTimeout(): void { self::getTimeoutQueue()->remove($this->client, 0); diff --git a/src/Driver/Http2Driver.php b/src/Driver/Http2Driver.php index d981d853..5a8900c4 100644 --- a/src/Driver/Http2Driver.php +++ b/src/Driver/Http2Driver.php @@ -699,6 +699,13 @@ private function updateTimeout(int $id): void } } + private function suspendTimeout(int $id): void + { + if ($id & 1) { + self::getTimeoutQueue()->suspend($this->client, $id); + } + } + private function readPreface(): string { $buffer = $this->readableStream->read(); @@ -899,8 +906,6 @@ public function handleHeaders(int $streamId, array $pseudo, array $headers, bool // Header frames can be received on previously opened streams (trailer headers). $this->remoteStreamId = \max($streamId, $this->remoteStreamId); - $this->updateTimeout($streamId); - if (isset($this->trailerDeferreds[$streamId]) && $stream->state & Http2Stream::RESERVED) { if (!$streamEnded) { throw new Http2ConnectionException( @@ -932,12 +937,16 @@ public function handleHeaders(int $streamId, array $pseudo, array $headers, bool unset($this->bodyQueues[$streamId], $this->trailerDeferreds[$streamId]); + $this->suspendTimeout($streamId); + $queue->complete(); $deferred->complete($headers); return; } + $this->updateTimeout($streamId); + if ($stream->state & Http2Stream::RESERVED) { throw new Http2StreamException( "Stream already reserved", diff --git a/src/Driver/Internal/TimeoutQueue.php b/src/Driver/Internal/TimeoutQueue.php index 2b9f20d6..2e6b2e1d 100644 --- a/src/Driver/Internal/TimeoutQueue.php +++ b/src/Driver/Internal/TimeoutQueue.php @@ -75,11 +75,19 @@ private function makeId(Client $client, int $streamId): string public function update(Client $client, int $streamId, int $timeout): void { $cacheId = $this->makeId($client, $streamId); - \assert(isset($this->callbacks[$cacheId])); + \assert(isset($this->callbacks[$cacheId], $this->streamNames[$client][$streamId])); $this->timeoutCache->update($cacheId, $this->now + $timeout); } + public function suspend(Client $client, int $streamId): void + { + $cacheId = $this->makeId($client, $streamId); + \assert(isset($this->callbacks[$cacheId], $this->streamNames[$client][$streamId])); + + $this->timeoutCache->clear($cacheId); + } + /** * Remove the given stream ID. */