From 59a30c3b721afdd7958718cf79496e1c5eafcbe7 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Tue, 12 Jan 2016 20:44:07 -0500 Subject: [PATCH 1/5] Replace slow validator with preg_match UTF8 check --- src/Encoding/NullValidator.php | 14 ---- src/Encoding/ToggleableValidator.php | 34 -------- src/Encoding/Validator.php | 93 --------------------- src/Encoding/ValidatorInterface.php | 15 ---- src/Handshake/Negotiator.php | 10 +-- src/Messaging/Streaming/MessageStreamer.php | 12 +-- tests/ab/clientRunner.php | 3 - tests/ab/startServer.php | 7 +- 8 files changed, 6 insertions(+), 182 deletions(-) delete mode 100644 src/Encoding/NullValidator.php delete mode 100644 src/Encoding/ToggleableValidator.php delete mode 100644 src/Encoding/Validator.php delete mode 100644 src/Encoding/ValidatorInterface.php diff --git a/src/Encoding/NullValidator.php b/src/Encoding/NullValidator.php deleted file mode 100644 index 6cc7515..0000000 --- a/src/Encoding/NullValidator.php +++ /dev/null @@ -1,14 +0,0 @@ -validationResponse; - } -} \ No newline at end of file diff --git a/src/Encoding/ToggleableValidator.php b/src/Encoding/ToggleableValidator.php deleted file mode 100644 index 3178bbc..0000000 --- a/src/Encoding/ToggleableValidator.php +++ /dev/null @@ -1,34 +0,0 @@ -validator = new Validator; - $this->on = (boolean)$on; - } - - /** - * {@inheritdoc} - */ - public function checkEncoding($str, $encoding) { - if (!(boolean)$this->on) { - return true; - } - - return $this->validator->checkEncoding($str, $encoding); - } -} diff --git a/src/Encoding/Validator.php b/src/Encoding/Validator.php deleted file mode 100644 index 5b2f7f4..0000000 --- a/src/Encoding/Validator.php +++ /dev/null @@ -1,93 +0,0 @@ -hasMbString = extension_loaded('mbstring'); - $this->hasIconv = extension_loaded('iconv'); - } - - /** - * @param string $str The value to check the encoding - * @param string $against The type of encoding to check against - * @return bool - */ - public function checkEncoding($str, $against) { - if ('UTF-8' === $against) { - return $this->isUtf8($str); - } - - if ($this->hasMbString) { - return mb_check_encoding($str, $against); - } elseif ($this->hasIconv) { - return ($str === iconv($against, "{$against}//IGNORE", $str)); - } - - return true; - } - - protected function isUtf8($str) { - if ($this->hasMbString) { - if (false === mb_check_encoding($str, 'UTF-8')) { - return false; - } - } elseif ($this->hasIconv) { - if ($str !== iconv('UTF-8', 'UTF-8//IGNORE', $str)) { - return false; - } - } - - $state = static::UTF8_ACCEPT; - - for ($i = 0, $len = strlen($str); $i < $len; $i++) { - $state = static::$dfa[256 + ($state << 4) + static::$dfa[ord($str[$i])]]; - - if (static::UTF8_REJECT === $state) { - return false; - } - } - - return true; - } -} diff --git a/src/Encoding/ValidatorInterface.php b/src/Encoding/ValidatorInterface.php deleted file mode 100644 index 3870157..0000000 --- a/src/Encoding/ValidatorInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -verifier = new RequestVerifier; - - $this->validator = $validator; } /** diff --git a/src/Messaging/Streaming/MessageStreamer.php b/src/Messaging/Streaming/MessageStreamer.php index fea0c9f..e0ef3bd 100644 --- a/src/Messaging/Streaming/MessageStreamer.php +++ b/src/Messaging/Streaming/MessageStreamer.php @@ -1,6 +1,5 @@ validator = $encodingValidator; $this->closeFrameChecker = $frameChecker; $this->checkForMask = (bool)$expectMask; @@ -166,7 +158,7 @@ class MessageStreamer { return $this->newCloseFrame(Frame::CLOSE_PROTOCOL); } - if (!$this->validator->checkEncoding(substr($bin, 2), 'UTF-8')) { + if (!preg_match('//u', substr($bin, 2))) { return $this->newCloseFrame(Frame::CLOSE_BAD_PAYLOAD); } @@ -201,7 +193,7 @@ class MessageStreamer { */ public function checkMessage(MessageInterface $message) { if (!$message->isBinary()) { - if (!$this->validator->checkEncoding($message->getPayload(), 'UTF-8')) { + if (!preg_match('//u', $message->getPayload())) { return Frame::CLOSE_BAD_PAYLOAD; } } diff --git a/tests/ab/clientRunner.php b/tests/ab/clientRunner.php index 13a99a7..ee8897f 100644 --- a/tests/ab/clientRunner.php +++ b/tests/ab/clientRunner.php @@ -19,7 +19,6 @@ $factory = new \React\SocketClient\Connector($loop, $dnsResolver); function echoStreamerFactory($conn) { return new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer( - new \Ratchet\RFC6455\Encoding\Validator, new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker, function (\Ratchet\RFC6455\Messaging\Protocol\MessageInterface $msg) use ($conn) { /** @var Frame $frame */ @@ -72,7 +71,6 @@ function getTestCases() { $deferred->reject(); } else { $ms = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer( - new \Ratchet\RFC6455\Encoding\Validator, new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker, function (\Ratchet\RFC6455\Messaging\Protocol\MessageInterface $msg) use ($deferred, $stream) { $deferred->resolve($msg->getPayload()); @@ -180,7 +178,6 @@ function createReport() { $deferred->reject(); } else { $ms = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer( - new \Ratchet\RFC6455\Encoding\Validator, new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker, function (\Ratchet\RFC6455\Messaging\Protocol\MessageInterface $msg) use ($deferred, $stream) { $deferred->resolve($msg->getPayload()); diff --git a/tests/ab/startServer.php b/tests/ab/startServer.php index 58b7814..778318d 100644 --- a/tests/ab/startServer.php +++ b/tests/ab/startServer.php @@ -10,13 +10,12 @@ $loop = \React\EventLoop\Factory::create(); $socket = new \React\Socket\Server($loop); $server = new \React\Http\Server($socket); -$encodingValidator = new \Ratchet\RFC6455\Encoding\Validator; $closeFrameChecker = new \Ratchet\RFC6455\Messaging\Protocol\CloseFrameChecker; -$negotiator = new \Ratchet\RFC6455\Handshake\Negotiator($encodingValidator); +$negotiator = new \Ratchet\RFC6455\Handshake\Negotiator; $uException = new \UnderflowException; -$server->on('request', function (\React\Http\Request $request, \React\Http\Response $response) use ($negotiator, $encodingValidator, $closeFrameChecker, $uException) { +$server->on('request', function (\React\Http\Request $request, \React\Http\Response $response) use ($negotiator, $closeFrameChecker, $uException) { $psrRequest = new \GuzzleHttp\Psr7\Request($request->getMethod(), $request->getPath(), $request->getHeaders()); $negotiatorResponse = $negotiator->handshake($psrRequest); @@ -34,7 +33,7 @@ $server->on('request', function (\React\Http\Request $request, \React\Http\Respo return; } - $parser = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer($encodingValidator, $closeFrameChecker, function(MessageInterface $message) use ($response) { + $parser = new \Ratchet\RFC6455\Messaging\Streaming\MessageStreamer($closeFrameChecker, function(MessageInterface $message) use ($response) { $response->write($message->getContents()); }, function(FrameInterface $frame) use ($response, &$parser) { switch ($frame->getOpCode()) { From 8aef77c11887ddd5aa4b8017fc2e3e66ed32d631 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Wed, 27 Jan 2016 18:41:35 -0500 Subject: [PATCH 2/5] Attempt newer HHVM on TravisCI --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b5758b7..9f61e42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ php: - 5.5 - 5.6 - 7 - - hhvm + - hhvm-nightly matrix: allow_failures: @@ -21,4 +21,4 @@ before_script: - sh tests/ab/run_ab_tests.sh script: - - phpunit \ No newline at end of file + - phpunit From 04a7b41d5a0a733f07a8ffdf0dc57e95eaea72ba Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Wed, 27 Jan 2016 18:55:28 -0500 Subject: [PATCH 3/5] Revert HHVM version change on TravisCI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9f61e42..24a8308 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ php: - 5.5 - 5.6 - 7 - - hhvm-nightly + - hhvm matrix: allow_failures: From f6bf0ca07c1b05c9e881e9b9cd40a8299c611a32 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Wed, 27 Jan 2016 19:59:58 -0500 Subject: [PATCH 4/5] Use mbstring if available HHVM seems to have mbstring loaded/enabled by default --- src/Messaging/Streaming/MessageStreamer.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Messaging/Streaming/MessageStreamer.php b/src/Messaging/Streaming/MessageStreamer.php index e0ef3bd..3b999d9 100644 --- a/src/Messaging/Streaming/MessageStreamer.php +++ b/src/Messaging/Streaming/MessageStreamer.php @@ -158,7 +158,7 @@ class MessageStreamer { return $this->newCloseFrame(Frame::CLOSE_PROTOCOL); } - if (!preg_match('//u', substr($bin, 2))) { + if (!$this->checkUtf8(substr($bin, 2))) { return $this->newCloseFrame(Frame::CLOSE_BAD_PAYLOAD); } @@ -193,7 +193,7 @@ class MessageStreamer { */ public function checkMessage(MessageInterface $message) { if (!$message->isBinary()) { - if (!preg_match('//u', $message->getPayload())) { + if (!$this->checkUtf8($message->getPayload())) { return Frame::CLOSE_BAD_PAYLOAD; } } @@ -201,6 +201,14 @@ class MessageStreamer { return true; } + private function checkUtf8($string) { + if (extension_loaded('mbstring')) { + return mb_check_encoding($string, 'UTF-8'); + } + + return preg_match('//u', $string); + } + /** * @return \Ratchet\RFC6455\Messaging\Protocol\MessageInterface */ From 797df1b318518cd8020ffb17a41e8687e64e1850 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Wed, 27 Jan 2016 23:41:03 -0500 Subject: [PATCH 5/5] HHVM not allowed to fail --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 24a8308..b1c7c1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,6 @@ php: - 7 - hhvm -matrix: - allow_failures: - - php: hhvm - before_install: - export PATH=$HOME/.local/bin:$PATH - pip install autobahntestsuite --user `whoami`