[WebSocket] Hixie refactoring
Created parent interface for messages and frames Created Hixie Connection Applied updated interfaces to Hixie versions Removed __toString on msgs/frames since there could be 2-3 types returned
This commit is contained in:
parent
439ac1234f
commit
49d68ba7df
28
src/Ratchet/WebSocket/Version/DataInterface.php
Normal file
28
src/Ratchet/WebSocket/Version/DataInterface.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version;
|
||||
|
||||
interface DataInterface {
|
||||
/**
|
||||
* Determine if the message is complete or still fragmented
|
||||
* @return bool
|
||||
*/
|
||||
function isCoalesced();
|
||||
|
||||
/**
|
||||
* Get the number of bytes the payload is set to be
|
||||
* @return int
|
||||
*/
|
||||
function getPayloadLength();
|
||||
|
||||
/**
|
||||
* Get the payload (message) sent from peer
|
||||
* @return string
|
||||
*/
|
||||
function getPayload();
|
||||
|
||||
/**
|
||||
* Get raw contents of the message
|
||||
* @return string
|
||||
*/
|
||||
function getContents();
|
||||
}
|
@ -1,29 +1,21 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version;
|
||||
|
||||
interface FrameInterface {
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isCoalesced();
|
||||
|
||||
interface FrameInterface extends DataInterface {
|
||||
/**
|
||||
* Add incoming data to the frame from peer
|
||||
* @param string
|
||||
* @todo Theoretically, there won't be a buffer overflow (end of frame + start of new frame) - but test later, return a string with overflow here
|
||||
*/
|
||||
function addBuffer($buf);
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
// function isFragment();
|
||||
|
||||
/**
|
||||
* Is this the final frame in a fragmented message?
|
||||
* @return bool
|
||||
*/
|
||||
function isFinal();
|
||||
|
||||
/**
|
||||
* Was the payload masked?
|
||||
* @return bool
|
||||
*/
|
||||
function isMasked();
|
||||
@ -36,21 +28,11 @@ interface FrameInterface {
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getPayloadLength();
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
// function getReceivedPayloadLength();
|
||||
//function getReceivedPayloadLength();
|
||||
|
||||
/**
|
||||
* 32-big string
|
||||
* @return string
|
||||
*/
|
||||
function getMaskingKey();
|
||||
|
||||
/**
|
||||
* @param string
|
||||
*/
|
||||
function getPayload();
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\MessageInterface;
|
||||
use Ratchet\WebSocket\Version\Hixie76\Connection;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\Response;
|
||||
use Ratchet\WebSocket\Version\Hixie76\Frame;
|
||||
|
||||
/**
|
||||
* FOR THE LOVE OF BEER, PLEASE PLEASE PLEASE DON'T allow the use of this in your application!
|
||||
@ -22,6 +26,9 @@ class Hixie76 implements VersionInterface {
|
||||
return !(null === $request->getHeader('Sec-WebSocket-Key2', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getVersionNumber() {
|
||||
return 0;
|
||||
}
|
||||
@ -46,25 +53,47 @@ class Hixie76 implements VersionInterface {
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hixie76\Message
|
||||
*/
|
||||
public function newMessage() {
|
||||
return new Hixie76\Message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hixie76\Frame
|
||||
*/
|
||||
public function newFrame() {
|
||||
return new Hixie76\Frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function frame($message, $mask = true) {
|
||||
return chr(0) . $message . chr(255);
|
||||
public function upgradeConnection(ConnectionInterface $conn, MessageInterface $coalescedCallback) {
|
||||
$upgraded = new Connection($conn);
|
||||
|
||||
if (!isset($upgraded->WebSocket)) {
|
||||
$upgraded->WebSocket = new \StdClass;
|
||||
}
|
||||
|
||||
$upgraded->WebSocket->coalescedCallback = $coalescedCallback;
|
||||
|
||||
return $upgraded;
|
||||
}
|
||||
|
||||
public function onMessage(ConnectionInterface $from, $data) {
|
||||
$overflow = '';
|
||||
|
||||
if (!isset($from->WebSocket->frame)) {
|
||||
$from->WebSocket->frame = $this->newFrame();
|
||||
}
|
||||
|
||||
$from->WebSocket->frame->addBuffer($data);
|
||||
if ($from->WebSocket->frame->isCoalesced()) {
|
||||
$overflow = $from->WebSocket->frame->extractOverflow();
|
||||
|
||||
$parsed = $from->WebSocket->frame->getPayload();
|
||||
unset($from->WebSocket->frame);
|
||||
|
||||
$from->WebSocket->coalescedCallback->onMessage($from, $parsed);
|
||||
|
||||
unset($from->WebSocket->frame);
|
||||
}
|
||||
|
||||
if (strlen($overflow) > 0) {
|
||||
$this->onMessage($from, $overflow);
|
||||
}
|
||||
}
|
||||
|
||||
public function newFrame() {
|
||||
return new Frame;
|
||||
}
|
||||
|
||||
public function generateKeyNumber($key) {
|
||||
|
16
src/Ratchet/WebSocket/Version/Hixie76/Connection.php
Normal file
16
src/Ratchet/WebSocket/Version/Hixie76/Connection.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version\Hixie76;
|
||||
use Ratchet\AbstractConnectionDecorator;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class Connection extends AbstractConnectionDecorator {
|
||||
public function send($msg) {
|
||||
return $this->getConnection()->send(chr(0) . $msg . chr(255));
|
||||
}
|
||||
|
||||
public function close() {
|
||||
return $this->getConnection()->close();
|
||||
}
|
||||
}
|
@ -75,4 +75,12 @@ class Frame implements FrameInterface {
|
||||
|
||||
return substr($this->_data, 1, strlen($this->_data) - 2);
|
||||
}
|
||||
|
||||
public function getContents() {
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
public function extractOverflow() {
|
||||
return '';
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version\Hixie76;
|
||||
use Ratchet\WebSocket\Version\MessageInterface;
|
||||
use Ratchet\WebSocket\Version\FrameInterface;
|
||||
|
||||
class Message implements MessageInterface {
|
||||
/**
|
||||
* @var Ratchet\WebSocket\Version\FrameInterface
|
||||
*/
|
||||
protected $_frame = null;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->getPayload();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCoalesced() {
|
||||
if (!($this->_frame instanceof FrameInterface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->_frame->isCoalesced();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addFrame(FrameInterface $fragment) {
|
||||
if (null !== $this->_frame) {
|
||||
throw new \OverflowException('Hixie76 does not support multiple framing of messages');
|
||||
}
|
||||
|
||||
$this->_frame = $fragment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOpcode() {
|
||||
// Hixie76 only supported text messages
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPayloadLength() {
|
||||
throw new \DomainException('Please sir, may I have some code? (' . __FUNCTION__ . ')');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPayload() {
|
||||
if (!$this->isCoalesced()) {
|
||||
throw new \UnderflowException('Message has not been fully buffered yet');
|
||||
}
|
||||
|
||||
return $this->_frame->getPayload();
|
||||
}
|
||||
}
|
@ -1,15 +1,7 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version;
|
||||
|
||||
/**
|
||||
* @todo Consider making parent interface/composite for Message/Frame with (isCoalesced, getOpcdoe, getPayloadLength, getPayload)
|
||||
*/
|
||||
interface MessageInterface {
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isCoalesced();
|
||||
|
||||
interface MessageInterface extends DataInterface {
|
||||
/**
|
||||
* @param FragmentInterface
|
||||
* @return MessageInterface
|
||||
@ -20,14 +12,4 @@ interface MessageInterface {
|
||||
* @return int
|
||||
*/
|
||||
function getOpcode();
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getPayloadLength();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getPayload();
|
||||
}
|
@ -2,14 +2,14 @@
|
||||
namespace Ratchet\WebSocket\Version\RFC6455;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\AbstractConnectionDecorator;
|
||||
use Ratchet\WebSocket\Version\FrameInterface;
|
||||
use Ratchet\WebSocket\Version\DataInterface;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class Connection extends AbstractConnectionDecorator {
|
||||
public function send($msg) {
|
||||
if (!($msg instanceof FrameInterface)) {
|
||||
if (!($msg instanceof DataInterface)) {
|
||||
$msg = new Frame($msg);
|
||||
}
|
||||
|
||||
|
@ -13,13 +13,6 @@ class Message implements MessageInterface {
|
||||
$this->_frames = new \SplDoublyLinkedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->getPayload();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -87,4 +80,21 @@ class Message implements MessageInterface {
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContents() {
|
||||
if (!$this->isCoalesced()) {
|
||||
throw new \UnderflowException("Message has not been put back together yet");
|
||||
}
|
||||
|
||||
$buffer = '';
|
||||
|
||||
foreach ($this->_frames as $frame) {
|
||||
$buffer .= $frame->getContents();
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Ratchet\WebSocket\Version;
|
||||
use Ratchet\MessageInterface;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
@ -25,20 +26,26 @@ interface VersionInterface extends MessageInterface {
|
||||
* Perform the handshake and return the response headers
|
||||
* @param Guzzle\Http\Message\RequestInterface
|
||||
* @return Guzzle\Http\Message\Response
|
||||
* @throws InvalidArgumentException If the HTTP handshake is mal-formed
|
||||
* @throws UnderflowException If the message hasn't finished buffering (not yet implemented, theoretically will only happen with Hixie version)
|
||||
*/
|
||||
function handshake(RequestInterface $request);
|
||||
|
||||
/**
|
||||
* @param Ratchet\ConnectionInterface
|
||||
* @param Ratchet\MessageInterface
|
||||
* @return Ratchet\ConnectionInterface
|
||||
*/
|
||||
function upgradeConnection(ConnectionInterface $conn, MessageInterface $coalescedCallback);
|
||||
|
||||
/**
|
||||
* @return MessageInterface
|
||||
*/
|
||||
function newMessage();
|
||||
//function newMessage();
|
||||
|
||||
/**
|
||||
* @return FrameInterface
|
||||
*/
|
||||
function newFrame();
|
||||
//function newFrame();
|
||||
|
||||
/**
|
||||
* @param string
|
||||
|
@ -61,7 +61,7 @@ class WsServer implements MessageComponentInterface {
|
||||
$this->versioner
|
||||
->enableVersion(new Version\RFC6455($component))
|
||||
->enableVersion(new Version\HyBi10($component))
|
||||
//->enableVersion(new Version\Hixie76)
|
||||
->enableVersion(new Version\Hixie76)
|
||||
;
|
||||
|
||||
$this->_decorating = $component;
|
||||
|
@ -57,7 +57,7 @@ class HyBi10Test extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testUnframeMatchesPreFraming() {
|
||||
$string = 'Hello World!';
|
||||
$framed = $this->_version->frame($string);
|
||||
$framed = $this->_version->newFrame($string)->getContents();
|
||||
|
||||
$frame = new Frame;
|
||||
$frame->addBuffer($framed);
|
||||
|
@ -60,11 +60,4 @@ class MessageTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@ class RFC6455Test extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testUnframeMatchesPreFraming() {
|
||||
$string = 'Hello World!';
|
||||
$framed = $this->version->frame($string);
|
||||
$framed = $this->version->newFrame($string)->getContents();
|
||||
|
||||
$frame = new Frame;
|
||||
$frame->addBuffer($framed);
|
||||
|
Loading…
Reference in New Issue
Block a user