Merge branch 'recursion'

This commit is contained in:
Chris Boden 2017-01-01 10:41:18 -05:00
commit 56aecde679
2 changed files with 49 additions and 6 deletions

View File

@ -55,17 +55,23 @@ class MessageBuffer {
$this->onControl = $onControl ?: function() {}; $this->onControl = $onControl ?: function() {};
} }
public function onData($data) {
while (strlen($data) > 0) {
$data = $this->processData($data);
}
}
/** /**
* @param string $data * @param string $data
* @return null * @return null
*/ */
public function onData($data) { private function processData($data) {
$this->messageBuffer ?: $this->messageBuffer = $this->newMessage(); $this->messageBuffer ?: $this->messageBuffer = $this->newMessage();
$this->frameBuffer ?: $this->frameBuffer = $this->newFrame(); $this->frameBuffer ?: $this->frameBuffer = $this->newFrame();
$this->frameBuffer->addBuffer($data); $this->frameBuffer->addBuffer($data);
if (!$this->frameBuffer->isCoalesced()) { if (!$this->frameBuffer->isCoalesced()) {
return; return '';
} }
$onMessage = $this->onMessage; $onMessage = $this->onMessage;
@ -82,7 +88,7 @@ class MessageBuffer {
$onControl($this->frameBuffer); $onControl($this->frameBuffer);
if (Frame::OP_CLOSE === $opcode) { if (Frame::OP_CLOSE === $opcode) {
return; return '';
} }
} else { } else {
$this->messageBuffer->addFrame($this->frameBuffer); $this->messageBuffer->addFrame($this->frameBuffer);
@ -101,9 +107,7 @@ class MessageBuffer {
$this->messageBuffer = null; $this->messageBuffer = null;
} }
if (strlen($overflow) > 0) { return $overflow;
$this->onData($overflow); // PHP doesn't do tail recursion :(
}
} }
/** /**

View File

@ -0,0 +1,39 @@
<?php
namespace Ratchet\RFC6455\Test\Unit\Messaging;
use Ratchet\RFC6455\Messaging\CloseFrameChecker;
use Ratchet\RFC6455\Messaging\Frame;
use Ratchet\RFC6455\Messaging\Message;
use Ratchet\RFC6455\Messaging\MessageBuffer;
class MessageBufferTest extends \PHPUnit_Framework_TestCase
{
/**
* This is to test that MessageBuffer can handle a large receive
* buffer with many many frames without blowing the stack (pre-v0.4 issue)
*/
public function testProcessingLotsOfFramesInASingleChunk() {
$frame = new Frame('a', true, Frame::OP_TEXT);
$frameRaw = $frame->getContents();
$data = str_repeat($frameRaw, 1000);
$messageCount = 0;
$messageBuffer = new MessageBuffer(
new CloseFrameChecker(),
function (Message $message) use (&$messageCount) {
$messageCount++;
$this->assertEquals('a', $message->getPayload());
},
null,
false
);
$messageBuffer->onData($data);
$this->assertEquals(1000, $messageCount);
}
}