API docs and message length
RFC6455 Message::getPayloadLenght now returns a value
This commit is contained in:
parent
852e5777e3
commit
381dd7bab6
@ -16,6 +16,9 @@ use Guzzle\Http\Message\Response;
|
|||||||
* @link http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
|
* @link http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
|
||||||
*/
|
*/
|
||||||
class Hixie76 implements VersionInterface {
|
class Hixie76 implements VersionInterface {
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public static function isProtocol(RequestInterface $request) {
|
public static function isProtocol(RequestInterface $request) {
|
||||||
return !(null === $request->getHeader('Sec-WebSocket-Key2'));
|
return !(null === $request->getHeader('Sec-WebSocket-Key2'));
|
||||||
}
|
}
|
||||||
@ -40,14 +43,23 @@ class Hixie76 implements VersionInterface {
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Hixie76\Message
|
||||||
|
*/
|
||||||
public function newMessage() {
|
public function newMessage() {
|
||||||
return new Hixie76\Message;
|
return new Hixie76\Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Hixie76\Frame
|
||||||
|
*/
|
||||||
public function newFrame() {
|
public function newFrame() {
|
||||||
return new Hixie76\Frame;
|
return new Hixie76\Frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function frame($message, $mask = true) {
|
public function frame($message, $mask = true) {
|
||||||
return chr(0) . $message . chr(255);
|
return chr(0) . $message . chr(255);
|
||||||
}
|
}
|
||||||
|
@ -12,26 +12,44 @@ class Frame implements FrameInterface {
|
|||||||
*/
|
*/
|
||||||
protected $_data = '';
|
protected $_data = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isCoalesced() {
|
public function isCoalesced() {
|
||||||
return (boolean)($this->_data[0] == chr(0) && substr($this->_data, -1) == chr(255));
|
return (boolean)($this->_data[0] == chr(0) && substr($this->_data, -1) == chr(255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function addBuffer($buf) {
|
public function addBuffer($buf) {
|
||||||
$this->_data .= (string)$buf;
|
$this->_data .= (string)$buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isFinal() {
|
public function isFinal() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isMasked() {
|
public function isMasked() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getOpcode() {
|
public function getOpcode() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayloadLength() {
|
public function getPayloadLength() {
|
||||||
if (!$this->isCoalesced()) {
|
if (!$this->isCoalesced()) {
|
||||||
throw new \UnderflowException('Not enough of the message has been buffered to determine the length of the payload');
|
throw new \UnderflowException('Not enough of the message has been buffered to determine the length of the payload');
|
||||||
@ -40,10 +58,16 @@ class Frame implements FrameInterface {
|
|||||||
return strlen($this->_data) - 2;
|
return strlen($this->_data) - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getMaskingKey() {
|
public function getMaskingKey() {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayload() {
|
public function getPayload() {
|
||||||
if (!$this->isCoalesced()) {
|
if (!$this->isCoalesced()) {
|
||||||
return new \UnderflowException('Not enough data buffered to read payload');
|
return new \UnderflowException('Not enough data buffered to read payload');
|
||||||
|
@ -9,10 +9,16 @@ class Message implements MessageInterface {
|
|||||||
*/
|
*/
|
||||||
protected $_frame = null;
|
protected $_frame = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function __toString() {
|
public function __toString() {
|
||||||
return $this->getPayload();
|
return $this->getPayload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isCoalesced() {
|
public function isCoalesced() {
|
||||||
if (!($this->_frame instanceof FrameInterface)) {
|
if (!($this->_frame instanceof FrameInterface)) {
|
||||||
return false;
|
return false;
|
||||||
@ -21,6 +27,9 @@ class Message implements MessageInterface {
|
|||||||
return $this->_frame->isCoalesced();
|
return $this->_frame->isCoalesced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function addFrame(FrameInterface $fragment) {
|
public function addFrame(FrameInterface $fragment) {
|
||||||
if (null !== $this->_frame) {
|
if (null !== $this->_frame) {
|
||||||
throw new \OverflowException('Hixie76 does not support multiple framing of messages');
|
throw new \OverflowException('Hixie76 does not support multiple framing of messages');
|
||||||
@ -29,15 +38,24 @@ class Message implements MessageInterface {
|
|||||||
$this->_frame = $fragment;
|
$this->_frame = $fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getOpcode() {
|
public function getOpcode() {
|
||||||
// Hixie76 only supported text messages
|
// Hixie76 only supported text messages
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayloadLength() {
|
public function getPayloadLength() {
|
||||||
throw new \DomainException('Please sir, may I have some code? (' . __FUNCTION__ . ')');
|
throw new \DomainException('Please sir, may I have some code? (' . __FUNCTION__ . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayload() {
|
public function getPayload() {
|
||||||
if (!$this->isCoalesced()) {
|
if (!$this->isCoalesced()) {
|
||||||
throw new \UnderflowException('Message has not been fully buffered yet');
|
throw new \UnderflowException('Message has not been fully buffered yet');
|
||||||
|
@ -20,14 +20,16 @@ class RFC6455 implements VersionInterface {
|
|||||||
$this->_verifier = new HandshakeVerifier;
|
$this->_verifier = new HandshakeVerifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public static function isProtocol(RequestInterface $request) {
|
public static function isProtocol(RequestInterface $request) {
|
||||||
$version = (int)$request->getHeader('Sec-WebSocket-Version', -1);
|
$version = (int)$request->getHeader('Sec-WebSocket-Version', -1);
|
||||||
return (13 === $version);
|
return (13 === $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* {@inheritdoc}
|
||||||
* I kept this as an array and combined in App for future considerations...easier to add a subprotol as a key value than edit a string
|
|
||||||
* @todo Decide what to do on failure...currently throwing an exception and I think socket connection is closed. Should be sending 40x error - but from where?
|
* @todo Decide what to do on failure...currently throwing an exception and I think socket connection is closed. Should be sending 40x error - but from where?
|
||||||
*/
|
*/
|
||||||
public function handshake(RequestInterface $request) {
|
public function handshake(RequestInterface $request) {
|
||||||
@ -62,6 +64,7 @@ class RFC6455 implements VersionInterface {
|
|||||||
* Thanks to @lemmingzshadow for the code on decoding a HyBi-10 frame
|
* Thanks to @lemmingzshadow for the code on decoding a HyBi-10 frame
|
||||||
* @link https://github.com/lemmingzshadow/php-websocket
|
* @link https://github.com/lemmingzshadow/php-websocket
|
||||||
* @todo look into what happens when false is returned here
|
* @todo look into what happens when false is returned here
|
||||||
|
* @todo This is needed when a client is created - needs re-write as missing parts of protocol
|
||||||
* @param string
|
* @param string
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +27,9 @@ class Frame implements FrameInterface {
|
|||||||
*/
|
*/
|
||||||
protected $_pay_check = -1;
|
protected $_pay_check = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isCoalesced() {
|
public function isCoalesced() {
|
||||||
try {
|
try {
|
||||||
$payload_length = $this->getPayloadLength();
|
$payload_length = $this->getPayloadLength();
|
||||||
@ -38,6 +41,9 @@ class Frame implements FrameInterface {
|
|||||||
return $payload_length + $payload_start === $this->_bytes_rec;
|
return $payload_length + $payload_start === $this->_bytes_rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function addBuffer($buf) {
|
public function addBuffer($buf) {
|
||||||
$buf = (string)$buf;
|
$buf = (string)$buf;
|
||||||
|
|
||||||
@ -45,6 +51,9 @@ class Frame implements FrameInterface {
|
|||||||
$this->_bytes_rec += strlen($buf);
|
$this->_bytes_rec += strlen($buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isFinal() {
|
public function isFinal() {
|
||||||
if ($this->_bytes_rec < 1) {
|
if ($this->_bytes_rec < 1) {
|
||||||
throw new \UnderflowException('Not enough bytes received to determine if this is the final frame in message');
|
throw new \UnderflowException('Not enough bytes received to determine if this is the final frame in message');
|
||||||
@ -54,6 +63,9 @@ class Frame implements FrameInterface {
|
|||||||
return (boolean)(int)$fbb[0];
|
return (boolean)(int)$fbb[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isMasked() {
|
public function isMasked() {
|
||||||
if ($this->_bytes_rec < 2) {
|
if ($this->_bytes_rec < 2) {
|
||||||
throw new \UnderflowException("Not enough bytes received ({$this->_bytes_rec}) to determine if mask is set");
|
throw new \UnderflowException("Not enough bytes received ({$this->_bytes_rec}) to determine if mask is set");
|
||||||
@ -62,6 +74,9 @@ class Frame implements FrameInterface {
|
|||||||
return (boolean)bindec(substr(sprintf('%08b', ord($this->_data[1])), 0, 1));
|
return (boolean)bindec(substr(sprintf('%08b', ord($this->_data[1])), 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getOpcode() {
|
public function getOpcode() {
|
||||||
if ($this->_bytes_rec < 1) {
|
if ($this->_bytes_rec < 1) {
|
||||||
throw new \UnderflowException('Not enough bytes received to determine opcode');
|
throw new \UnderflowException('Not enough bytes received to determine opcode');
|
||||||
@ -125,6 +140,9 @@ class Frame implements FrameInterface {
|
|||||||
return (1 + $this->getNumPayloadBits()) / 8;
|
return (1 + $this->getNumPayloadBits()) / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayloadLength() {
|
public function getPayloadLength() {
|
||||||
if ($this->_pay_len_def !== -1) {
|
if ($this->_pay_len_def !== -1) {
|
||||||
return $this->_pay_len_def;
|
return $this->_pay_len_def;
|
||||||
@ -151,6 +169,9 @@ class Frame implements FrameInterface {
|
|||||||
return $this->getPayloadLength();
|
return $this->getPayloadLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getMaskingKey() {
|
public function getMaskingKey() {
|
||||||
if (!$this->isMasked()) {
|
if (!$this->isMasked()) {
|
||||||
return '';
|
return '';
|
||||||
@ -166,10 +187,16 @@ class Frame implements FrameInterface {
|
|||||||
return substr($this->_data, $start, $length);
|
return substr($this->_data, $start, $length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayloadStartingByte() {
|
public function getPayloadStartingByte() {
|
||||||
return 1 + $this->getNumPayloadBytes() + strlen($this->getMaskingKey());
|
return 1 + $this->getNumPayloadBytes() + strlen($this->getMaskingKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayload() {
|
public function getPayload() {
|
||||||
if (!$this->isCoalesced()) {
|
if (!$this->isCoalesced()) {
|
||||||
throw new \UnderflowException('Can not return partial message');
|
throw new \UnderflowException('Can not return partial message');
|
||||||
|
@ -13,10 +13,16 @@ class Message implements MessageInterface {
|
|||||||
$this->_frames = new \SplDoublyLinkedList;
|
$this->_frames = new \SplDoublyLinkedList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function __toString() {
|
public function __toString() {
|
||||||
return $this->getPayload();
|
return $this->getPayload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function isCoalesced() {
|
public function isCoalesced() {
|
||||||
if (count($this->_frames) == 0) {
|
if (count($this->_frames) == 0) {
|
||||||
return false;
|
return false;
|
||||||
@ -28,6 +34,7 @@ class Message implements MessageInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
* @todo Should I allow addFrame if the frame is not coalesced yet? I believe I'm assuming this class will only receive fully formed frame messages
|
* @todo Should I allow addFrame if the frame is not coalesced yet? I believe I'm assuming this class will only receive fully formed frame messages
|
||||||
* @todo Also, I should perhaps check the type...control frames (ping/pong/close) are not to be considered part of a message
|
* @todo Also, I should perhaps check the type...control frames (ping/pong/close) are not to be considered part of a message
|
||||||
*/
|
*/
|
||||||
@ -35,6 +42,9 @@ class Message implements MessageInterface {
|
|||||||
$this->_frames->push($fragment);
|
$this->_frames->push($fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getOpcode() {
|
public function getOpcode() {
|
||||||
if (count($this->_frames) == 0) {
|
if (count($this->_frames) == 0) {
|
||||||
throw new \UnderflowException('No frames have been added to this message');
|
throw new \UnderflowException('No frames have been added to this message');
|
||||||
@ -43,10 +53,25 @@ class Message implements MessageInterface {
|
|||||||
return $this->_frames->bottom()->getOpcode();
|
return $this->_frames->bottom()->getOpcode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayloadLength() {
|
public function getPayloadLength() {
|
||||||
throw new \DomainException('Please sir, may I have some code? (' . __FUNCTION__ . ')');
|
$len = 0;
|
||||||
|
|
||||||
|
foreach ($this->_frames as $frame) {
|
||||||
|
try {
|
||||||
|
$len += $frame->getPayloadLength();
|
||||||
|
} catch (\UnderflowException $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function getPayload() {
|
public function getPayload() {
|
||||||
if (!$this->isCoalesced()) {
|
if (!$this->isCoalesced()) {
|
||||||
throw new \UnderflowMessage('Message has not been put back together yet');
|
throw new \UnderflowMessage('Message has not been put back together yet');
|
||||||
|
Loading…
Reference in New Issue
Block a user