From 98aea77b781521dbec0d0cec6592d14d8703fbd3 Mon Sep 17 00:00:00 2001 From: Alexander Valinurov Date: Thu, 28 Jan 2016 17:33:42 +0300 Subject: [PATCH 1/2] code style fixes --- src/Devristo/Phpws/Client/Connector.php | 23 +++- src/Devristo/Phpws/Client/WebSocket.php | 83 ++++++++---- .../Exceptions/WebSocketFrameSizeMismatch.php | 7 +- .../WebSocketInvalidChallengeResponse.php | 4 +- .../WebSocketInvalidKeyException.php | 4 +- .../Exceptions/WebSocketInvalidUrlScheme.php | 4 +- .../WebSocketMessageNotFinalised.php | 4 +- src/Devristo/Phpws/Framing/WebSocketFrame.php | 103 +++++++++++---- .../Phpws/Framing/WebSocketFrame76.php | 23 +++- .../Phpws/Framing/WebSocketFrameInterface.php | 5 +- .../Phpws/Framing/WebSocketOpcode.php | 21 ++- .../Phpws/Messaging/MessageInterface.php | 6 +- .../Phpws/Messaging/RemoteEventMessage.php | 57 +++++--- .../Phpws/Messaging/WebSocketMessage.php | 39 ++++-- .../Phpws/Messaging/WebSocketMessage76.php | 25 +++- .../Messaging/WebSocketMessageInterface.php | 4 +- src/Devristo/Phpws/Protocol/Handshake.php | 37 ++++-- .../Phpws/Protocol/StackTransport.php | 109 +++++++++++++--- .../Phpws/Protocol/TransportInterface.php | 6 +- .../Phpws/Protocol/WebSocketConnection.php | 71 ++++++---- .../Phpws/Protocol/WebSocketTransport.php | 95 ++++++++++---- .../Protocol/WebSocketTransportFactory.php | 14 +- .../Protocol/WebSocketTransportFlash.php | 38 +++++- .../Protocol/WebSocketTransportHixie.php | 55 +++++--- .../Phpws/Protocol/WebSocketTransportHybi.php | 111 +++++++++------- .../Protocol/WebSocketTransportInterface.php | 26 +++- .../Phpws/Protocol/WebsocketTransportRole.php | 4 +- .../Phpws/Reflection/FullAccessWrapper.php | 23 ++-- .../RemoteEvent/RemoteEventTransport.php | 105 ++++++++++----- .../Phpws/RemoteEvent/RemoteEvents.php | 32 +++-- src/Devristo/Phpws/RemoteEvent/Room.php | 23 +++- src/Devristo/Phpws/Server/OriginEnforcer.php | 15 ++- .../Phpws/Server/UriHandler/ClientRouter.php | 122 ++++++++++++------ .../Server/UriHandler/WebSocketUriHandler.php | 34 ++++- .../WebSocketUriHandlerInterface.php | 11 +- src/Devristo/Phpws/Server/WebSocketServer.php | 108 ++++++++++------ 36 files changed, 1013 insertions(+), 438 deletions(-) diff --git a/src/Devristo/Phpws/Client/Connector.php b/src/Devristo/Phpws/Client/Connector.php index d650367..d1b6edf 100644 --- a/src/Devristo/Phpws/Client/Connector.php +++ b/src/Devristo/Phpws/Client/Connector.php @@ -5,20 +5,31 @@ use React\SocketClient\Connector as BaseConnector; use React\EventLoop\LoopInterface; use React\Dns\Resolver\Resolver; -use React\Promise\When; +use React\Promise; class Connector extends BaseConnector { - protected $contextOptions = array(); + protected $contextOptions = []; + /** + * @param LoopInterface $loop + * @param Resolver $resolver + * @param array|null $contextOptions + */ public function __construct(LoopInterface $loop, Resolver $resolver, array $contextOptions = null) { parent::__construct($loop, $resolver); - $contextOptions = null === $contextOptions ? array() : $contextOptions; + $contextOptions = null === $contextOptions ? [] : $contextOptions; $this->contextOptions = $contextOptions; } + /** + * @param $address + * @param $port + * @param null $hostName + * @return \React\Promise\PromiseInterface|static + */ public function createSocketForAddress($address, $port, $hostName = null) { $url = $this->getSocketUrl($address, $port); @@ -36,7 +47,7 @@ public function createSocketForAddress($address, $port, $hostName = null) $socket = stream_socket_client($url, $errno, $errstr, 0, $flags, $context); if (!$socket) { - return When::reject(new \RuntimeException( + return Promise\reject(new \RuntimeException( sprintf("connection to %s:%d failed: %s", $address, $port, $errstr), $errno )); @@ -48,7 +59,7 @@ public function createSocketForAddress($address, $port, $hostName = null) return $this ->waitForStreamOnce($socket) - ->then(array($this, 'checkConnectedSocket')) - ->then(array($this, 'handleConnectedSocket')); + ->then([$this, 'checkConnectedSocket']) + ->then([$this, 'handleConnectedSocket']); } } diff --git a/src/Devristo/Phpws/Client/WebSocket.php b/src/Devristo/Phpws/Client/WebSocket.php index 1c2f8fe..1cf0018 100644 --- a/src/Devristo/Phpws/Client/WebSocket.php +++ b/src/Devristo/Phpws/Client/WebSocket.php @@ -44,7 +44,7 @@ class WebSocket extends EventEmitter /** * @var WebSocketTransport */ - protected $transport = null; + protected $transport; protected $headers; protected $loop; @@ -52,11 +52,25 @@ class WebSocket extends EventEmitter protected $logger; protected $isClosing = false; - - protected $streamOptions = null; - public function __construct($url, LoopInterface $loop, LoggerInterface $logger, array $streamOptions = null) - { + protected $streamOptions; + + /** @var \React\Dns\Resolver\Resolver */ + protected $dns; + + /** + * @param string $url + * @param LoopInterface $loop + * @param LoggerInterface $logger + * @param array|null $streamOptions + * @throws WebSocketInvalidUrlScheme + */ + public function __construct( + $url, + LoopInterface $loop, + LoggerInterface $logger, + array $streamOptions = null + ) { $this->logger = $logger; $this->loop = $loop; $this->streamOptions = $streamOptions; @@ -64,14 +78,19 @@ public function __construct($url, LoopInterface $loop, LoggerInterface $logger, $this->url = $url; - if (in_array($parts['scheme'], array('ws', 'wss')) === false) + if (in_array($parts['scheme'], ['ws', 'wss']) === false) { throw new WebSocketInvalidUrlScheme(); + } $dnsResolverFactory = new \React\Dns\Resolver\Factory(); $this->dns = $dnsResolverFactory->createCached('8.8.8.8', $loop); } - public function open($timeOut=null) + /** + * @param null $timeOut + * @return \React\Promise\Promise|\React\Promise\PromiseInterface + */ + public function open($timeOut = null) { /** * @var $that self @@ -80,7 +99,7 @@ public function open($timeOut=null) $uri = new Uri($this->url); - $isSecured = 'wss' === $uri->getScheme(); + $isSecured = 'wss' === $uri->getScheme(); $defaultPort = $isSecured ? 443 : 80; $connector = new Connector($this->loop, $this->dns, $this->streamOptions); @@ -92,42 +111,45 @@ public function open($timeOut=null) $deferred = new Deferred(); $connector->create($uri->getHost(), $uri->getPort() ?: $defaultPort) - ->then(function (\React\Stream\DuplexStreamInterface $stream) use ($that, $uri, $deferred, $timeOut){ + ->then(function (\React\Stream\DuplexStreamInterface $stream) use ($that, $uri, $deferred, $timeOut) { - if($timeOut){ - $timeOutTimer = $that->loop->addTimer($timeOut, function() use($deferred, $stream, $that){ + if ($timeOut) { + $timeOutTimer = $that->loop->addTimer($timeOut, function () use ($deferred, $stream, $that) { $stream->close(); $that->logger->notice("Timeout occured, closing connection"); $that->emit("error"); $deferred->reject("Timeout occured"); }); - } else $timeOutTimer = null; + } else { + $timeOutTimer = null; + } $transport = new WebSocketTransportHybi($stream); $transport->setLogger($that->logger); $that->transport = $transport; $that->stream = $stream; - $stream->on("close", function() use($that){ + $stream->on("close", function () use ($that) { $that->isClosing = false; $that->state = WebSocket::STATE_CLOSED; }); // Give the chance to change request - $transport->on("request", function(Request $handshake) use($that){ + $transport->on("request", function (Request $handshake) use ($that) { $that->emit("request", func_get_args()); }); - $transport->on("handshake", function(Handshake $handshake) use($that){ + $transport->on("handshake", function (Handshake $handshake) use ($that) { $that->request = $handshake->getRequest(); $that->response = $handshake->getRequest(); - $that->emit("handshake", array($handshake)); + $that->emit("handshake", [$handshake]); }); - $transport->on("connect", function() use(&$state, $that, $transport, $timeOutTimer, $deferred){ - if($timeOutTimer) + $transport->on("connect", function () use (&$state, $that, $transport, $timeOutTimer, $deferred) { + if ($timeOutTimer) { $timeOutTimer->cancel(); + } $deferred->resolve($transport); $that->state = WebSocket::STATE_CONNECTED; @@ -136,13 +158,12 @@ public function open($timeOut=null) }); $transport->on('message', function ($message) use ($that, $transport) { - $that->emit("message", array("message" => $message)); + $that->emit("message", ["message" => $message]); }); $transport->initiateHandshake($uri); $that->state = WebSocket::STATE_HANDSHAKE_SENT; - }, function($reason) use ($that, $deferred) - { + }, function ($reason) use ($that, $deferred) { $deferred->reject($reason); $that->logger->err($reason); }); @@ -151,28 +172,41 @@ public function open($timeOut=null) } + /** + * @param string $string + */ public function send($string) { $this->transport->sendString($string); } + /** + * @param WebSocketMessageInterface $msg + */ public function sendMessage(WebSocketMessageInterface $msg) { $this->transport->sendMessage($msg); } + /** + * @param WebSocketFrameInterface $frame + */ public function sendFrame(WebSocketFrameInterface $frame) { $this->transport->sendFrame($frame); } + /** + * @return void + */ public function close() { - if ($this->isClosing) + if ($this->isClosing) { return; + } $this->isClosing = true; - $this->sendFrame(WebSocketFrame::create(WebSocketOpcode::CloseFrame)); + $this->sendFrame(WebSocketFrame::create(WebSocketOpcode::CLOSE_FRAME)); $this->state = self::STATE_CLOSING; $stream = $this->stream; @@ -183,8 +217,9 @@ public function close() $loop = $this->loop; $stream->once("close", function () use ($closeTimer, $loop) { - if ($closeTimer) + if ($closeTimer) { $loop->cancelTimer($closeTimer); + } }); } } diff --git a/src/Devristo/Phpws/Exceptions/WebSocketFrameSizeMismatch.php b/src/Devristo/Phpws/Exceptions/WebSocketFrameSizeMismatch.php index 2051f7a..cc34770 100644 --- a/src/Devristo/Phpws/Exceptions/WebSocketFrameSizeMismatch.php +++ b/src/Devristo/Phpws/Exceptions/WebSocketFrameSizeMismatch.php @@ -13,10 +13,11 @@ class WebSocketFrameSizeMismatch extends Exception { - + /** + * @param WebSocketFrameInterface $msg + */ public function __construct(WebSocketFrameInterface $msg) { parent::__construct("Frame size mismatches with the expected frame size. Maybe a buggy client."); } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Exceptions/WebSocketInvalidChallengeResponse.php b/src/Devristo/Phpws/Exceptions/WebSocketInvalidChallengeResponse.php index 5dbadae..a52474b 100644 --- a/src/Devristo/Phpws/Exceptions/WebSocketInvalidChallengeResponse.php +++ b/src/Devristo/Phpws/Exceptions/WebSocketInvalidChallengeResponse.php @@ -12,10 +12,8 @@ class WebSocketInvalidChallengeResponse extends Exception { - public function __construct() { parent::__construct("Server send an incorrect response to the clients challenge!"); } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Exceptions/WebSocketInvalidKeyException.php b/src/Devristo/Phpws/Exceptions/WebSocketInvalidKeyException.php index 84f227b..05de27d 100644 --- a/src/Devristo/Phpws/Exceptions/WebSocketInvalidKeyException.php +++ b/src/Devristo/Phpws/Exceptions/WebSocketInvalidKeyException.php @@ -6,7 +6,6 @@ class WebSocketInvalidKeyException extends Exception { - /** * @param string $key1 * @param string $key2 @@ -17,5 +16,4 @@ public function __construct($key1, $key2, $l8b) parent::__construct("Client sent an invalid opening handshake!"); fwrite(STDERR, "Key 1: \t$key1\nKey 2: \t$key2\nL8b: \t$l8b"); } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Exceptions/WebSocketInvalidUrlScheme.php b/src/Devristo/Phpws/Exceptions/WebSocketInvalidUrlScheme.php index ed689ff..8adfc38 100644 --- a/src/Devristo/Phpws/Exceptions/WebSocketInvalidUrlScheme.php +++ b/src/Devristo/Phpws/Exceptions/WebSocketInvalidUrlScheme.php @@ -12,10 +12,8 @@ class WebSocketInvalidUrlScheme extends Exception { - public function __construct() { parent::__construct("Only 'ws://' urls are supported!"); } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Exceptions/WebSocketMessageNotFinalised.php b/src/Devristo/Phpws/Exceptions/WebSocketMessageNotFinalised.php index 83f653a..12422c2 100644 --- a/src/Devristo/Phpws/Exceptions/WebSocketMessageNotFinalised.php +++ b/src/Devristo/Phpws/Exceptions/WebSocketMessageNotFinalised.php @@ -13,10 +13,8 @@ class WebSocketMessageNotFinalised extends Exception { - public function __construct(WebSocketMessageInterface $msg) { parent::__construct("WebSocketMessage is not finalised!"); } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Framing/WebSocketFrame.php b/src/Devristo/Phpws/Framing/WebSocketFrame.php index 5e5df36..ca01c10 100644 --- a/src/Devristo/Phpws/Framing/WebSocketFrame.php +++ b/src/Devristo/Phpws/Framing/WebSocketFrame.php @@ -7,6 +7,7 @@ * To change this template use File | Settings | File Templates. */ namespace Devristo\Phpws\Framing; + use Devristo\Phpws\Exceptions\WebSocketFrameSizeMismatch; /** @@ -23,7 +24,7 @@ class WebSocketFrame implements WebSocketFrameInterface protected $RSV1 = 0; protected $RSV2 = 0; protected $RSV3 = 0; - protected $opcode = WebSocketOpcode::TextFrame; + protected $opcode = WebSocketOpcode::TEXT_FRAME; // Second Byte protected $mask = 0; protected $payloadLength = 0; @@ -36,6 +37,11 @@ private function __construct() } + /** + * @param int $type + * @param null $data + * @return WebSocketFrame + */ public static function create($type, $data = null) { $o = new self(); @@ -48,45 +54,72 @@ public static function create($type, $data = null) return $o; } + /** + * @param bool $mask + */ public function setMasked($mask) { $this->mask = $mask ? 1 : 0; } + /** + * @return bool + */ public function isMasked() { return $this->mask == 1; } + /** + * @param int $type + */ protected function setType($type) { $this->opcode = $type; - if ($type == WebSocketOpcode::CloseFrame) + if ($type == WebSocketOpcode::CLOSE_FRAME) { $this->mask = 1; + } } - protected static function IsBitSet($byte, $pos) + /** + * @param int $byte + * @param int $pos + * @return int + */ + protected static function isBitSet($byte, $pos) { return ($byte & pow(2, $pos)) > 0 ? 1 : 0; } + /** + * @param $data + * @param $key + * @param int $offset + * @return int + */ protected static function rotMask($data, $key, $offset = 0) { // Rotate key for example if $offset=1 and $key=abcd then output will be bcda - $rotated_key = substr($key, $offset) . substr($key, 0, $offset); + $rotatedKey = substr($key, $offset) . substr($key, 0, $offset); // Repeat key until it is at least the size of the $data - $key_pad = str_repeat($rotated_key, ceil(1.0*strlen($data) / strlen($key))); + $keyPad = str_repeat($rotatedKey, ceil(1.0*strlen($data) / strlen($key))); - return $data ^ substr($key_pad, 0, strlen($data)); + return $data ^ substr($keyPad, 0, strlen($data)); } + /** + * @return int + */ public function getType() { return $this->opcode; } + /** + * @return string + */ public function encode() { $this->payloadLength = strlen($this->payloadData); @@ -102,7 +135,7 @@ public function encode() $secondByte += $this->mask * 128; $encoded .= chr($secondByte); - } else if ($this->payloadLength <= 256 * 256 - 1) { + } elseif ($this->payloadLength <= 256 * 256 - 1) { $secondByte = 126; $secondByte += $this->mask * 128; @@ -123,16 +156,24 @@ public function encode() $encoded .= $key; } - if ($this->payloadData) - $encoded .= ($this->mask == 1) ? $this->rotMask($this->payloadData, $key) : $this->payloadData; + if ($this->payloadData) { + $encoded .= ($this->mask == 1) + ? $this->rotMask($this->payloadData, $key) + : $this->payloadData; + } return $encoded; } + /** + * @param $buffer + * @return WebSocketFrame|null + */ public static function decode(&$buffer) { - if(strlen($buffer) < 2) + if (strlen($buffer) < 2) { return null; + } $frame = new self(); @@ -143,20 +184,20 @@ public static function decode(&$buffer) $firstByte = ord($firstByte); $secondByte = ord($secondByte); - $frame->FIN = self::IsBitSet($firstByte, 7); - $frame->RSV1 = self::IsBitSet($firstByte, 6); - $frame->RSV2 = self::IsBitSet($firstByte, 5); - $frame->RSV3 = self::IsBitSet($firstByte, 4); + $frame->FIN = self::isBitSet($firstByte, 7); + $frame->RSV1 = self::isBitSet($firstByte, 6); + $frame->RSV2 = self::isBitSet($firstByte, 5); + $frame->RSV3 = self::isBitSet($firstByte, 4); - $frame->mask = self::IsBitSet($secondByte, 7); + $frame->mask = self::isBitSet($secondByte, 7); $frame->opcode = ($firstByte & 0x0F); $len = $secondByte & ~128; - if ($len <= 125){ + if ($len <= 125) { $frame->payloadLength = $len; - }elseif (($len == 126) && strlen($raw) >= 2){ + } elseif (($len == 126) && strlen($raw) >= 2) { $arr = unpack("nfirst", $raw); $frame->payloadLength = array_pop($arr); $raw = substr($raw, 2); @@ -164,54 +205,66 @@ public static function decode(&$buffer) list(, $h, $l) = unpack('N2', $raw); $frame->payloadLength = ($l + ($h * 0x0100000000)); $raw = substr($raw, 8); - } else{ + } else { return null; } // If the frame is masked, try to eat the key from the buffer. If the buffer is insufficient, return null and // try again next time if ($frame->mask) { - if(strlen($raw) < 4) + if (strlen($raw) < 4) { return null; + } $frame->maskingKey = substr($raw, 0, 4); $raw = substr($raw, 4); } - // Don't continue until we have a full frame - if(strlen($raw) < $frame->payloadLength) + if (strlen($raw) < $frame->payloadLength) { return null; + } $packetPayload = substr($raw, 0, $frame->payloadLength); // Advance buffer $buffer = substr($raw, $frame->payloadLength); - if ($frame->mask) + if ($frame->mask) { $frame->payloadData = self::rotMask($packetPayload, $frame->maskingKey, 0); - else + } else { $frame->payloadData = $packetPayload; + } return $frame; } + /** + * @return bool + * @throws WebSocketFrameSizeMismatch + */ public function isReady() { if ($this->actualLength > $this->payloadLength) { throw new WebSocketFrameSizeMismatch($this); } + return ($this->actualLength == $this->payloadLength); } + /** + * @return bool + */ public function isFinal() { return $this->FIN == 1; } + /** + * @return string + */ public function getData() { return $this->payloadData; } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Framing/WebSocketFrame76.php b/src/Devristo/Phpws/Framing/WebSocketFrame76.php index a816a01..5b13721 100644 --- a/src/Devristo/Phpws/Framing/WebSocketFrame76.php +++ b/src/Devristo/Phpws/Framing/WebSocketFrame76.php @@ -1,13 +1,16 @@ payloadData . chr(255); } + /** + * @return string + */ public function getData() { return $this->payloadData; } + /** + * @return int + */ public function getType() { return $this->opcode; } + /** + * @param $str + * @return WebSocketFrame76 + */ public static function decode(&$str) { $o = new self(); @@ -41,5 +57,4 @@ public static function decode(&$str) return $o; } - } diff --git a/src/Devristo/Phpws/Framing/WebSocketFrameInterface.php b/src/Devristo/Phpws/Framing/WebSocketFrameInterface.php index d8c9ad5..4fb4beb 100644 --- a/src/Devristo/Phpws/Framing/WebSocketFrameInterface.php +++ b/src/Devristo/Phpws/Framing/WebSocketFrameInterface.php @@ -7,6 +7,7 @@ * To change this template use File | Settings | File Templates. */ namespace Devristo\Phpws\Framing; + /** * Interface for WebSocket frames. One or more frames compose a message. * In the case of the Hixie protocol, a message contains of one frame only @@ -15,7 +16,6 @@ */ interface WebSocketFrameInterface { - /** * Serialize the frame so that it can be send over a socket * @return string Serialized binary string @@ -25,7 +25,6 @@ public function encode(); /** * Deserialize a binary string into a IWebSocketFrame * @param $string - * @param null $head * @return string Serialized binary string */ public static function decode(&$string); @@ -48,4 +47,4 @@ public function getType(); * @return \Devristo\Phpws\Framing\WebSocketFrameInterface */ public static function create($type, $data = null); -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Framing/WebSocketOpcode.php b/src/Devristo/Phpws/Framing/WebSocketOpcode.php index c95eab2..8b72a32 100644 --- a/src/Devristo/Phpws/Framing/WebSocketOpcode.php +++ b/src/Devristo/Phpws/Framing/WebSocketOpcode.php @@ -7,6 +7,7 @@ * To change this template use File | Settings | File Templates. */ namespace Devristo\Phpws\Framing; + /** * Enum-like construct containing all opcodes defined in the WebSocket protocol * @author Chris @@ -14,14 +15,13 @@ */ class WebSocketOpcode { - - const __default = 0; - const ContinuationFrame = 0x00; - const TextFrame = 0x01; - const BinaryFrame = 0x02; - const CloseFrame = 0x08; - const PingFrame = 0x09; - const PongFrame = 0x0A; + const __DEFAULT = 0; + const CONTINUATION_FRAME = 0x00; + const TEXT_FRAME = 0x01; + const BINARY_FRAME = 0x02; + const CLOSE_FRAME = 0x08; + const PING_FRAME = 0x09; + const PONG_FRAME = 0x0A; private function __construct() { @@ -36,9 +36,8 @@ private function __construct() */ public static function isControlFrame($type) { - $controlFrames = array(self::CloseFrame, self::PingFrame, self::PongFrame); + $controlFrames = [self::CLOSE_FRAME, self::PING_FRAME, self::PONG_FRAME]; return in_array($type, $controlFrames); } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Messaging/MessageInterface.php b/src/Devristo/Phpws/Messaging/MessageInterface.php index 7480697..195f1e5 100644 --- a/src/Devristo/Phpws/Messaging/MessageInterface.php +++ b/src/Devristo/Phpws/Messaging/MessageInterface.php @@ -8,7 +8,7 @@ namespace Devristo\Phpws\Messaging; - -interface MessageInterface { +interface MessageInterface +{ public function getData(); -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Messaging/RemoteEventMessage.php b/src/Devristo/Phpws/Messaging/RemoteEventMessage.php index e791c4b..16f396e 100644 --- a/src/Devristo/Phpws/Messaging/RemoteEventMessage.php +++ b/src/Devristo/Phpws/Messaging/RemoteEventMessage.php @@ -8,17 +8,24 @@ namespace Devristo\Phpws\Messaging; - -class RemoteEventMessage implements MessageInterface { +class RemoteEventMessage implements MessageInterface +{ protected $tag; protected $data; protected $event; protected $room; - public function __construct(){ + public function __construct() + { $this->tag = uniqid("server-"); } + /** + * @param $room + * @param $event + * @param $data + * @return RemoteEventMessage + */ public static function create($room, $event, $data) { $message = new RemoteEventMessage(); @@ -77,32 +84,48 @@ public function getTag() return $this->tag; } - public static function fromJson($jsonString){ + /** + * @param $jsonString + * @return RemoteEventMessage + */ + public static function fromJson($jsonString) + { $data = json_decode($jsonString); - if(!$data || !property_exists($data, 'event') || !property_exists($data, 'tag') || !property_exists($data, 'room')) + if (!$data + || !property_exists($data, 'event') + || !property_exists($data, 'tag') + || !property_exists($data, 'room') + ) { throw new \InvalidArgumentException("Not a valid JSON RemoteEvent object"); + } - $JsonMessage = new RemoteEventMessage(); + $jsonMessage = new RemoteEventMessage(); - if(property_exists($data, 'data')) - $JsonMessage->setData($data->data); - else $JsonMessage->setData(null); + if (property_exists($data, 'data')) { + $jsonMessage->setData($data->data); + } else { + $jsonMessage->setData(null); + } - $JsonMessage->setTag($data->tag); - $JsonMessage->setEvent($data->event); - $JsonMessage->setRoom($data->room); + $jsonMessage->setTag($data->tag); + $jsonMessage->setEvent($data->event); + $jsonMessage->setRoom($data->room); - return $JsonMessage; + return $jsonMessage; } - public function toJson(){ - return json_encode(array( + /** + * @return string + */ + public function toJson() + { + return json_encode([ 'tag' => $this->getTag(), 'data' => $this->getData(), 'room' => $this->getRoom(), 'event' => $this->getEvent() - )); + ]); } /** @@ -120,4 +143,4 @@ public function getEvent() { return $this->event; } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Messaging/WebSocketMessage.php b/src/Devristo/Phpws/Messaging/WebSocketMessage.php index 8eba499..4fdd6ff 100644 --- a/src/Devristo/Phpws/Messaging/WebSocketMessage.php +++ b/src/Devristo/Phpws/Messaging/WebSocketMessage.php @@ -1,11 +1,11 @@ data = $data; @@ -31,6 +33,10 @@ public function setData($data) $this->createFrames(); } + /** + * @param string $data + * @return WebSocketMessage + */ public static function create($data) { $o = new self(); @@ -39,10 +45,15 @@ public static function create($data) return $o; } + /** + * @return string + * @throws WebSocketMessageNotFinalised + */ public function getData() { - if ($this->isFinalised() == false) + if ($this->isFinalised() == false) { throw new WebSocketMessageNotFinalised($this); + } $data = ''; @@ -53,6 +64,10 @@ public function getData() return $data; } + /** + * @param WebSocketFrameInterface $frame + * @return WebSocketMessage + */ public static function fromFrame(WebSocketFrameInterface $frame) { assert($frame instanceof WebSocketFrame); @@ -67,18 +82,27 @@ public static function fromFrame(WebSocketFrameInterface $frame) protected function createFrames() { - $this->frames = array(WebSocketFrame::create(WebSocketOpcode::TextFrame, $this->data)); + $this->frames = [ + WebSocketFrame::create(WebSocketOpcode::TEXT_FRAME, $this->data) + ]; } + /** + * @return \Devristo\Phpws\Framing\WebSocketFrame[] + */ public function getFrames() { return $this->frames; } + /** + * @return bool + */ public function isFinalised() { - if (count($this->frames) == 0) + if (count($this->frames) == 0) { return false; + } return $this->frames[count($this->frames) - 1]->isFinal(); } @@ -91,5 +115,4 @@ public function takeFrame(WebSocketFrame $frame) { $this->frames[] = $frame; } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Messaging/WebSocketMessage76.php b/src/Devristo/Phpws/Messaging/WebSocketMessage76.php index 577d9b5..2c3a876 100644 --- a/src/Devristo/Phpws/Messaging/WebSocketMessage76.php +++ b/src/Devristo/Phpws/Messaging/WebSocketMessage76.php @@ -7,6 +7,7 @@ * To change this template use File | Settings | File Templates. */ namespace Devristo\Phpws\Messaging; + use Devristo\Phpws\Framing\WebSocketFrameInterface; use Devristo\Phpws\Framing\WebSocketFrame76; use Devristo\Phpws\Framing\WebSocketOpcode; @@ -20,7 +21,6 @@ */ class WebSocketMessage76 implements WebSocketMessageInterface { - protected $data = ''; /** @@ -28,6 +28,10 @@ class WebSocketMessage76 implements WebSocketMessageInterface */ protected $frame = null; + /** + * @param string $data + * @return WebSocketMessage76 + */ public static function create($data) { $o = new self(); @@ -36,26 +40,38 @@ public static function create($data) return $o; } + /** + * @return array + */ public function getFrames() { - $arr = array(); + $arr = []; $arr[] = $this->frame; return $arr; } + /** + * @param string $data + */ public function setData($data) { $this->data = $data; - $this->frame = WebSocketFrame76::create(WebSocketOpcode::TextFrame, $data); + $this->frame = WebSocketFrame76::create(WebSocketOpcode::TEXT_FRAME, $data); } + /** + * @return string + */ public function getData() { return $this->frame->getData(); } + /** + * @return bool + */ public function isFinalised() { return true; @@ -74,5 +90,4 @@ public static function fromFrame(WebSocketFrameInterface $frame) return $o; } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Messaging/WebSocketMessageInterface.php b/src/Devristo/Phpws/Messaging/WebSocketMessageInterface.php index a107971..2e95d4b 100644 --- a/src/Devristo/Phpws/Messaging/WebSocketMessageInterface.php +++ b/src/Devristo/Phpws/Messaging/WebSocketMessageInterface.php @@ -7,6 +7,7 @@ * To change this template use File | Settings | File Templates. */ namespace Devristo\Phpws\Messaging; + use Devristo\Phpws\Framing\WebSocketFrameInterface; use Devristo\Phpws\Framing\WebSocketFrame; use Exception; @@ -19,7 +20,6 @@ */ interface WebSocketMessageInterface extends MessageInterface { - /** * Retrieve an array of frames of which this message is composed * @@ -53,4 +53,4 @@ public function isFinalised(); * @throws Exception */ public static function fromFrame(WebSocketFrameInterface $frame); -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/Handshake.php b/src/Devristo/Phpws/Protocol/Handshake.php index ea82752..b6c9e8c 100644 --- a/src/Devristo/Phpws/Protocol/Handshake.php +++ b/src/Devristo/Phpws/Protocol/Handshake.php @@ -8,33 +8,54 @@ namespace Devristo\Phpws\Protocol; - use Zend\Http\Request; use Zend\Http\Response; -class Handshake { +class Handshake +{ protected $abort = false; protected $request; protected $response; - public function __construct(Request $request, Response $response){ + /** + * @param Request $request + * @param Response $response + */ + public function __construct(Request $request, Response $response) + { $this->request = $request; $this->response = $response; } - public function getRequest(){ + /** + * @return Request + */ + public function getRequest() + { return $this->request; } - public function getResponse(){ + /** + * @return Response + */ + public function getResponse() + { return $this->response; } - public function abort(){ + /** + * @return void + */ + public function abort() + { $this->abort = true; } - public function isAborted(){ + /** + * @return bool + */ + public function isAborted() + { return $this->abort; } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/StackTransport.php b/src/Devristo/Phpws/Protocol/StackTransport.php index 71bfb67..f19a3bd 100644 --- a/src/Devristo/Phpws/Protocol/StackTransport.php +++ b/src/Devristo/Phpws/Protocol/StackTransport.php @@ -8,25 +8,33 @@ namespace Devristo\Phpws\Protocol; - use Zend\Http\Request; use Zend\Http\Response; -class StackTransport implements \ArrayAccess, WebSocketTransportInterface{ +class StackTransport implements \ArrayAccess, WebSocketTransportInterface +{ protected $stack; + /** + * @param WebSocketTransportInterface $webSocketTransport + * @param $stackSpecs + * @return StackTransport + */ public static function create(WebSocketTransportInterface $webSocketTransport, $stackSpecs) { - if (count($stackSpecs) < 1) + if (count($stackSpecs) < 1) { throw new \InvalidArgumentException("Stack should be a non empty array"); + } - $ws2stack = array(); + $ws2stack = []; - // A specification can be either a fully qualified class name or a lambda expression: TransportInterface -> TransportInterface - $instantiator = function($spec, TransportInterface $carrier){ - if(is_string($spec)){ + /** A specification can be either a fully qualified class name or a lambda expression: + * TransportInterface -> TransportInterface + */ + $instantiator = function ($spec, TransportInterface $carrier) { + if (is_string($spec)) { $transport = new $spec($carrier); - } elseif(is_callable($spec)){ + } elseif (is_callable($spec)) { $transport = $spec($carrier); } return $transport; @@ -38,16 +46,16 @@ public static function create(WebSocketTransportInterface $webSocketTransport, $ /** * @var $stack TransportInterface[] */ - $stack = array($carrier); + $stack = [$carrier]; // Instantiate transports $i = 0; - do{ + do { $transport = $instantiator($stackSpecs[$i], new StackTransport($stack)); $stack[] = $transport; $i++; - }while($i < count($stackSpecs)); + } while ($i < count($stackSpecs)); $first = $stack[1]; $last = $stack[count($stack) - 1]; @@ -56,9 +64,14 @@ public static function create(WebSocketTransportInterface $webSocketTransport, $ return new StackTransport($stack); } - public function __construct(array $stack){ - if(count($stack) < 1) + /** + * @param array $stack + */ + public function __construct(array $stack) + { + if (count($stack) < 1) { throw new \InvalidArgumentException("Stack must be a non-empty array"); + } $this->stack = $stack; } @@ -66,14 +79,16 @@ public function __construct(array $stack){ /** * @return WebSocketTransportInterface */ - public function getWebSocketTransport(){ + public function getWebSocketTransport() + { return $this->stack[0]; } /** * @return TransportInterface */ - public function getTopTransport(){ + public function getTopTransport() + { return $this->stack[count($this->stack) - 1]; } @@ -139,61 +154,107 @@ public function offsetUnset($offset) throw new \BadMethodCallException("Immutable stack, cannot set element"); } + /** + * @param $event + * @param callable $listener + * @return mixed + */ public function on($event, callable $listener) { return $this->getTopTransport()->on($event, $listener); } + /** + * @param $event + * @param callable $listener + * @return mixed + */ public function once($event, callable $listener) { return $this->getTopTransport()->once($event, $listener); } + /** + * @param $event + * @param callable $listener + * @return mixed + */ public function removeListener($event, callable $listener) { return $this->getTopTransport()->removeListener($event, $listener); } + /** + * @param null $event + * @return mixed + */ public function removeAllListeners($event = null) { return $this->getTopTransport()->removeAllListeners($event); } + /** + * @param $event + * @return mixed + */ public function listeners($event) { return $this->getTopTransport()->listeners($event); } - public function emit($event, array $arguments = array()) + /** + * @param $event + * @param array $arguments + * @return mixed + */ + public function emit($event, array $arguments = []) { return $this->getTopTransport()->emit($event, $arguments); } + /** + * @return mixed + */ public function getId() { return $this->getWebSocketTransport()->getId(); } + /** + * @param Request $request + */ public function respondTo(Request $request) { throw new \BadMethodCallException(); } + /** + * @param $data + */ public function handleData(&$data) { throw new \BadMethodCallException(); } + /** + * @param $msg + */ public function sendString($msg) { $this->getTopTransport()->sendString($msg); } + /** + * @return void + */ public function getIp() { $this->getWebSocketTransport()->getIp(); } + /** + * @return void + */ public function close() { $this->getWebSocketTransport()->close(); @@ -215,11 +276,21 @@ public function getHandshakeResponse() return $this->getWebSocketTransport()->getHandshakeResponse(); } - public function setData($key, $value){ + /** + * @param $key + * @param $value + */ + public function setData($key, $value) + { $this->getWebSocketTransport()->setData($key, $value); } - public function getData($key){ + /** + * @param $key + * @return mixed + */ + public function getData($key) + { return $this->getWebSocketTransport()->getData($key); } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/TransportInterface.php b/src/Devristo/Phpws/Protocol/TransportInterface.php index b502754..5b9f6b7 100644 --- a/src/Devristo/Phpws/Protocol/TransportInterface.php +++ b/src/Devristo/Phpws/Protocol/TransportInterface.php @@ -8,9 +8,9 @@ namespace Devristo\Phpws\Protocol; - use Evenement\EventEmitterInterface; -interface TransportInterface extends EventEmitterInterface{ +interface TransportInterface extends EventEmitterInterface +{ public function sendString($string); -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/WebSocketConnection.php b/src/Devristo/Phpws/Protocol/WebSocketConnection.php index 681c3c8..bd8bcff 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketConnection.php +++ b/src/Devristo/Phpws/Protocol/WebSocketConnection.php @@ -19,20 +19,28 @@ class WebSocketConnection extends Connection * * @var WebSocketTransportInterface */ - private $_transport = null; - private $_lastChanged = null; + private $transport; + private $lastChanged; + /** + * @param $socket + * @param LoopInterface $loop + * @param $logger + */ public function __construct($socket, LoopInterface $loop, $logger) { parent::__construct($socket, $loop); - $this->_lastChanged = time(); + $this->lastChanged = time(); $this->logger = $logger; } + /** + * @param $stream + */ public function handleData($stream) { - if (feof($stream) || !is_resource($stream)){ + if (feof($stream) || !is_resource($stream)) { $this->close(); return; } @@ -45,57 +53,71 @@ public function handleData($stream) } } + /** + * @param $data + */ private function onData($data) { try { - $this->_lastChanged = time(); + $this->lastChanged = time(); - if ($this->_transport) - $this->emit('data', array($data, $this)); - else + if ($this->transport) { + $this->emit('data', [$data, $this]); + } else { $this->establishConnection($data); + } } catch (Exception $e) { - $this->logger->err("Error while handling incoming data. Exception message is: ".$e->getMessage()); + $this->logger->err("Error while handling incoming data. Exception message is: " . $e->getMessage()); $this->close(); } } + /** + * @param WebSocketTransportInterface $con + */ public function setTransport(WebSocketTransportInterface $con) { - $this->_transport = $con; + $this->transport = $con; } + /** + * @param $data + */ public function establishConnection($data) { - $this->_transport = WebSocketTransportFactory::fromSocketData($this, $data, $this->logger); + $this->transport = WebSocketTransportFactory::fromSocketData($this, $data, $this->logger); $myself = $this; - $this->_transport->on("handshake", function(Handshake $request) use ($myself){ - $myself->emit("handshake", array($request)); + $this->transport->on("handshake", function (Handshake $request) use ($myself) { + $myself->emit("handshake", [$request]); }); - $this->_transport->on("connect", function() use ($myself){ - $myself->emit("connect", array($myself)); + $this->transport->on("connect", function () use ($myself) { + $myself->emit("connect", [$myself]); }); - $this->_transport->on("message", function($message) use($myself){ - $myself->emit("message", array("message" => $message)); + $this->transport->on("message", function ($message) use ($myself) { + $myself->emit("message", ["message" => $message]); }); - $this->_transport->on("flashXmlRequest", function($message) use($myself){ + $this->transport->on("flashXmlRequest", function ($message) use ($myself) { $myself->emit("flashXmlRequest"); }); - if ($this->_transport instanceof WebSocketTransportFlash) + if ($this->transport instanceof WebSocketTransportFlash) { return; + } $request = Request::fromString($data); - $this->_transport->respondTo($request); + $this->transport->respondTo($request); } + /** + * @return int + */ public function getLastChanged() { - return $this->_lastChanged; + return $this->lastChanged; } /** @@ -104,11 +126,14 @@ public function getLastChanged() */ public function getTransport() { - return $this->_transport; + return $this->transport; } + /** + * @param LoggerInterface $logger + */ public function setLogger(LoggerInterface $logger) { $this->logger = $logger; } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/WebSocketTransport.php b/src/Devristo/Phpws/Protocol/WebSocketTransport.php index 6cd36ca..de3a0ac 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketTransport.php +++ b/src/Devristo/Phpws/Protocol/WebSocketTransport.php @@ -19,6 +19,8 @@ abstract class WebSocketTransport extends EventEmitter implements WebSocketTransportInterface, LoggerAwareInterface { + public $parameters; + /** * @var LoggerInterface */ @@ -38,92 +40,139 @@ abstract class WebSocketTransport extends EventEmitter implements WebSocketTrans * * @var WebSocketConnection */ - protected $_socket = null; - protected $_cookies = array(); - public $parameters = null; - protected $_role = WebsocketTransportRole::CLIENT; + protected $socket; + protected $cookies = []; + protected $role = WebsocketTransportRole::CLIENT; + + protected $eventManger; - protected $_eventManger; + protected $data = []; - protected $data = array(); + protected $id; + /** + * @param WritableStreamInterface $socket + */ public function __construct(WritableStreamInterface $socket) { - $this->_socket = $socket; - $this->_id = uniqid("connection-"); + $this->socket = $socket; + $this->id = uniqid("connection-"); $that = $this; $buffer = ''; - $socket->on("data", function($data) use ($that, &$buffer){ + $socket->on("data", function ($data) use ($that, &$buffer) { $buffer .= $data; $that->handleData($buffer); }); - $socket->on("close", function($data) use ($that){ + $socket->on("close", function ($data) use ($that) { $that->emit("close", func_get_args()); }); } + /** + * @return string + */ public function getIp() { - return $this->_socket->getRemoteAddress(); + return $this->socket->getRemoteAddress(); } + /** + * @return string + */ public function getId() { - return $this->_id; + return $this->id; } - protected function setRequest(Request $request){ + protected function setRequest(Request $request) + { $this->request = $request; } - protected function setResponse(Response $response){ + protected function setResponse(Response $response) + { $this->response = $response; } - public function getHandshakeRequest(){ + /** + * @return Request + */ + public function getHandshakeRequest() + { return $this->request; } - public function getHandshakeResponse(){ + /** + * @return Response + */ + public function getHandshakeResponse() + { return $this->response; } + /** + * @return WebSocketConnection|WritableStreamInterface + */ public function getSocket() { - return $this->_socket; + return $this->socket; } - public function setLogger(LoggerInterface $logger){ + /** + * @param LoggerInterface $logger + */ + public function setLogger(LoggerInterface $logger) + { $this->logger = $logger; } + /** + * @param WebSocketFrameInterface $frame + * @return bool + */ public function sendFrame(WebSocketFrameInterface $frame) { - if ($this->_socket->write($frame->encode()) === false) + if ($this->socket->write($frame->encode()) === false) { return false; + } return true; } + /** + * @param WebSocketMessageInterface $msg + * @return bool + */ public function sendMessage(WebSocketMessageInterface $msg) { foreach ($msg->getFrames() as $frame) { - if ($this->sendFrame($frame) === false) + if ($this->sendFrame($frame) === false) { return false; + } } return true; } - public function setData($key, $value){ + /** + * @param $key + * @param $value + */ + public function setData($key, $value) + { $this->data[$key] = $value; } - public function getData($key){ + /** + * @param $key + * @return mixed + */ + public function getData($key) + { return $this->data[$key]; } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/WebSocketTransportFactory.php b/src/Devristo/Phpws/Protocol/WebSocketTransportFactory.php index b443c20..b043a4e 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketTransportFactory.php +++ b/src/Devristo/Phpws/Protocol/WebSocketTransportFactory.php @@ -14,11 +14,16 @@ class WebSocketTransportFactory { - + /** + * @param ConnectionInterface $socket + * @param $data + * @param LoggerInterface $logger + * @return WebSocketTransportFlash|WebSocketTransportHixie|WebSocketTransportHybi + */ public static function fromSocketData(ConnectionInterface $socket, $data, LoggerInterface $logger) { // Check whether we have a Adobe Flash Policy file Request - if(strpos($data, '') === 0){ + if (strpos($data, '') === 0) { $s = new WebSocketTransportFlash($socket, $data); $s->setLogger($logger); @@ -30,12 +35,11 @@ public static function fromSocketData(ConnectionInterface $socket, $data, Logger if ($request->getHeader('Sec-Websocket-Key1')) { $s = new WebSocketTransportHixie($socket, $request, $data); $s->setLogger($logger); - } else{ + } else { $s = new WebSocketTransportHybi($socket, $request); $s->setLogger($logger); } - return $s; } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Protocol/WebSocketTransportFlash.php b/src/Devristo/Phpws/Protocol/WebSocketTransportFlash.php index e407753..0780a79 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketTransportFlash.php +++ b/src/Devristo/Phpws/Protocol/WebSocketTransportFlash.php @@ -9,34 +9,60 @@ namespace Devristo\Phpws\Protocol; use Exception; +use Zend\Http\Request; class WebSocketTransportFlash extends WebSocketTransport { - + /** + * WebSocketTransportFlash constructor. + * @param \React\Stream\WritableStreamInterface $socket + * @param $data + */ public function __construct($socket, $data) { - $this->_socket = $socket; + $this->socket = $socket; $this->emit("flashXmlRequest"); } + /** + * @param $msg + */ public function sendString($msg) { - $this->_socket->write($msg); + $this->socket->write($msg); } + /** + * @return void + */ public function close() { - $this->_socket->close(); + $this->socket->close(); } + /** + * @throws Exception + */ public function sendHandshakeResponse() { throw new Exception("Not supported!"); } - public function handleData($data) + /** + * @param $data + * @throws Exception + */ + public function handleData(&$data) { throw new Exception("Not supported!"); } -} \ No newline at end of file + + /** + * @param Request $request + */ + public function respondTo(Request $request) + { + // TODO: Implement respondTo() method. + } +} diff --git a/src/Devristo/Phpws/Protocol/WebSocketTransportHixie.php b/src/Devristo/Phpws/Protocol/WebSocketTransportHixie.php index c83b658..e32d527 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketTransportHixie.php +++ b/src/Devristo/Phpws/Protocol/WebSocketTransportHixie.php @@ -5,15 +5,17 @@ use Devristo\Phpws\Exceptions\WebSocketInvalidKeyException; use Devristo\Phpws\Framing\WebSocketFrame76; use Devristo\Phpws\Messaging\WebSocketMessage76; -use React\Stream\WritableStreamInterface; use Zend\Http\Headers; use Zend\Http\Request; use Zend\Http\Response; class WebSocketTransportHixie extends WebSocketTransport { - - public function respondTo(Request $request){ + /** + * @param Request $request + */ + public function respondTo(Request $request) + { $this->request = $request; $this->sendHandshakeResponse(); } @@ -28,7 +30,7 @@ private function sendHandshakeResponse() $key2 = $this->getHandshakeRequest()->getHeader('Sec-Websocket-Key2')->getFieldValue(); // Origin checking (TODO) - $originHeader = $this->getHandshakeRequest()->getHeader('Origin', null); + $originHeader = $this->getHandshakeRequest()->getHeader('Origin', null); $host = $this->getHandshakeRequest()->getHeader('Host')->getFieldValue(); $location = $this->getHandshakeRequest()->getUriString(); @@ -43,8 +45,10 @@ private function sendHandshakeResponse() $headers->addHeaderLine("Upgrade", "WebSocket"); $headers->addHeaderLine("Connection", "Upgrade"); - if($originHeader) + if ($originHeader) { $headers->addHeaderLine("Sec-WebSocket-Origin", $originHeader->getFieldValue()); + } + $headers->addHeaderLine("Sec-WebSocket-Location", "ws://{$host}$location"); // Build HIXIE response @@ -53,12 +57,12 @@ private function sendHandshakeResponse() $this->setResponse($response); $handshakeRequest = new Handshake($this->getHandshakeRequest(), $this->getHandshakeResponse()); - $this->emit("handshake", array($handshakeRequest)); + $this->emit("handshake", [$handshakeRequest]); - if($handshakeRequest->isAborted()) + if ($handshakeRequest->isAborted()) { $this->close(); - else { - $this->_socket->write($response->toString()); + } else { + $this->socket->write($response->toString()); $this->logger->debug("Got an HYBI style request, sent HYBY handshake response"); $this->emit("connect"); @@ -81,7 +85,7 @@ private static function calcHixieResponse($key1, $key2, $l8b) $numbers1 = preg_replace("/[^0-9]/", "", $key1); $numbers2 = preg_replace("/[^0-9]/", "", $key2); - //Count spaces + // Count spaces $spaces1 = substr_count($key1, " "); $spaces2 = substr_count($key2, " "); @@ -90,24 +94,34 @@ private static function calcHixieResponse($key1, $key2, $l8b) } // Key is the number divided by the amount of spaces expressed as a big-endian 32 bit integer - $key1_sec = pack("N", $numbers1 / $spaces1); - $key2_sec = pack("N", $numbers2 / $spaces2); - - // The response is the md5-hash of the 2 keys and the last 8 bytes of the opening handshake, expressed as a binary string - return md5($key1_sec . $key2_sec . $l8b, 1); + $key1Sec = pack("N", $numbers1 / $spaces1); + $key2Sec = pack("N", $numbers2 / $spaces2); + + /** + * The response is the md5-hash of the 2 keys and the last 8 bytes of the opening handshake, + * expressed as a binary string + */ + return md5($key1Sec . $key2Sec . $l8b, 1); } - + /** + * @param $data + * @return array + */ public function handleData(&$data) { $f = WebSocketFrame76::decode($data); $message = WebSocketMessage76::fromFrame($f); - $this->emit("message", array('message' => $message)); + $this->emit("message", ['message' => $message]); - return array($f); + return [$f]; } + /** + * @param $msg + * @return bool + */ public function sendString($msg) { $m = WebSocketMessage76::create($msg); @@ -115,8 +129,11 @@ public function sendString($msg) return $this->sendMessage($m); } + /** + * @return void + */ public function close() { - $this->_socket->close(); + $this->socket->close(); } } diff --git a/src/Devristo/Phpws/Protocol/WebSocketTransportHybi.php b/src/Devristo/Phpws/Protocol/WebSocketTransportHybi.php index 4740f0b..1d5442d 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketTransportHybi.php +++ b/src/Devristo/Phpws/Protocol/WebSocketTransportHybi.php @@ -20,32 +20,36 @@ class WebSocketTransportHybi extends WebSocketTransport { - /** * @var WebSocketMessage */ - private $_openMessage = null; + private $openMessage; /** * @var WebSocketFrame */ - private $lastFrame = null; + private $lastFrame; protected $connected = false; - public function respondTo(Request $request){ + /** + * @param Request $request + */ + public function respondTo(Request $request) + { $this->request = $request; - $this->_role = WebsocketTransportRole::SERVER; + $this->role = WebsocketTransportRole::SERVER; $this->sendHandshakeResponse(); } private function sendHandshakeResponse() { - try{ + try { $challengeHeader = $this->getHandshakeRequest()->getHeader('Sec-Websocket-Key', null); - if(!$challengeHeader) + if (!$challengeHeader) { throw new Exception("No Sec-WebSocket-Key received!"); + } // Check for newer handshake $challenge = $challengeHeader->getFieldValue(); @@ -65,19 +69,19 @@ private function sendHandshakeResponse() $this->setResponse($response); $handshakeRequest = new Handshake($this->getHandshakeRequest(), $this->getHandshakeResponse()); - $this->emit("handshake", array($handshakeRequest)); + $this->emit("handshake", [$handshakeRequest]); - if($handshakeRequest->isAborted()) + if ($handshakeRequest->isAborted()) { $this->close(); - else { - $this->_socket->write($response->toString()); + } else { + $this->socket->write($response->toString()); $this->logger->debug("Got an HYBI style request, sent HYBY handshake response"); $this->connected = true; $this->emit("connect"); } - } catch(Exception $e){ - $this->logger->err("Connection error, message: ".$e->getMessage()); + } catch (Exception $e) { + $this->logger->err("Connection error, message: " . $e->getMessage()); $this->close(); } } @@ -87,26 +91,31 @@ private static function calcHybiResponse($challenge) return base64_encode(sha1($challenge . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)); } - private static function containsCompleteHeader($data) { + private static function containsCompleteHeader($data) + { return strstr($data, "\r\n\r\n"); } + /** + * @param $data + * @return array + */ public function handleData(&$data) { - if(!$this->connected) - { + if (!$this->connected) { if (!$this->containsCompleteHeader($data)) { - return array(); + return []; } $data = $this->readHandshakeResponse($data); - } + } - $frames = array(); - while ($frame = WebSocketFrame::decode($data)){ - if (WebSocketOpcode::isControlFrame($frame->getType())) + $frames = []; + while ($frame = WebSocketFrame::decode($data)) { + if (WebSocketOpcode::isControlFrame($frame->getType())) { $this->processControlFrame($frame); - else + } else { $this->processMessageFrame($frame); + } $frames[] = $frame; } @@ -114,6 +123,10 @@ public function handleData(&$data) return $frames; } + /** + * @param WebSocketFrameInterface $frame + * @return bool|void + */ public function sendFrame(WebSocketFrameInterface $frame) { /** @@ -122,7 +135,7 @@ public function sendFrame(WebSocketFrameInterface $frame) $hybiFrame = $frame; // Mask IFF client! - $hybiFrame->setMasked($this->_role == WebsocketTransportRole::CLIENT); + $hybiFrame->setMasked($this->role == WebsocketTransportRole::CLIENT); parent::sendFrame($hybiFrame); } @@ -139,15 +152,15 @@ public function sendFrame(WebSocketFrameInterface $frame) */ protected function processMessageFrame(WebSocketFrame $frame) { - if ($this->_openMessage && $this->_openMessage->isFinalised() == false) { - $this->_openMessage->takeFrame($frame); + if ($this->openMessage && $this->openMessage->isFinalised() == false) { + $this->openMessage->takeFrame($frame); } else { - $this->_openMessage = WebSocketMessage::fromFrame($frame); + $this->openMessage = WebSocketMessage::fromFrame($frame); } - if ($this->_openMessage && $this->_openMessage->isFinalised()) { - $this->emit("message", array('message' => $this->_openMessage)); - $this->_openMessage = null; + if ($this->openMessage && $this->openMessage->isFinalised()) { + $this->emit("message", ['message' => $this->openMessage]); + $this->openMessage = null; } } @@ -161,21 +174,25 @@ protected function processMessageFrame(WebSocketFrame $frame) protected function processControlFrame(WebSocketFrame $frame) { switch ($frame->getType()) { - case WebSocketOpcode::CloseFrame : + case WebSocketOpcode::CLOSE_FRAME: $this->logger->notice("Got CLOSE frame"); - $frame = WebSocketFrame::create(WebSocketOpcode::CloseFrame); + $frame = WebSocketFrame::create(WebSocketOpcode::CLOSE_FRAME); $this->sendFrame($frame); - $this->_socket->close(); + $this->socket->close(); break; - case WebSocketOpcode::PingFrame : - $frame = WebSocketFrame::create(WebSocketOpcode::PongFrame); + case WebSocketOpcode::PING_FRAME: + $frame = WebSocketFrame::create(WebSocketOpcode::PONG_FRAME); $this->sendFrame($frame); break; } } + /** + * @param $msg + * @return bool + */ public function sendString($msg) { try { @@ -189,12 +206,15 @@ public function sendString($msg) return false; } + /** + * @return void + */ public function close() { - $f = WebSocketFrame::create(WebSocketOpcode::CloseFrame); + $f = WebSocketFrame::create(WebSocketOpcode::CLOSE_FRAME); $this->sendFrame($f); - $this->_socket->close(); + $this->socket->close(); } private static function randHybiKey() @@ -207,6 +227,10 @@ private static function randHybiKey() ); } + /** + * @param Uri $uri + * @return Request + */ public function initiateHandshake(Uri $uri) { $challenge = self::randHybiKey(); @@ -215,9 +239,9 @@ public function initiateHandshake(Uri $uri) $requestUri = $uri->getPath(); - if($uri->getQuery()) - $requestUri .= "?".$uri->getQuery(); - + if ($uri->getQuery()) { + $requestUri .= "?" . $uri->getQuery(); + } $request->setUri($requestUri); @@ -229,9 +253,9 @@ public function initiateHandshake(Uri $uri) $this->setRequest($request); - $this->emit("request", array($request)); + $this->emit("request", [$request]); - $this->_socket->write($request->toString()); + $this->socket->write($request->toString()); return $request; } @@ -243,9 +267,9 @@ private function readHandshakeResponse($data) $handshake = new Handshake($this->request, $response); - $this->emit("handshake", array($handshake)); + $this->emit("handshake", [$handshake]); - if($handshake->isAborted()){ + if ($handshake->isAborted()) { $this->close(); return ''; } @@ -255,5 +279,4 @@ private function readHandshakeResponse($data) return $response->getContent(); } - } diff --git a/src/Devristo/Phpws/Protocol/WebSocketTransportInterface.php b/src/Devristo/Phpws/Protocol/WebSocketTransportInterface.php index d5108db..a9da8e4 100644 --- a/src/Devristo/Phpws/Protocol/WebSocketTransportInterface.php +++ b/src/Devristo/Phpws/Protocol/WebSocketTransportInterface.php @@ -8,16 +8,17 @@ */ namespace Devristo\Phpws\Protocol; -use Devristo\Phpws\Framing\WebSocketFrameInterface; -use Devristo\Phpws\Messaging\WebSocketMessageInterface; use Zend\Http\Request; use Zend\Http\Response; interface WebSocketTransportInterface extends TransportInterface { - public function getId(); + /** + * @param Request $request + * @return mixed + */ public function respondTo(Request $request); /** @@ -30,13 +31,32 @@ public function getHandshakeRequest(); */ public function getHandshakeResponse(); + /** + * @param $data + * @return mixed + */ public function handleData(&$data); + /** + * @return mixed + */ public function getIp(); + /** + * @return mixed + */ public function close(); + /** + * @param $key + * @param $value + * @return mixed + */ public function setData($key, $value); + /** + * @param $key + * @return mixed + */ public function getData($key); } diff --git a/src/Devristo/Phpws/Protocol/WebsocketTransportRole.php b/src/Devristo/Phpws/Protocol/WebsocketTransportRole.php index 72cbec5..a285e16 100644 --- a/src/Devristo/Phpws/Protocol/WebsocketTransportRole.php +++ b/src/Devristo/Phpws/Protocol/WebsocketTransportRole.php @@ -10,8 +10,6 @@ class WebsocketTransportRole { - const CLIENT = 0; const SERVER = 1; - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Reflection/FullAccessWrapper.php b/src/Devristo/Phpws/Reflection/FullAccessWrapper.php index 503b2a5..32fdba3 100644 --- a/src/Devristo/Phpws/Reflection/FullAccessWrapper.php +++ b/src/Devristo/Phpws/Reflection/FullAccessWrapper.php @@ -6,37 +6,36 @@ namespace Devristo\Phpws\Reflection; - class FullAccessWrapper { - protected $_self; - protected $_refl; + protected $self; + protected $refl; public function __construct($self) { - $this->_self = $self; - $this->_refl = new \ReflectionObject($self); + $this->self = $self; + $this->refl = new \ReflectionObject($self); } public function __call($method, $args) { - $mrefl = $this->_refl->getMethod($method); + $mrefl = $this->refl->getMethod($method); $mrefl->setAccessible(true); - return $mrefl->invokeArgs($this->_self, $args); + return $mrefl->invokeArgs($this->self, $args); } public function __set($name, $value) { - $prefl = $this->_refl->getProperty($name); + $prefl = $this->refl->getProperty($name); $prefl->setAccessible(true); - $prefl->setValue($this->_self, $value); + $prefl->setValue($this->self, $value); } public function __get($name) { - $prefl = $this->_refl->getProperty($name); + $prefl = $this->refl->getProperty($name); $prefl->setAccessible(true); - return $prefl->getValue($this->_self); + return $prefl->getValue($this->self); } public function __isset($name) @@ -44,4 +43,4 @@ public function __isset($name) $value = $this->__get($name); return isset($value); } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/RemoteEvent/RemoteEventTransport.php b/src/Devristo/Phpws/RemoteEvent/RemoteEventTransport.php index 2887c6b..3bbfab2 100644 --- a/src/Devristo/Phpws/RemoteEvent/RemoteEventTransport.php +++ b/src/Devristo/Phpws/RemoteEvent/RemoteEventTransport.php @@ -16,7 +16,8 @@ use React\Promise\Deferred; use Zend\Log\LoggerInterface; -class RemoteEventTransport extends EventEmitter implements TransportInterface{ +class RemoteEventTransport extends EventEmitter implements TransportInterface +{ /** * @var TransportInterface */ @@ -26,16 +27,26 @@ class RemoteEventTransport extends EventEmitter implements TransportInterface{ /** * @var Deferred[] */ - protected $deferred = array(); - protected $timers = array(); + protected $deferred = []; + protected $timers = []; protected $actionEmitter; - public function remoteEvent(){ + /** + * @var LoopInterface + */ + protected $loop; + + /** + * @return EventEmitter + */ + public function remoteEvent() + { return $this->actionEmitter; } - public function __construct(TransportInterface $carrierProtocol, LoopInterface $loop, LoggerInterface $logger){ + public function __construct(TransportInterface $carrierProtocol, LoopInterface $loop, LoggerInterface $logger) + { $that = $this; $this->logger = $logger; $this->loop = $loop; @@ -46,34 +57,44 @@ public function __construct(TransportInterface $carrierProtocol, LoopInterface $ $deferreds = &$this->deferred; $timers = &$this->timers; - $carrierProtocol->on("message", function(MessageInterface $message) use (&$deferreds, &$timers, &$loop, $that, $logger){ - $string = $message->getData(); + $carrierProtocol->on( + "message", + function (MessageInterface $message) use (&$deferreds, &$timers, &$loop, $that, $logger) { + $string = $message->getData(); - try{ - $jsonMessage = RemoteEventMessage::fromJson($string); + try { + $jsonMessage = RemoteEventMessage::fromJson($string); - $tag = $jsonMessage->getTag(); + $tag = $jsonMessage->getTag(); - if(array_key_exists($tag, $deferreds)){ - $deferred = $deferreds[$tag]; - unset($deferreds[$tag]); + if (array_key_exists($tag, $deferreds)) { + $deferred = $deferreds[$tag]; + unset($deferreds[$tag]); - if(array_key_exists($tag, $timers)){ - $loop->cancelTimer($timers[$tag]); - unset($timers[$tag]); + if (array_key_exists($tag, $timers)) { + $loop->cancelTimer($timers[$tag]); + unset($timers[$tag]); + } + $deferred->resolve($jsonMessage); + } else { + $that->remoteEvent()->emit($jsonMessage->getEvent(), [$jsonMessage]); } - $deferred->resolve($jsonMessage); - }else - $that->remoteEvent()->emit($jsonMessage->getEvent(), array($jsonMessage)); - $that->emit("message", array($jsonMessage)); - }catch(\Exception $e){ - $logger->err("Exception while parsing JsonMessage: ".$e->getMessage()); + $that->emit("message", [$jsonMessage]); + + } catch (\Exception $e) { + $logger->err("Exception while parsing JsonMessage: " . $e->getMessage()); + } } - }); + ); } - public function replyTo(RemoteEventMessage $message, $data){ + /** + * @param RemoteEventMessage $message + * @param $data + */ + public function replyTo(RemoteEventMessage $message, $data) + { $reply = new RemoteEventMessage(); $reply->setRoom($message->getRoom()); $reply->setTag($message->getTag()); @@ -83,7 +104,13 @@ public function replyTo(RemoteEventMessage $message, $data){ $this->carrierProtocol->sendString($reply->toJson()); } - public function whenResponseTo(RemoteEventMessage $message, $timeout=null){ + /** + * @param RemoteEventMessage $message + * @param null $timeout + * @return \React\Promise\Promise|\React\Promise\PromiseInterface + */ + public function whenResponseTo(RemoteEventMessage $message, $timeout = null) + { $deferred = new Deferred(); $tag = $message->getTag(); @@ -91,17 +118,17 @@ public function whenResponseTo(RemoteEventMessage $message, $timeout=null){ $this->carrierProtocol->sendString($message->toJson()); $this->logger->debug(sprintf( - "Awaiting response to '%s'%s with %s" - , $message->getData() - , $message->getRoom() ? " in room ".$message->getRoom() : '' - , $timeout ? "timeout $timeout" : 'no timeout' + "Awaiting response to '%s'%s with %s", + $message->getData(), + $message->getRoom() ? " in room " . $message->getRoom() : '', + $timeout ? "timeout $timeout" : 'no timeout' )); - if($timeout){ + if ($timeout) { $list = &$this->deferred; $logger = $this->logger; - $this->timers[$tag] = $this->loop->addTimer($timeout, function() use($deferred, &$list, $tag, $logger){ + $this->timers[$tag] = $this->loop->addTimer($timeout, function () use ($deferred, &$list, $tag, $logger) { unset($list[$tag]); $logger->debug("Request with tag $tag has timed out"); $deferred->reject("Timeout occurred"); @@ -111,11 +138,20 @@ public function whenResponseTo(RemoteEventMessage $message, $timeout=null){ return $deferred->promise(); } - public function sendEmit($room, $event, $data){ + /** + * @param $room + * @param $event + * @param $data + */ + public function sendEmit($room, $event, $data) + { $message = RemoteEventMessage::create($room, $event, $data); $this->send($message); } + /** + * @param $string + */ public function sendString($string) { $message = new RemoteEventMessage(); @@ -125,8 +161,11 @@ public function sendString($string) $this->send($message); } + /** + * @param RemoteEventMessage $message + */ public function send(RemoteEventMessage $message) { $this->carrierProtocol->sendString($message->toJson()); } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/RemoteEvent/RemoteEvents.php b/src/Devristo/Phpws/RemoteEvent/RemoteEvents.php index 85cb7a4..8bb281a 100644 --- a/src/Devristo/Phpws/RemoteEvent/RemoteEvents.php +++ b/src/Devristo/Phpws/RemoteEvent/RemoteEvents.php @@ -4,14 +4,13 @@ use Devristo\Phpws\Messaging\RemoteEventMessage; use Devristo\Phpws\Protocol\StackTransport; -use Devristo\Phpws\RemoteEvent\Room; class RemoteEvents extends \Evenement\EventEmitter { /** * @var Room[] */ - protected $rooms = array(); + protected $rooms = []; protected $logger; public function __construct(\Zend\Log\LoggerInterface $logger) @@ -25,28 +24,33 @@ public function __construct(\Zend\Log\LoggerInterface $logger) */ public function room($room) { - if (!array_key_exists($room, $this->rooms)) + if (!array_key_exists($room, $this->rooms)) { $this->rooms[$room] = new Room($room, $this->logger); + } return $this->rooms[$room]; } + /** + * @param StackTransport $transport + */ public function listenTo(StackTransport $transport) { $self = $this; $transport->on("message", function (RemoteEventMessage $message) use ($transport, $self) { $room = $message->getRoom(); - if (!$room) + if (!$room) { return; + } $event = $message->getEvent(); - if ($message->getEvent() == 'subscribe'){ + if ($message->getEvent() == 'subscribe') { $self->room($room)->subscribe($transport); // If the transport is disconnected, make sure we 'fake' the unsubscribe - $transport->getWebSocketTransport()->on("close", function() use ($self, $transport, $room){ + $transport->getWebSocketTransport()->on("close", function () use ($self, $transport, $room) { $self->room($room)->unsubscribe($transport); // Fake unsubscribe message @@ -54,22 +58,24 @@ public function listenTo(StackTransport $transport) $message->setEvent("unsubscribe"); $message->setRoom($room); - $self->emit("unsubscribe", array($transport, $message)); - $self->room($room)->emit("unsubscribe", array($transport, $message)); + $self->emit("unsubscribe", [$transport, $message]); + $self->room($room)->emit("unsubscribe", [$transport, $message]); }); - } elseif ($message->getEvent() == 'unsubscribe'){ + } elseif ($message->getEvent() == 'unsubscribe') { $self->room($room)->unsubscribe($transport); } - - $self->room($room)->emit($message->getEvent(), array($transport, $message)); - $self->emit($event, array($transport, $message)); + $self->room($room)->emit($message->getEvent(), [$transport, $message]); + $self->emit($event, [$transport, $message]); }); } + /** + * @return array + */ public function getRooms() { return array_keys($this->rooms); } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/RemoteEvent/Room.php b/src/Devristo/Phpws/RemoteEvent/Room.php index 143dd08..9ae6b8d 100644 --- a/src/Devristo/Phpws/RemoteEvent/Room.php +++ b/src/Devristo/Phpws/RemoteEvent/Room.php @@ -6,7 +6,7 @@ class Room extends \Evenement\EventEmitter { - private $members = array(); + private $members = []; private $name = ''; private $logger; @@ -16,18 +16,24 @@ public function __construct($name, \Zend\Log\LoggerInterface $logger) $this->logger = $logger; } + /** + * @param StackTransport $transport + */ public function subscribe(StackTransport $transport) { $this->members[$transport->getId()] = $transport; $this->logger->notice("[{$this->name}] User {$transport->getId()} has subscribed!"); } + /** + * @param StackTransport $transport + */ public function unsubscribe(StackTransport $transport) { - if (array_key_exists($transport->getId(), $this->members)){ + if (array_key_exists($transport->getId(), $this->members)) { unset($this->members[$transport->getId()]); - $this->emit("unsubscribe", array($transport)); + $this->emit("unsubscribe", [$transport]); } } @@ -39,10 +45,15 @@ public function getMembers() return array_values($this->members); } - public function remoteEmit($event, $data){ - foreach($this->getMembers() as $member){ + /** + * @param $event + * @param $data + */ + public function remoteEmit($event, $data) + { + foreach ($this->getMembers() as $member) { $message = RemoteEventMessage::create($this->name, $event, $data); $member->getTopTransport()->send($message); } } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Server/OriginEnforcer.php b/src/Devristo/Phpws/Server/OriginEnforcer.php index 0e51167..a6c00cc 100644 --- a/src/Devristo/Phpws/Server/OriginEnforcer.php +++ b/src/Devristo/Phpws/Server/OriginEnforcer.php @@ -7,20 +7,23 @@ */ namespace Devristo\Phpws\Server; + use Devristo\Phpws\Protocol\Handshake; -class OriginEnforcer { - public function __construct(WebSocketServer $server, array $allowedOrigins){ - $server->on("handshake", function(Handshake $handshake) use ($allowedOrigins){ +class OriginEnforcer +{ + public function __construct(WebSocketServer $server, array $allowedOrigins) + { + $server->on("handshake", function (Handshake $handshake) use ($allowedOrigins) { $originHeader = $handshake->getRequest()->getHeader('Origin', null); $origin = $originHeader ? $originHeader->getFieldValue() : null; - if(in_array("*", $allowedOrigins) || !in_array($origin, $allowedOrigins)) + if (in_array("*", $allowedOrigins) || !in_array($origin, $allowedOrigins)) { $handshake->abort(); - else{ + } else { // Confirm that the origin is allowed $handshake->getResponse()->getHeaders()->addHeaderLine("Access-Control-Allow-Origin", $origin); } }); } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Server/UriHandler/ClientRouter.php b/src/Devristo/Phpws/Server/UriHandler/ClientRouter.php index 34d577b..30e1b05 100644 --- a/src/Devristo/Phpws/Server/UriHandler/ClientRouter.php +++ b/src/Devristo/Phpws/Server/UriHandler/ClientRouter.php @@ -8,20 +8,24 @@ namespace Devristo\Phpws\Server\UriHandler; -use Devristo\Phpws\Messaging\MessageInterface; use Devristo\Phpws\Messaging\WebSocketMessageInterface; -use Devristo\Phpws\Protocol\TransportInterface; -use Devristo\Phpws\Protocol\WebSocketTransport; use Devristo\Phpws\Protocol\WebSocketTransportInterface; -use Devristo\Phpws\Server\WebSocketServer; +use Evenement\EventEmitter; use Zend\Log\LoggerInterface; -class ClientRouter { +class ClientRouter +{ protected $handlers; protected $logger; protected $membership; - public function __construct($server, LoggerInterface $logger){ + + /** + * @param EventEmitter $server + * @param LoggerInterface $logger + */ + public function __construct(EventEmitter $server, LoggerInterface $logger) + { $this->server = $server; $this->logger = $logger; $this->handlers = new \SplObjectStorage(); @@ -34,51 +38,82 @@ public function __construct($server, LoggerInterface $logger){ $that = $this; - $server->on("connect", function(WebSocketTransportInterface $client) use ($that, $logger, $membership){ - $handler = $that->matchConnection($client); - - if($handler){ - $logger->notice("Added client {$client->getId()} to ".get_class($handler)); - $membership->attach($client, $handler); - $handler->emit("connect", array("client" => $client)); - $handler->addConnection($client); - }else - $logger->err("Cannot route {$client->getId()} with request uri {$client->getHandshakeRequest()->getUriString()}"); - }); + $server->on( + "connect", + function (WebSocketTransportInterface $client) use ($that, $logger, $membership) { + $handler = $that->matchConnection($client); + + if ($handler) { + $logger->notice("Added client {$client->getId()} to " . get_class($handler)); + $membership->attach($client, $handler); + $handler->emit("connect", ["client" => $client]); + $handler->addConnection($client); + } else { + $logger->err( + sprintf( + "Cannot route %s with request uri %s", + $client->getId(), + $client->getHandshakeRequest()->getUriString() + ) + ); + } + } + ); - $server->on('disconnect', function(WebSocketTransportInterface $client) use($that, $logger, $membership){ - if($membership->contains($client)){ - $handler = $membership[$client]; - $membership->detach($client); + $server->on( + 'disconnect', + function (WebSocketTransportInterface $client) use ($that, $logger, $membership) { + if ($membership->contains($client)) { + $handler = $membership[$client]; + $membership->detach($client); - $logger->notice("Removed client {$client->getId()} from".get_class($handler)); + $logger->notice("Removed client {$client->getId()} from" . get_class($handler)); - $handler->removeConnection($client); - $handler->emit("disconnect", array("client" => $client)); + $handler->removeConnection($client); + $handler->emit("disconnect", ["client" => $client]); - } else { - $logger->warn("Client {$client->getId()} not attached to any handler, so cannot remove it!"); + } else { + $logger->warn("Client {$client->getId()} not attached to any handler, so cannot remove it!"); + } } - }); - - $server->on("message", function(WebSocketTransportInterface $client, WebSocketMessageInterface $message) use($that, $logger, $membership){ - if($membership->contains($client)){ - $handler = $membership[$client]; - $handler->emit("message", compact('client', 'message')); - } else { - $logger->warn("Client {$client->getId()} not attached to any handler, so cannot forward the message!"); + ); + + $server->on( + "message", + function ( + WebSocketTransportInterface $client, + WebSocketMessageInterface $message + ) use ( + $that, + $logger, + $membership + ) { + if ($membership->contains($client)) { + $handler = $membership[$client]; + $handler->emit("message", compact('client', 'message')); + } else { + $logger->warn( + sprintf( + "Client %s not attached to any handler, so cannot forward the message!", + $client->getId() + ) + ); + } } - }); + ); } /** * @param \Devristo\Phpws\Protocol\WebSocketTransportInterface $transport * @return null|WebSocketUriHandlerInterface */ - public function matchConnection(WebSocketTransportInterface $transport){ - foreach($this->handlers as $tester){ - if($tester($transport)) + public function matchConnection(WebSocketTransportInterface $transport) + { + foreach ($this->handlers as $tester) { + /** @var \Closure $tester */ + if ($tester($transport)) { return $this->handlers[$tester]; + } } return null; @@ -89,14 +124,15 @@ public function matchConnection(WebSocketTransportInterface $transport){ * @param WebSocketUriHandlerInterface $handler * @throws \InvalidArgumentException */ - public function addRoute($tester, WebSocketUriHandlerInterface $handler){ - if(is_string($tester)){ - $tester = function(WebSocketTransportInterface $transport) use ($tester){ + public function addRoute($tester, WebSocketUriHandlerInterface $handler) + { + if (is_string($tester)) { + $tester = function (WebSocketTransportInterface $transport) use ($tester) { return preg_match($tester, $transport->getHandshakeRequest()->getUriString()); }; - } elseif(!is_callable($tester)) + } elseif (!is_callable($tester)) throw new \InvalidArgumentException("Tester should either be a regexp or a callable"); $this->handlers->attach($tester, $handler); } -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandler.php b/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandler.php index e87f222..608b273 100644 --- a/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandler.php +++ b/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandler.php @@ -11,7 +11,6 @@ class WebSocketUriHandler extends EventEmitter implements WebSocketUriHandlerInterface { - /** * * Enter description here ... @@ -36,30 +35,52 @@ public function __construct($logger) $this->users = new SplObjectStorage(); $this->logger = $logger; - $this->on("message", array($this, 'onMessage')); - $this->on("disconnect", array($this, 'onDisconnect')); - $this->on("connect", array($this, 'onConnect')); + $this->on("message", [$this, 'onMessage']); + $this->on("disconnect", [$this, 'onDisconnect']); + $this->on("connect", [$this, 'onConnect']); } + /** + * @param WebSocketTransportInterface $user + * @return void + */ public function addConnection(WebSocketTransportInterface $user) { $this->users->attach($user); } + /** + * @param WebSocketTransportInterface $user + * @return void + */ public function removeConnection(WebSocketTransportInterface $user) { $this->users->detach($user); } + /** + * @param WebSocketTransportInterface $user + * @return void + */ public function onDisconnect(WebSocketTransportInterface $user) { } - public function onConnect(WebSocketTransportInterface $user){ + /** + * @param WebSocketTransportInterface $user + * @return void + */ + public function onConnect(WebSocketTransportInterface $user) + { } + /** + * @param WebSocketTransportInterface $user + * @param WebSocketMessageInterface $msg + * @return void + */ public function onMessage(WebSocketTransportInterface $user, WebSocketMessageInterface $msg) { @@ -72,5 +93,4 @@ public function getConnections() { return $this->users; } - -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandlerInterface.php b/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandlerInterface.php index afeb8ea..d0356d2 100644 --- a/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandlerInterface.php +++ b/src/Devristo/Phpws/Server/UriHandler/WebSocketUriHandlerInterface.php @@ -13,13 +13,20 @@ interface WebSocketUriHandlerInterface extends EventEmitterInterface { - + /** + * @param WebSocketTransportInterface $user + * @return mixed + */ public function addConnection(WebSocketTransportInterface $user); + /** + * @param WebSocketTransportInterface $user + * @return mixed + */ public function removeConnection(WebSocketTransportInterface $user); /** * @return WebSocketTransportInterface[] */ public function getConnections(); -} \ No newline at end of file +} diff --git a/src/Devristo/Phpws/Server/WebSocketServer.php b/src/Devristo/Phpws/Server/WebSocketServer.php index fa0aca0..a9fbc57 100644 --- a/src/Devristo/Phpws/Server/WebSocketServer.php +++ b/src/Devristo/Phpws/Server/WebSocketServer.php @@ -9,7 +9,6 @@ use Devristo\Phpws\Protocol\WebSocketTransportInterface; use Devristo\Phpws\Protocol\WebSocketConnection; use Evenement\EventEmitter; -use Exception; use React\EventLoop\LoopInterface; use SplObjectStorage; use Zend\Log\LoggerInterface; @@ -22,37 +21,53 @@ */ class WebSocketServer extends EventEmitter { - protected $_url; + protected $url; + + /** + * @var Uri + */ + protected $uri; + + /** + * @var LoopInterface + */ + protected $loop; /** * * The raw streams connected to the WebSocket server (whether a handshake has taken place or not) * @var WebSocketConnection[]|SplObjectStorage */ - protected $_streams; + protected $streams; /** * The connected clients to the WebSocket server, a valid handshake has been performed. * @var \SplObjectStorage|WebSocketTransportInterface[] */ - protected $_connections = array(); + protected $connections = []; - protected $purgeUserTimeOut = null; - protected $_context = null; + protected $purgeUserTimeOut; + protected $context; + + /** + * @var LoggerInterface + */ + protected $logger; /** * * Enter description here ... * @var \Devristo\Phpws\Server\UriHandler\WebSocketUriHandlerInterface[] */ - protected $uriHandlers = array(); + protected $uriHandlers = []; /** * Flash-policy-response for flashplayer/flashplugin * @access protected * @var string */ - protected $FLASH_POLICY_FILE = "\0"; + protected $flashPolicyFile = + "\0"; /** * Handle incoming messages. @@ -68,32 +83,40 @@ public function __construct($url, LoopInterface $loop, LoggerInterface $logger) { $uri = new Uri($url); - if($uri->getScheme() == 'ws') + if ($uri->getScheme() == 'ws') { $uri->setScheme('tcp'); - elseif($uri->getScheme() == 'wss') + } elseif ($uri->getScheme() == 'wss') { $uri->setScheme('ssl'); + } - if($uri->getScheme() != 'tcp' && $uri->getScheme() != 'ssl') + if ($uri->getScheme() != 'tcp' && $uri->getScheme() != 'ssl') { throw new \InvalidArgumentException("Uri scheme must be one of: tcp, ssl, ws, wss"); + } $this->uri = $uri; $this->loop = $loop; - $this->_streams = new SplObjectStorage(); - $this->_connections = new SplObjectStorage(); + $this->streams = new SplObjectStorage(); + $this->connections = new SplObjectStorage(); - $this->_context = stream_context_create(); - $this->_logger = $logger; + $this->context = stream_context_create(); + $this->logger = $logger; } + /** + * @return resource + */ public function getStreamContext() { - return $this->_context; + return $this->context; } + /** + * @param $context + */ public function setStreamContext($context) { - $this->_context = $context; + $this->context = $context; } /** @@ -104,21 +127,28 @@ public function bind() $err = $errno = 0; - $this->FLASH_POLICY_FILE = str_replace('to-ports="*', 'to-ports="' . $this->uri->getPort() ?: 80, $this->FLASH_POLICY_FILE); + $this->flashPolicyFile = + str_replace('to-ports="*', 'to-ports="' . $this->uri->getPort() ?: 80, $this->flashPolicyFile); - $serverSocket = stream_socket_server($this->uri->toString(), $errno, $err, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $this->_context); + $serverSocket = stream_socket_server( + $this->uri->toString(), + $errno, + $err, + STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, + $this->context + ); - $this->_logger->notice(sprintf("phpws listening on %s", $this->uri->toString())); + $this->logger->notice(sprintf("phpws listening on %s", $this->uri->toString())); if ($serverSocket == false) { - $this->_logger->err("Error: $err"); + $this->logger->err("Error: $err"); return; } - $timeOut = & $this->purgeUserTimeOut; - $sockets = $this->_streams; + $timeOut = &$this->purgeUserTimeOut; + $sockets = $this->streams; $that = $this; - $logger = $this->_logger; + $logger = $this->logger; $this->loop->addReadStream($serverSocket, function ($serverSocket) use ($that, $logger, $sockets) { $newSocket = stream_socket_accept($serverSocket); @@ -131,33 +161,33 @@ public function bind() $client = new WebSocketConnection($newSocket, $that->loop, $logger); $sockets->attach($client); - $client->on("handshake", function(Handshake $request) use($that, $client){ - $that->emit("handshake",array($client->getTransport(), $request)); + $client->on("handshake", function (Handshake $request) use ($that, $client) { + $that->emit("handshake", [$client->getTransport(), $request]); }); $client->on("connect", function () use ($that, $client, $logger) { $con = $client->getTransport(); $that->getConnections()->attach($con); - $that->emit("connect", array("client" => $con)); + $that->emit("connect", ["client" => $con]); }); $client->on("message", function ($message) use ($that, $client, $logger) { $connection = $client->getTransport(); - $that->emit("message", array("client" => $connection, "message" => $message)); + $that->emit("message", ["client" => $connection, "message" => $message]); }); $client->on("close", function () use ($that, $client, $logger, &$sockets, $client) { $sockets->detach($client); $connection = $client->getTransport(); - if($connection){ + if ($connection) { $that->getConnections()->detach($connection); - $that->emit("disconnect", array("client" => $connection)); + $that->emit("disconnect", ["client" => $connection]); } }); $client->on("flashXmlRequest", function () use ($that, $client) { - $client->getTransport()->sendString($that->FLASH_POLICY_FILE); + $client->getTransport()->sendString($that->flashPolicyFile); $client->close(); }); }); @@ -165,14 +195,16 @@ public function bind() $this->loop->addPeriodicTimer(5, function () use ($timeOut, $sockets, $that) { # Lets send some pings - foreach($that->getConnections() as $c){ - if($c instanceof WebSocketTransportHybi) - $c->sendFrame(WebSocketFrame::create(WebSocketOpcode::PingFrame)); + foreach ($that->getConnections() as $c) { + if ($c instanceof WebSocketTransportHybi) { + $c->sendFrame(WebSocketFrame::create(WebSocketOpcode::PING_FRAME)); + } } $currentTime = time(); - if ($timeOut == null) + if ($timeOut == null) { return; + } foreach ($sockets as $s) { if ($currentTime - $s->getLastChanged() > $timeOut) { @@ -182,9 +214,11 @@ public function bind() }); } + /** + * @return \Devristo\Phpws\Protocol\WebSocketTransportInterface[]|SplObjectStorage + */ public function getConnections() { - return $this->_connections; + return $this->connections; } } - From 140ab72e572eb732470047c5f8d22d3a5ea61bf4 Mon Sep 17 00:00:00 2001 From: Alexander Valinurov Date: Thu, 28 Jan 2016 18:59:59 +0300 Subject: [PATCH 2/2] add dns-server injection possibility --- src/Devristo/Phpws/Client/WebSocket.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Devristo/Phpws/Client/WebSocket.php b/src/Devristo/Phpws/Client/WebSocket.php index 1cf0018..3f99452 100644 --- a/src/Devristo/Phpws/Client/WebSocket.php +++ b/src/Devristo/Phpws/Client/WebSocket.php @@ -13,6 +13,7 @@ use Devristo\Phpws\Protocol\WebSocketConnection; use Devristo\Phpws\Reflection\FullAccessWrapper; use Evenement\EventEmitter; +use React\Dns\Resolver\Resolver; use React\EventLoop\LoopInterface; use React\Promise\Deferred; use Zend\Http\Request; @@ -63,13 +64,15 @@ class WebSocket extends EventEmitter * @param LoopInterface $loop * @param LoggerInterface $logger * @param array|null $streamOptions + * @param string $dns * @throws WebSocketInvalidUrlScheme */ public function __construct( $url, LoopInterface $loop, LoggerInterface $logger, - array $streamOptions = null + array $streamOptions = null, + $dns = '8.8.8.8' ) { $this->logger = $logger; $this->loop = $loop; @@ -83,7 +86,7 @@ public function __construct( } $dnsResolverFactory = new \React\Dns\Resolver\Factory(); - $this->dns = $dnsResolverFactory->createCached('8.8.8.8', $loop); + $this->dns = $dnsResolverFactory->createCached($dns, $loop); } /**