diff options
author | marvin-borner@live.com | 2018-04-10 21:50:16 +0200 |
---|---|---|
committer | marvin-borner@live.com | 2018-04-10 21:54:48 +0200 |
commit | fc9401f04a3aca5abb22f87ebc210de8afe11d32 (patch) | |
tree | b0b310f3581764ec3955f4e496a05137a32951c3 /assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp | |
parent | 286d643180672f20526f3dc3bd19d7b751e2fa97 (diff) |
Initial Commit
Diffstat (limited to 'assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp')
8 files changed, 646 insertions, 0 deletions
diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php new file mode 100644 index 0000000..6c824da --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Exception.php @@ -0,0 +1,5 @@ +<?php +namespace Ratchet\Wamp; + +class Exception extends \Exception { +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php new file mode 100644 index 0000000..8f05d28 --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/JsonException.php @@ -0,0 +1,31 @@ +<?php +namespace Ratchet\Wamp; + +class JsonException extends Exception { + public function __construct() { + $code = json_last_error(); + + switch ($code) { + case JSON_ERROR_DEPTH: + $msg = 'Maximum stack depth exceeded'; + break; + case JSON_ERROR_STATE_MISMATCH: + $msg = 'Underflow or the modes mismatch'; + break; + case JSON_ERROR_CTRL_CHAR: + $msg = 'Unexpected control character found'; + break; + case JSON_ERROR_SYNTAX: + $msg = 'Syntax error, malformed JSON'; + break; + case JSON_ERROR_UTF8: + $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; + break; + default: + $msg = 'Unknown error'; + break; + } + + parent::__construct($msg, $code); + } +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php new file mode 100644 index 0000000..2d6d799 --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/ServerProtocol.php @@ -0,0 +1,161 @@ +<?php +namespace Ratchet\Wamp; +use Ratchet\MessageComponentInterface; +use Ratchet\WebSocket\WsServerInterface; +use Ratchet\ConnectionInterface; + +/** + * WebSocket Application Messaging Protocol + * + * @link http://wamp.ws/spec + * @link https://github.com/oberstet/autobahn-js + * + * +--------------+----+------------------+ + * | Message Type | ID | DIRECTION | + * |--------------+----+------------------+ + * | WELCOME | 0 | Server-to-Client | + * | PREFIX | 1 | Bi-Directional | + * | CALL | 2 | Client-to-Server | + * | CALL RESULT | 3 | Server-to-Client | + * | CALL ERROR | 4 | Server-to-Client | + * | SUBSCRIBE | 5 | Client-to-Server | + * | UNSUBSCRIBE | 6 | Client-to-Server | + * | PUBLISH | 7 | Client-to-Server | + * | EVENT | 8 | Server-to-Client | + * +--------------+----+------------------+ + */ +class ServerProtocol implements MessageComponentInterface, WsServerInterface { + const MSG_WELCOME = 0; + const MSG_PREFIX = 1; + const MSG_CALL = 2; + const MSG_CALL_RESULT = 3; + const MSG_CALL_ERROR = 4; + const MSG_SUBSCRIBE = 5; + const MSG_UNSUBSCRIBE = 6; + const MSG_PUBLISH = 7; + const MSG_EVENT = 8; + + /** + * @var WampServerInterface + */ + protected $_decorating; + + /** + * @var \SplObjectStorage + */ + protected $connections; + + /** + * @param WampServerInterface $serverComponent An class to propagate calls through + */ + public function __construct(WampServerInterface $serverComponent) { + $this->_decorating = $serverComponent; + $this->connections = new \SplObjectStorage; + } + + /** + * {@inheritdoc} + */ + public function getSubProtocols() { + if ($this->_decorating instanceof WsServerInterface) { + $subs = $this->_decorating->getSubProtocols(); + $subs[] = 'wamp'; + + return $subs; + } + + return ['wamp']; + } + + /** + * {@inheritdoc} + */ + public function onOpen(ConnectionInterface $conn) { + $decor = new WampConnection($conn); + $this->connections->attach($conn, $decor); + + $this->_decorating->onOpen($decor); + } + + /** + * {@inheritdoc} + * @throws \Ratchet\Wamp\Exception + * @throws \Ratchet\Wamp\JsonException + */ + public function onMessage(ConnectionInterface $from, $msg) { + $from = $this->connections[$from]; + + if (null === ($json = @json_decode($msg, true))) { + throw new JsonException; + } + + if (!is_array($json) || $json !== array_values($json)) { + throw new Exception("Invalid WAMP message format"); + } + + if (isset($json[1]) && !(is_string($json[1]) || is_numeric($json[1]))) { + throw new Exception('Invalid Topic, must be a string'); + } + + switch ($json[0]) { + case static::MSG_PREFIX: + $from->WAMP->prefixes[$json[1]] = $json[2]; + break; + + case static::MSG_CALL: + array_shift($json); + $callID = array_shift($json); + $procURI = array_shift($json); + + if (count($json) == 1 && is_array($json[0])) { + $json = $json[0]; + } + + $this->_decorating->onCall($from, $callID, $from->getUri($procURI), $json); + break; + + case static::MSG_SUBSCRIBE: + $this->_decorating->onSubscribe($from, $from->getUri($json[1])); + break; + + case static::MSG_UNSUBSCRIBE: + $this->_decorating->onUnSubscribe($from, $from->getUri($json[1])); + break; + + case static::MSG_PUBLISH: + $exclude = (array_key_exists(3, $json) ? $json[3] : null); + if (!is_array($exclude)) { + if (true === (boolean)$exclude) { + $exclude = [$from->WAMP->sessionId]; + } else { + $exclude = []; + } + } + + $eligible = (array_key_exists(4, $json) ? $json[4] : []); + + $this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2], $exclude, $eligible); + break; + + default: + throw new Exception('Invalid WAMP message type'); + } + } + + /** + * {@inheritdoc} + */ + public function onClose(ConnectionInterface $conn) { + $decor = $this->connections[$conn]; + $this->connections->detach($conn); + + $this->_decorating->onClose($decor); + } + + /** + * {@inheritdoc} + */ + public function onError(ConnectionInterface $conn, \Exception $e) { + return $this->_decorating->onError($this->connections[$conn], $e); + } +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php new file mode 100644 index 0000000..bca8f67 --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/Topic.php @@ -0,0 +1,99 @@ +<?php +namespace Ratchet\Wamp; +use Ratchet\ConnectionInterface; + +/** + * A topic/channel containing connections that have subscribed to it + */ +class Topic implements \IteratorAggregate, \Countable { + private $id; + + private $subscribers; + + /** + * @param string $topicId Unique ID for this object + */ + public function __construct($topicId) { + $this->id = $topicId; + $this->subscribers = new \SplObjectStorage; + } + + /** + * @return string + */ + public function getId() { + return $this->id; + } + + public function __toString() { + return $this->getId(); + } + + /** + * Send a message to all the connections in this topic + * @param string|array $msg Payload to publish + * @param array $exclude A list of session IDs the message should be excluded from (blacklist) + * @param array $eligible A list of session Ids the message should be send to (whitelist) + * @return Topic The same Topic object to chain + */ + public function broadcast($msg, array $exclude = array(), array $eligible = array()) { + $useEligible = (bool)count($eligible); + foreach ($this->subscribers as $client) { + if (in_array($client->WAMP->sessionId, $exclude)) { + continue; + } + + if ($useEligible && !in_array($client->WAMP->sessionId, $eligible)) { + continue; + } + + $client->event($this->id, $msg); + } + + return $this; + } + + /** + * @param WampConnection $conn + * @return boolean + */ + public function has(ConnectionInterface $conn) { + return $this->subscribers->contains($conn); + } + + /** + * @param WampConnection $conn + * @return Topic + */ + public function add(ConnectionInterface $conn) { + $this->subscribers->attach($conn); + + return $this; + } + + /** + * @param WampConnection $conn + * @return Topic + */ + public function remove(ConnectionInterface $conn) { + if ($this->subscribers->contains($conn)) { + $this->subscribers->detach($conn); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getIterator() { + return $this->subscribers; + } + + /** + * {@inheritdoc} + */ + public function count() { + return $this->subscribers->count(); + } +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php new file mode 100644 index 0000000..dd06ada --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/TopicManager.php @@ -0,0 +1,125 @@ +<?php +namespace Ratchet\Wamp; +use Ratchet\ConnectionInterface; +use Ratchet\WebSocket\WsServerInterface; + +class TopicManager implements WsServerInterface, WampServerInterface { + /** + * @var WampServerInterface + */ + protected $app; + + /** + * @var array + */ + protected $topicLookup = array(); + + public function __construct(WampServerInterface $app) { + $this->app = $app; + } + + /** + * {@inheritdoc} + */ + public function onOpen(ConnectionInterface $conn) { + $conn->WAMP->subscriptions = new \SplObjectStorage; + $this->app->onOpen($conn); + } + + /** + * {@inheritdoc} + */ + public function onCall(ConnectionInterface $conn, $id, $topic, array $params) { + $this->app->onCall($conn, $id, $this->getTopic($topic), $params); + } + + /** + * {@inheritdoc} + */ + public function onSubscribe(ConnectionInterface $conn, $topic) { + $topicObj = $this->getTopic($topic); + + if ($conn->WAMP->subscriptions->contains($topicObj)) { + return; + } + + $this->topicLookup[$topic]->add($conn); + $conn->WAMP->subscriptions->attach($topicObj); + $this->app->onSubscribe($conn, $topicObj); + } + + /** + * {@inheritdoc} + */ + public function onUnsubscribe(ConnectionInterface $conn, $topic) { + $topicObj = $this->getTopic($topic); + + if (!$conn->WAMP->subscriptions->contains($topicObj)) { + return; + } + + $this->cleanTopic($topicObj, $conn); + + $this->app->onUnsubscribe($conn, $topicObj); + } + + /** + * {@inheritdoc} + */ + public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) { + $this->app->onPublish($conn, $this->getTopic($topic), $event, $exclude, $eligible); + } + + /** + * {@inheritdoc} + */ + public function onClose(ConnectionInterface $conn) { + $this->app->onClose($conn); + + foreach ($this->topicLookup as $topic) { + $this->cleanTopic($topic, $conn); + } + } + + /** + * {@inheritdoc} + */ + public function onError(ConnectionInterface $conn, \Exception $e) { + $this->app->onError($conn, $e); + } + + /** + * {@inheritdoc} + */ + public function getSubProtocols() { + if ($this->app instanceof WsServerInterface) { + return $this->app->getSubProtocols(); + } + + return array(); + } + + /** + * @param string + * @return Topic + */ + protected function getTopic($topic) { + if (!array_key_exists($topic, $this->topicLookup)) { + $this->topicLookup[$topic] = new Topic($topic); + } + + return $this->topicLookup[$topic]; + } + + protected function cleanTopic(Topic $topic, ConnectionInterface $conn) { + if ($conn->WAMP->subscriptions->contains($topic)) { + $conn->WAMP->subscriptions->detach($topic); + } + + $this->topicLookup[$topic->getId()]->remove($conn); + + if (0 === $topic->count()) { + unset($this->topicLookup[$topic->getId()]); + } + } +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php new file mode 100644 index 0000000..dda1e4e --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampConnection.php @@ -0,0 +1,115 @@ +<?php +namespace Ratchet\Wamp; +use Ratchet\ConnectionInterface; +use Ratchet\AbstractConnectionDecorator; +use Ratchet\Wamp\ServerProtocol as WAMP; + +/** + * A ConnectionInterface object wrapper that is passed to your WAMP application + * representing a client. Methods on this Connection are therefore different. + * @property \stdClass $WAMP + */ +class WampConnection extends AbstractConnectionDecorator { + /** + * {@inheritdoc} + */ + public function __construct(ConnectionInterface $conn) { + parent::__construct($conn); + + $this->WAMP = new \StdClass; + $this->WAMP->sessionId = str_replace('.', '', uniqid(mt_rand(), true)); + $this->WAMP->prefixes = array(); + + $this->send(json_encode(array(WAMP::MSG_WELCOME, $this->WAMP->sessionId, 1, \Ratchet\VERSION))); + } + + /** + * Successfully respond to a call made by the client + * @param string $id The unique ID given by the client to respond to + * @param array $data an object or array + * @return WampConnection + */ + public function callResult($id, $data = array()) { + return $this->send(json_encode(array(WAMP::MSG_CALL_RESULT, $id, $data))); + } + + /** + * Respond with an error to a client call + * @param string $id The unique ID given by the client to respond to + * @param string $errorUri The URI given to identify the specific error + * @param string $desc A developer-oriented description of the error + * @param string $details An optional human readable detail message to send back + * @return WampConnection + */ + public function callError($id, $errorUri, $desc = '', $details = null) { + if ($errorUri instanceof Topic) { + $errorUri = (string)$errorUri; + } + + $data = array(WAMP::MSG_CALL_ERROR, $id, $errorUri, $desc); + + if (null !== $details) { + $data[] = $details; + } + + return $this->send(json_encode($data)); + } + + /** + * @param string $topic The topic to broadcast to + * @param mixed $msg Data to send with the event. Anything that is json'able + * @return WampConnection + */ + public function event($topic, $msg) { + return $this->send(json_encode(array(WAMP::MSG_EVENT, (string)$topic, $msg))); + } + + /** + * @param string $curie + * @param string $uri + * @return WampConnection + */ + public function prefix($curie, $uri) { + $this->WAMP->prefixes[$curie] = (string)$uri; + + return $this->send(json_encode(array(WAMP::MSG_PREFIX, $curie, (string)$uri))); + } + + /** + * Get the full request URI from the connection object if a prefix has been established for it + * @param string $uri + * @return string + */ + public function getUri($uri) { + $curieSeperator = ':'; + + if (preg_match('/http(s*)\:\/\//', $uri) == false) { + if (strpos($uri, $curieSeperator) !== false) { + list($prefix, $action) = explode($curieSeperator, $uri); + + if(isset($this->WAMP->prefixes[$prefix]) === true){ + return $this->WAMP->prefixes[$prefix] . '#' . $action; + } + } + } + + return $uri; + } + + /** + * @internal + */ + public function send($data) { + $this->getConnection()->send($data); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function close($opt = null) { + $this->getConnection()->close($opt); + } + +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php new file mode 100644 index 0000000..5d710aa --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServer.php @@ -0,0 +1,67 @@ +<?php +namespace Ratchet\Wamp; +use Ratchet\MessageComponentInterface; +use Ratchet\WebSocket\WsServerInterface; +use Ratchet\ConnectionInterface; + +/** + * Enable support for the official WAMP sub-protocol in your application + * WAMP allows for Pub/Sub and RPC + * @link http://wamp.ws The WAMP specification + * @link https://github.com/oberstet/autobahn-js Souce for client side library + * @link http://autobahn.s3.amazonaws.com/js/autobahn.min.js Minified client side library + */ +class WampServer implements MessageComponentInterface, WsServerInterface { + /** + * @var ServerProtocol + */ + protected $wampProtocol; + + /** + * This class just makes it 1 step easier to use Topic objects in WAMP + * If you're looking at the source code, look in the __construct of this + * class and use that to make your application instead of using this + */ + public function __construct(WampServerInterface $app) { + $this->wampProtocol = new ServerProtocol(new TopicManager($app)); + } + + /** + * {@inheritdoc} + */ + public function onOpen(ConnectionInterface $conn) { + $this->wampProtocol->onOpen($conn); + } + + /** + * {@inheritdoc} + */ + public function onMessage(ConnectionInterface $conn, $msg) { + try { + $this->wampProtocol->onMessage($conn, $msg); + } catch (Exception $we) { + $conn->close(1007); + } + } + + /** + * {@inheritdoc} + */ + public function onClose(ConnectionInterface $conn) { + $this->wampProtocol->onClose($conn); + } + + /** + * {@inheritdoc} + */ + public function onError(ConnectionInterface $conn, \Exception $e) { + $this->wampProtocol->onError($conn, $e); + } + + /** + * {@inheritdoc} + */ + public function getSubProtocols() { + return $this->wampProtocol->getSubProtocols(); + } +} diff --git a/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php new file mode 100644 index 0000000..15c521d --- /dev/null +++ b/assets/php/vendor/cboden/ratchet/src/Ratchet/Wamp/WampServerInterface.php @@ -0,0 +1,43 @@ +<?php +namespace Ratchet\Wamp; +use Ratchet\ComponentInterface; +use Ratchet\ConnectionInterface; + +/** + * An extension of Ratchet\ComponentInterface to server a WAMP application + * onMessage is replaced by various types of messages for this protocol (pub/sub or rpc) + */ +interface WampServerInterface extends ComponentInterface { + /** + * An RPC call has been received + * @param \Ratchet\ConnectionInterface $conn + * @param string $id The unique ID of the RPC, required to respond to + * @param string|Topic $topic The topic to execute the call against + * @param array $params Call parameters received from the client + */ + function onCall(ConnectionInterface $conn, $id, $topic, array $params); + + /** + * A request to subscribe to a topic has been made + * @param \Ratchet\ConnectionInterface $conn + * @param string|Topic $topic The topic to subscribe to + */ + function onSubscribe(ConnectionInterface $conn, $topic); + + /** + * A request to unsubscribe from a topic has been made + * @param \Ratchet\ConnectionInterface $conn + * @param string|Topic $topic The topic to unsubscribe from + */ + function onUnSubscribe(ConnectionInterface $conn, $topic); + + /** + * A client is attempting to publish content to a subscribed connections on a URI + * @param \Ratchet\ConnectionInterface $conn + * @param string|Topic $topic The topic the user has attempted to publish to + * @param string $event Payload of the publish + * @param array $exclude A list of session IDs the message should be excluded from (blacklist) + * @param array $eligible A list of session Ids the message should be send to (whitelist) + */ + function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible); +} |