[WebSocket] Messaging

Fluent interface on MessageInterface::addFrame
RFC6455 Message unit tests
RFC handling TCP concatenation (refs #31)
This commit is contained in:
Chris Boden 2012-06-02 22:08:27 -04:00
parent 7790ef39a1
commit 54479da9d5
7 changed files with 91 additions and 9 deletions

View File

@ -21,13 +21,17 @@ class MessageParser {
return;
}
// Check frame
// If is control frame, do your thing
// Else, add to message
// Control frames (ping, pong, close) can be sent in between a fragmented message
$nextFrame = $from->WebSocket->version->newFrame();
$nextFrame->addBuffer($from->WebSocket->frame->extractOverflow());
$from->WebSocket->message->addFrame($from->WebSocket->frame);
unset($from->WebSocket->frame);
$from->WebSocket->frame = $nextFrame;
}
if ($from->WebSocket->message->isCoalesced()) {

View File

@ -36,6 +36,8 @@ class Message implements MessageInterface {
}
$this->_frame = $fragment;
return $this;
}
/**

View File

@ -17,6 +17,7 @@ interface MessageInterface {
/**
* @param FragmentInterface
* @return MessageInterface
*/
function addFrame(FrameInterface $fragment);

View File

@ -35,7 +35,6 @@ class Frame implements FrameInterface {
* @param bool Mask the payload
* @return Frame
* @throws InvalidArgumentException If the payload is not a valid UTF-8 string
* @throws BadMethodCallException If there is a problem with miss-matching parameters
* @throws LengthException If the payload is too big
*/
public static function create($payload, $final = true, $opcode = 1, $mask = false) {
@ -45,10 +44,6 @@ class Frame implements FrameInterface {
throw new \InvalidArgumentException("Payload is not a valid UTF-8 string");
}
if (false === (boolean)$final && $opcode !== static::OP_CONTINUE) {
throw new \BadMethodCallException("opcode MUST be 'continue' if the frame is not final");
}
$raw = (int)(boolean)$final . sprintf('%07b', (int)$opcode);
$plLen = strlen($payload);

View File

@ -39,6 +39,8 @@ class Message implements MessageInterface {
*/
public function addFrame(FrameInterface $fragment) {
$this->_frames->push($fragment);
return $this;
}
/**
@ -62,6 +64,7 @@ class Message implements MessageInterface {
try {
$len += $frame->getPayloadLength();
} catch (\UnderflowException $e) {
// Not an error, want the current amount buffered
}
}
@ -73,7 +76,7 @@ class Message implements MessageInterface {
*/
public function getPayload() {
if (!$this->isCoalesced()) {
throw new \UnderflowMessage('Message has not been put back together yet');
throw new \UnderflowException('Message has not been put back together yet');
}
$buffer = '';

View File

@ -249,9 +249,8 @@ class FrameTest extends \PHPUnit_Framework_TestCase {
$this->assertEquals($msg, $this->_frame->getPayload());
}
public function testCreate() {
public function testLongCreate() {
$len = 65525;
$len = 65575;
$pl = $this->generateRandomString($len);
$frame = Frame::create($pl, true, Frame::OP_PING);
@ -263,6 +262,14 @@ class FrameTest extends \PHPUnit_Framework_TestCase {
$this->assertEquals($pl, $frame->getPayload());
}
public function testReallyLongCreate() {
$len = 65575;
$frame = Frame::create($this->generateRandomString($len));
$this->assertEquals($len, $frame->getPayloadLength());
}
public function testExtractOverflow() {
$string1 = $this->generateRandomString();
$frame1 = Frame::create($string1);

View File

@ -0,0 +1,70 @@
<?php
namespace Ratchet\Tests\WebSocket\Version\RFC6455\Message;
use Ratchet\WebSocket\Version\RFC6455\Message;
use Ratchet\WebSocket\Version\RFC6455\Frame;
/**
* @covers Ratchet\WebSocket\Version\RFC6455\Message
*/
class MessageTest extends \PHPUnit_Framework_TestCase {
protected $message;
public function setUp() {
$this->message = new Message;
}
public function testNoFrames() {
$this->assertFalse($this->message->isCoalesced());
}
public function testNoFramesOpCode() {
$this->setExpectedException('UnderflowException');
$this->message->getOpCode();
}
public function testFragmentationPayload() {
$a = 'Hello ';
$b = 'World!';
$f1 = Frame::create($a, false);
$f2 = Frame::create($b, true, Frame::OP_CONTINUE);
$this->message->addFrame($f1)->addFrame($f2);
$this->assertEquals(strlen($a . $b), $this->message->getPayloadLength());
$this->assertEquals($a . $b, $this->message->getPayload());
}
public function testUnbufferedFragment() {
$this->message->addFrame(Frame::create('The quick brow', false));
$this->setExpectedException('UnderflowException');
$this->message->getPayload();
}
public function testGetOpCode() {
$this->message
->addFrame(Frame::create('The quick brow', false, Frame::OP_TEXT))
->addFrame(Frame::create('n fox jumps ov', false, Frame::OP_CONTINUE))
->addFrame(Frame::create('er the lazy dog', true, Frame::OP_CONTINUE))
;
$this->assertEquals(Frame::OP_TEXT, $this->message->getOpCode());
}
public function testGetUnBufferedPayloadLength() {
$this->message
->addFrame(Frame::create('The quick brow', false, Frame::OP_TEXT))
->addFrame(Frame::create('n fox jumps ov', false, Frame::OP_CONTINUE))
;
$this->assertEquals(28, $this->message->getPayloadLength());
}
public function testToString() {
$msg = 'Who likes short shorts?';
$this->message->addFrame(Frame::create($msg));
$this->assertEquals($msg, (string)$this->message);
}
}