From cc507e821efcd108fb1d4d178f055e7f218d27b0 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Tue, 22 Nov 2011 11:33:41 -0500 Subject: [PATCH] Documentation A bunch of API updates Added read() to SocketInterface Return self for fluid interface in Server --- README.md | 2 +- .../Application/ApplicationInterface.php | 17 ++++++++++++----- lib/Ratchet/Application/Server/App.php | 13 +++++++++++-- lib/Ratchet/Application/WebSocket/App.php | 19 +++++++++++++++++++ .../WebSocket/Command/Action/Disconnect.php | 3 +++ .../WebSocket/Command/Action/Ping.php | 3 +++ .../WebSocket/Command/Action/Pong.php | 3 +++ .../Application/WebSocket/Util/HTTP.php | 1 + .../WebSocket/WebSocketAppInterface.php | 1 + lib/Ratchet/Socket.php | 8 ++++++++ lib/Ratchet/SocketInterface.php | 15 +++++++++++++++ 11 files changed, 77 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f9d0e8e..a056e9c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Re-use your application without changing any of its code just by wrapping it in ##WebSockets * Supports the HyBi-10 and Hixie76 protocol versions (at the same time) -* Tested on Chrome 14, Firefox 7, Safari 5, iOS 4.2 +* Tested on Chrome 13 - 15, Firefox 6 - 8, Safari 5, iOS 4.2, iOS 5 ##Requirements diff --git a/lib/Ratchet/Application/ApplicationInterface.php b/lib/Ratchet/Application/ApplicationInterface.php index 00da591..4c0c919 100644 --- a/lib/Ratchet/Application/ApplicationInterface.php +++ b/lib/Ratchet/Application/ApplicationInterface.php @@ -2,42 +2,49 @@ namespace Ratchet\Application; use Ratchet\Resource\Connection; +/** + * This is the interface to build a Ratchet application with + * It impelemtns the decorator and command pattern to build an application stack + */ interface ApplicationInterface { /** * Decorator pattern * @param Ratchet\ApplicationInterface Application to wrap in protocol - * @throws UnexpectedValueException */ public function __construct(ApplicationInterface $app = null); /** * When a new connection is opened it will be passed to this method - * @param SocketInterface The socket/connection that just connected to your application + * @param Ratchet\Resource\Connection The socket/connection that just connected to your application * @return Ratchet\Resource\Command\CommandInterface|null + * @throws Exception */ function onOpen(Connection $conn); /** * Triggered when a client sends data through the socket - * @param SocketInterface The socket/connection that sent the message to your application + * @param Ratchet\Resource\Connection The socket/connection that sent the message to your application * @param string The message received * @return Ratchet\Resource\Command\CommandInterface|null + * @throws Exception */ function onMessage(Connection $from, $msg); /** * This is called before or after a socket is closed (depends on how it's closed). SendMessage to $conn will not result in an error if it has already been closed. - * @param SocketInterface The socket/connection that is closing/closed + * @param Ratchet\Resource\Connection The socket/connection that is closing/closed * @return Ratchet\Resource\Command\CommandInterface|null + * @throws Exception */ function onClose(Connection $conn); /** * If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown, * the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method - * @param SocketInterface + * @param Ratchet\Resource\Connection * @param \Exception * @return Ratchet\Resource\Command\CommandInterface|null + * @throws Exception */ function onError(Connection $conn, \Exception $e); } \ No newline at end of file diff --git a/lib/Ratchet/Application/Server/App.php b/lib/Ratchet/Application/Server/App.php index cb80669..bd7188c 100644 --- a/lib/Ratchet/Application/Server/App.php +++ b/lib/Ratchet/Application/Server/App.php @@ -21,8 +21,8 @@ class App implements ApplicationInterface { protected $_connections = array(); /** + * The decorated application to send events to * @var Ratchet\Application\ApplicationInterface - * Maybe temporary? */ protected $_app; @@ -41,18 +41,27 @@ class App implements ApplicationInterface { $this->_app = $application; } + /** + * Set the incoming buffer size in bytes + * @param int + * @return App + * @throws InvalidArgumentException If the parameter is less than 1 + */ public function setBufferSize($recv_bytes) { if ((int)$recv_bytes < 1) { throw new \InvalidArgumentException('Invalid number of bytes set, must be more than 0'); } $this->_buffer_size = (int)$recv_bytes; + + return $this; } /* + * Run the server infinitely * @param Ratchet\SocketInterface * @param mixed The address to listen for incoming connections on. "0.0.0.0" to listen from anywhere - * @param int The port to listen to connections on + * @param int The port to listen to connections on (make sure to run as root if < 1000) * @throws Ratchet\Exception * @todo Validate address. Use socket_get_option, if AF_INET must be IP, if AF_UNIX must be path * @todo Consider making the 4kb listener changable diff --git a/lib/Ratchet/Application/WebSocket/App.php b/lib/Ratchet/Application/WebSocket/App.php index 29eb303..7a12c55 100644 --- a/lib/Ratchet/Application/WebSocket/App.php +++ b/lib/Ratchet/Application/WebSocket/App.php @@ -15,6 +15,7 @@ use Ratchet\Application\WebSocket\Util\HTTP; * @todo Make sure this works both ways (client/server) as stack needs to exist on client for framing * @todo Learn about closing the socket. A message has to be sent prior to closing - does the message get sent onClose event or CloseConnection command? * @todo Consider chaning this class to a State Pattern. If a WS App interface is passed use different state for additional methods used + * @todo I think I need to overhaul the architecture of this...more onus should be on the VersionInterfaces in case of changes...let them handle more decisions, not just parsing */ class App implements ApplicationInterface, ConfiguratorInterface { /** @@ -24,6 +25,7 @@ class App implements ApplicationInterface, ConfiguratorInterface { protected $_app; /** + * Creates commands/composites instead of calling several classes manually * @var Ratchet\Resource\Command\Factory */ protected $_factory; @@ -47,6 +49,8 @@ class App implements ApplicationInterface, ConfiguratorInterface { } /** + * Return the desired socket configuration if hosting a WebSocket server + * This method may be removed * @return array */ public static function getDefaultConfig() { @@ -66,6 +70,10 @@ class App implements ApplicationInterface, ConfiguratorInterface { $conn->WebSocket->headers = ''; } + /** + * Do handshake, frame/unframe messages coming/going in stack + * @todo This needs some major refactoring + */ public function onMessage(Connection $from, $msg) { if (true !== $from->WebSocket->handshake) { if (!isset($from->WebSocket->version)) { @@ -136,12 +144,17 @@ class App implements ApplicationInterface, ConfiguratorInterface { return $this->prepareCommand($this->_app->onClose($conn)); } + /** + * @todo Shouldn't I be using prepareCommand() on the return? look into this + */ public function onError(Connection $conn, \Exception $e) { return $this->_app->onError($conn, $e); } /** + * Incomplete, WebSocket protocol allows client to ask to use a sub-protocol, I'm thinking/wanting to somehow implement this in an application decorated class * @param string + * @todo Implement or delete... */ public function setSubProtocol($name) { } @@ -153,6 +166,10 @@ class App implements ApplicationInterface, ConfiguratorInterface { */ protected function prepareCommand(CommandInterface $command = null) { if ($command instanceof SendMessage) { + if (!isset($command->getConnection()->WebSocket->version)) { // Client could close connection before handshake complete or invalid handshake + return $command; + } + $version = $command->getConnection()->WebSocket->version; return $command->setMessage($version->frame($command->getMessage())); } @@ -167,6 +184,7 @@ class App implements ApplicationInterface, ConfiguratorInterface { } /** + * Detect the WebSocket protocol version a client is using based on the HTTP header request * @param array of HTTP headers * @return Version\VersionInterface * @throws UnderFlowException If we think the entire header message hasn't been buffered yet @@ -192,6 +210,7 @@ class App implements ApplicationInterface, ConfiguratorInterface { } /** + * Create and return the instance of a version class * @return Version\VersionInterface */ protected function versionFactory($version) { diff --git a/lib/Ratchet/Application/WebSocket/Command/Action/Disconnect.php b/lib/Ratchet/Application/WebSocket/Command/Action/Disconnect.php index e8035f2..f2e6a8d 100644 --- a/lib/Ratchet/Application/WebSocket/Command/Action/Disconnect.php +++ b/lib/Ratchet/Application/WebSocket/Command/Action/Disconnect.php @@ -3,6 +3,9 @@ namespace Ratchet\Application\WebSocket\Command\Action; use Ratchet\Resource\Command\Action\SendMessage; use Ratchet\Application\ApplicationInterface; +/** + * Not yet implemented/completed + */ class Disconnect extends SendMessage { protected $_code = 1000; diff --git a/lib/Ratchet/Application/WebSocket/Command/Action/Ping.php b/lib/Ratchet/Application/WebSocket/Command/Action/Ping.php index 5fc0737..1644bf3 100644 --- a/lib/Ratchet/Application/WebSocket/Command/Action/Ping.php +++ b/lib/Ratchet/Application/WebSocket/Command/Action/Ping.php @@ -3,6 +3,9 @@ namespace Ratchet\Application\WebSocket\Command\Action; use Ratchet\Resource\Command\ActionTemplate; use Ratchet\Application\ApplicationInterface; +/** + * Not yet implemented/completed + */ class Ping extends ActionTemplate { public function execute(ApplicationInterface $scope = null) { } diff --git a/lib/Ratchet/Application/WebSocket/Command/Action/Pong.php b/lib/Ratchet/Application/WebSocket/Command/Action/Pong.php index e010fc6..fe390e9 100644 --- a/lib/Ratchet/Application/WebSocket/Command/Action/Pong.php +++ b/lib/Ratchet/Application/WebSocket/Command/Action/Pong.php @@ -3,6 +3,9 @@ namespace Ratchet\Application\WebSocket\Command\Action; use Ratchet\Resource\Command\ActionTemplate; use Ratchet\Application\ApplicationInterface; +/** + * Not yet implemented/completed + */ class Pong extends ActionTemplate { public function execute(ApplicationInterface $scope = null) { } diff --git a/lib/Ratchet/Application/WebSocket/Util/HTTP.php b/lib/Ratchet/Application/WebSocket/Util/HTTP.php index fefb70d..57dcc55 100644 --- a/lib/Ratchet/Application/WebSocket/Util/HTTP.php +++ b/lib/Ratchet/Application/WebSocket/Util/HTTP.php @@ -3,6 +3,7 @@ namespace Ratchet\Application\WebSocket\Util; /** * A helper class for handling HTTP requests + * @todo Needs re-write...http_parse_headers is a PECL extension that changes the case to unexpected values */ class HTTP { /** diff --git a/lib/Ratchet/Application/WebSocket/WebSocketAppInterface.php b/lib/Ratchet/Application/WebSocket/WebSocketAppInterface.php index 4b85a49..f78ca6c 100644 --- a/lib/Ratchet/Application/WebSocket/WebSocketAppInterface.php +++ b/lib/Ratchet/Application/WebSocket/WebSocketAppInterface.php @@ -9,6 +9,7 @@ use Ratchet\Application\ApplicationInterface; */ interface WebSocketAppInterface extends ApplicationInterface { /** + * Currently instead of this, I'm setting header in the Connection object passed around...not sure which I like more * @param string */ function setHeaders($headers); diff --git a/lib/Ratchet/Socket.php b/lib/Ratchet/Socket.php index ba511b3..20969b0 100644 --- a/lib/Ratchet/Socket.php +++ b/lib/Ratchet/Socket.php @@ -116,6 +116,14 @@ class Socket implements SocketInterface { return $this; } + public function read($length, $type = PHP_BINARY_READ) { + if (false === ($res = @socket_read($this->getResource(), $length, $type))) { + throw new Exception($this); + } + + return $res; + } + /** * @see http://ca3.php.net/manual/en/function.socket-recv.php * @param string Variable to write data to diff --git a/lib/Ratchet/SocketInterface.php b/lib/Ratchet/SocketInterface.php index 3f0a1e1..8e54361 100644 --- a/lib/Ratchet/SocketInterface.php +++ b/lib/Ratchet/SocketInterface.php @@ -34,6 +34,7 @@ interface SocketInterface { // function accept(); /** + * Bind the socket instance to an address/port * @param string * @param int * @return SocketInterface @@ -47,6 +48,7 @@ interface SocketInterface { function close(); /** + * Initiates a connection to a socket * @param string * @param int * @return SocketInterface @@ -70,12 +72,22 @@ interface SocketInterface { function get_option($level, $optname); /** + * Listen for incoming connections on this socket * @param int * @return SocketInterface * @throws Exception */ function listen($backlog = 0); + /** + * Read a maximum of length bytes from a socket + * @param int Number of bytes to read + * @param int Flags + * @return string Data read from the socket + * @throws Exception + */ + function read($length, $type = PHP_BINARY_READ); + /** * Called when the client sends data to the server through the socket * @param string Variable to write data to @@ -91,12 +103,15 @@ interface SocketInterface { // function select(array &$read, array &$write, array &$except, $tv_sec, $tv_usec = 0); /** + * Sets the blocking mode on the socket resource + * Wen an operation (receive, send, connect, accept, etc) is performed after set_block() the script will pause execution until the operation is completed * @return SocketInterface * @throws Exception */ function set_block(); /** + * Sets nonblocking mode for socket resource * @return SocketInterface * @throws Exception */