From 8eed9e7db24be7ef710695c7052f00fa1578326c Mon Sep 17 00:00:00 2001 From: Matt Bonneau Date: Fri, 10 Mar 2017 00:17:23 -0500 Subject: [PATCH] Server passing tests - client passes most tests - refactoring and API help needed --- src/Handshake/ClientNegotiator.php | 2 +- src/Handshake/PermessageDeflateOptions.php | 11 ++---- src/Messaging/MessageBuffer.php | 45 +++++++++++++++------- tests/ab/clientRunner.php | 13 +++---- tests/ab/startServer.php | 2 - 5 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/Handshake/ClientNegotiator.php b/src/Handshake/ClientNegotiator.php index 95f49ec..b4394df 100644 --- a/src/Handshake/ClientNegotiator.php +++ b/src/Handshake/ClientNegotiator.php @@ -36,7 +36,7 @@ class ClientNegotiator { if ($enablePerMessageDeflate) { $this->defaultHeader = $this->defaultHeader->withAddedHeader( 'Sec-WebSocket-Extensions', - 'permessage-deflate'); + 'permessage-deflate; client_max_window_bits'); } } diff --git a/src/Handshake/PermessageDeflateOptions.php b/src/Handshake/PermessageDeflateOptions.php index 6b325d8..8b91289 100644 --- a/src/Handshake/PermessageDeflateOptions.php +++ b/src/Handshake/PermessageDeflateOptions.php @@ -121,7 +121,6 @@ final class PermessageDeflateOptions */ public function getClientNoContextTakeover() { - return false; // always return false unless we want to conserve resources return $this->client_no_context_takeover; } @@ -163,11 +162,9 @@ final class PermessageDeflateOptions if ($this->client_max_window_bits != 15) { $header .= '; client_max_window_bits='. $this->client_max_window_bits; } - // this would only be needed if you want to save server resources (no buffer needed) - // worse compression -// if ($this->client_no_context_takeover) { -// $header .= '; client_no_context_takeover'; -// } + if ($this->client_no_context_takeover) { + $header .= '; client_no_context_takeover'; + } if ($this->server_max_window_bits != 15) { $header .= '; server_max_window_bits=' . $this->server_max_window_bits; } @@ -175,8 +172,6 @@ final class PermessageDeflateOptions $header .= '; server_no_context_takeover'; } - echo $header . "\n"; - return $response->withAddedHeader('Sec-Websocket-Extensions', $header); } } \ No newline at end of file diff --git a/src/Messaging/MessageBuffer.php b/src/Messaging/MessageBuffer.php index 2ace8db..b5aba3e 100644 --- a/src/Messaging/MessageBuffer.php +++ b/src/Messaging/MessageBuffer.php @@ -124,6 +124,8 @@ class MessageBuffer { return ''; } } else { + //echo "fin: " . json_encode($this->frameBuffer->isFinal()) . ", bCount: " . $this->messageBuffer->count() . ", Rsv1: " . json_encode($this->frameBuffer->getRsv1()) . "\n"; + if ($this->messageBuffer->count() === 0 && $this->frameBuffer->getRsv1()) { $this->compressedMessage = true; } @@ -305,7 +307,7 @@ class MessageBuffer { if ($final) { // reset deflator if client doesn't remember contexts - if ($this->permessageDeflateOptions->getClientNoContextTakeover()) { + if ($this->getDeflateNoContextTakeover()) { $this->deflator = null; } $this->streamingMessageOpCode = -1; @@ -314,17 +316,38 @@ class MessageBuffer { private $inflator; + private function getDeflateNoContextTakeover() { + return $this->checkForMask ? + $this->permessageDeflateOptions->getServerNoContextTakeover() : + $this->permessageDeflateOptions->getClientNoContextTakeover(); + } + + private function getDeflateWindowBits() { + return $this->checkForMask ? $this->permessageDeflateOptions->getServerMaxWindowBits() : $this->permessageDeflateOptions->getClientMaxWindowBits(); + } + + private function getInflateNoContextTakeover() { + return $this->checkForMask ? + $this->permessageDeflateOptions->getClientNoContextTakeover() : + $this->permessageDeflateOptions->getServerNoContextTakeover(); + } + + private function getInflateWindowBits() { + return $this->checkForMask ? $this->permessageDeflateOptions->getClientMaxWindowBits() : $this->permessageDeflateOptions->getServerMaxWindowBits(); + } + private function inflateFrame(Frame $frame) { if ($this->inflator === null) { -// $this->inflator = inflate_init(ZLIB_ENCODING_RAW); + $options = [ + 'level' => -1, + 'memory' => 8, + 'window' => $this->getInflateWindowBits(), + 'strategy' => ZLIB_DEFAULT_STRATEGY + ]; + //echo "inflate_init(RAW, " . json_encode($options) . ")\n"; $this->inflator = inflate_init( ZLIB_ENCODING_RAW, - [ - 'level' => -1, - 'memory' => 8, - 'window' => $this->permessageDeflateOptions->getClientMaxWindowBits(), - 'strategy' => ZLIB_DEFAULT_STRATEGY - ] + $options ); } @@ -349,16 +372,12 @@ class MessageBuffer { } if ($this->deflator === null) { -// $this->deflator = deflate_init( -// ZLIB_ENCODING_RAW -// ); - echo "init with " . $this->permessageDeflateOptions->getServerMaxWindowBits(); $this->deflator = deflate_init( ZLIB_ENCODING_RAW, [ 'level' => -1, 'memory' => 8, - 'window' => $this->permessageDeflateOptions->getServerMaxWindowBits(), + 'window' => $this->getDeflateWindowBits(), 'strategy' => ZLIB_DEFAULT_STRATEGY ] ); diff --git a/tests/ab/clientRunner.php b/tests/ab/clientRunner.php index bfd90a4..2cd963e 100644 --- a/tests/ab/clientRunner.php +++ b/tests/ab/clientRunner.php @@ -1,5 +1,7 @@ create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred, $casePath, $case) { $cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(true); + /** @var RequestInterface $cnRequest */ $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $casePath)); $rawResponse = ""; @@ -129,15 +128,13 @@ function runTest($case) $response = \GuzzleHttp\Psr7\parse_response($rawResponse); if (!$cn->validateResponse($cnRequest, $response)) { + echo "Invalid response.\n"; $stream->end(); $deferred->reject(); } else { $ms = echoStreamerFactory( $stream, - (new ResponseVerifier())->getPermessageDeflateOptions( - $cnRequest->getHeader('Sec-WebSocket-Extensions'), - $response->getHeader('Sec-WebSocket-Extensions') - ) + PermessageDeflateOptions::fromRequestOrResponse($response)[0] ); } } diff --git a/tests/ab/startServer.php b/tests/ab/startServer.php index f492e19..515065a 100644 --- a/tests/ab/startServer.php +++ b/tests/ab/startServer.php @@ -1,7 +1,5 @@