Documentation

A bunch of API updates
Added read() to SocketInterface
Return self for fluid interface in Server
This commit is contained in:
Chris Boden 2011-11-22 11:33:41 -05:00
parent c5597edd55
commit cc507e821e
11 changed files with 77 additions and 8 deletions

View File

@ -7,7 +7,7 @@ Re-use your application without changing any of its code just by wrapping it in
##WebSockets ##WebSockets
* Supports the HyBi-10 and Hixie76 protocol versions (at the same time) * 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 ##Requirements

View File

@ -2,42 +2,49 @@
namespace Ratchet\Application; namespace Ratchet\Application;
use Ratchet\Resource\Connection; 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 { interface ApplicationInterface {
/** /**
* Decorator pattern * Decorator pattern
* @param Ratchet\ApplicationInterface Application to wrap in protocol * @param Ratchet\ApplicationInterface Application to wrap in protocol
* @throws UnexpectedValueException
*/ */
public function __construct(ApplicationInterface $app = null); public function __construct(ApplicationInterface $app = null);
/** /**
* When a new connection is opened it will be passed to this method * 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 * @return Ratchet\Resource\Command\CommandInterface|null
* @throws Exception
*/ */
function onOpen(Connection $conn); function onOpen(Connection $conn);
/** /**
* Triggered when a client sends data through the socket * 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 * @param string The message received
* @return Ratchet\Resource\Command\CommandInterface|null * @return Ratchet\Resource\Command\CommandInterface|null
* @throws Exception
*/ */
function onMessage(Connection $from, $msg); 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. * 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 * @return Ratchet\Resource\Command\CommandInterface|null
* @throws Exception
*/ */
function onClose(Connection $conn); function onClose(Connection $conn);
/** /**
* If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown, * 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 * 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 * @param \Exception
* @return Ratchet\Resource\Command\CommandInterface|null * @return Ratchet\Resource\Command\CommandInterface|null
* @throws Exception
*/ */
function onError(Connection $conn, \Exception $e); function onError(Connection $conn, \Exception $e);
} }

View File

@ -21,8 +21,8 @@ class App implements ApplicationInterface {
protected $_connections = array(); protected $_connections = array();
/** /**
* The decorated application to send events to
* @var Ratchet\Application\ApplicationInterface * @var Ratchet\Application\ApplicationInterface
* Maybe temporary?
*/ */
protected $_app; protected $_app;
@ -41,18 +41,27 @@ class App implements ApplicationInterface {
$this->_app = $application; $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) { public function setBufferSize($recv_bytes) {
if ((int)$recv_bytes < 1) { if ((int)$recv_bytes < 1) {
throw new \InvalidArgumentException('Invalid number of bytes set, must be more than 0'); throw new \InvalidArgumentException('Invalid number of bytes set, must be more than 0');
} }
$this->_buffer_size = (int)$recv_bytes; $this->_buffer_size = (int)$recv_bytes;
return $this;
} }
/* /*
* Run the server infinitely
* @param Ratchet\SocketInterface * @param Ratchet\SocketInterface
* @param mixed The address to listen for incoming connections on. "0.0.0.0" to listen from anywhere * @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 * @throws Ratchet\Exception
* @todo Validate address. Use socket_get_option, if AF_INET must be IP, if AF_UNIX must be path * @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 * @todo Consider making the 4kb listener changable

View File

@ -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 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 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 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 { class App implements ApplicationInterface, ConfiguratorInterface {
/** /**
@ -24,6 +25,7 @@ class App implements ApplicationInterface, ConfiguratorInterface {
protected $_app; protected $_app;
/** /**
* Creates commands/composites instead of calling several classes manually
* @var Ratchet\Resource\Command\Factory * @var Ratchet\Resource\Command\Factory
*/ */
protected $_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 * @return array
*/ */
public static function getDefaultConfig() { public static function getDefaultConfig() {
@ -66,6 +70,10 @@ class App implements ApplicationInterface, ConfiguratorInterface {
$conn->WebSocket->headers = ''; $conn->WebSocket->headers = '';
} }
/**
* Do handshake, frame/unframe messages coming/going in stack
* @todo This needs some major refactoring
*/
public function onMessage(Connection $from, $msg) { public function onMessage(Connection $from, $msg) {
if (true !== $from->WebSocket->handshake) { if (true !== $from->WebSocket->handshake) {
if (!isset($from->WebSocket->version)) { if (!isset($from->WebSocket->version)) {
@ -136,12 +144,17 @@ class App implements ApplicationInterface, ConfiguratorInterface {
return $this->prepareCommand($this->_app->onClose($conn)); 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) { public function onError(Connection $conn, \Exception $e) {
return $this->_app->onError($conn, $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 * @param string
* @todo Implement or delete...
*/ */
public function setSubProtocol($name) { public function setSubProtocol($name) {
} }
@ -153,6 +166,10 @@ class App implements ApplicationInterface, ConfiguratorInterface {
*/ */
protected function prepareCommand(CommandInterface $command = null) { protected function prepareCommand(CommandInterface $command = null) {
if ($command instanceof SendMessage) { 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; $version = $command->getConnection()->WebSocket->version;
return $command->setMessage($version->frame($command->getMessage())); 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 * @param array of HTTP headers
* @return Version\VersionInterface * @return Version\VersionInterface
* @throws UnderFlowException If we think the entire header message hasn't been buffered yet * @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 * @return Version\VersionInterface
*/ */
protected function versionFactory($version) { protected function versionFactory($version) {

View File

@ -3,6 +3,9 @@ namespace Ratchet\Application\WebSocket\Command\Action;
use Ratchet\Resource\Command\Action\SendMessage; use Ratchet\Resource\Command\Action\SendMessage;
use Ratchet\Application\ApplicationInterface; use Ratchet\Application\ApplicationInterface;
/**
* Not yet implemented/completed
*/
class Disconnect extends SendMessage { class Disconnect extends SendMessage {
protected $_code = 1000; protected $_code = 1000;

View File

@ -3,6 +3,9 @@ namespace Ratchet\Application\WebSocket\Command\Action;
use Ratchet\Resource\Command\ActionTemplate; use Ratchet\Resource\Command\ActionTemplate;
use Ratchet\Application\ApplicationInterface; use Ratchet\Application\ApplicationInterface;
/**
* Not yet implemented/completed
*/
class Ping extends ActionTemplate { class Ping extends ActionTemplate {
public function execute(ApplicationInterface $scope = null) { public function execute(ApplicationInterface $scope = null) {
} }

View File

@ -3,6 +3,9 @@ namespace Ratchet\Application\WebSocket\Command\Action;
use Ratchet\Resource\Command\ActionTemplate; use Ratchet\Resource\Command\ActionTemplate;
use Ratchet\Application\ApplicationInterface; use Ratchet\Application\ApplicationInterface;
/**
* Not yet implemented/completed
*/
class Pong extends ActionTemplate { class Pong extends ActionTemplate {
public function execute(ApplicationInterface $scope = null) { public function execute(ApplicationInterface $scope = null) {
} }

View File

@ -3,6 +3,7 @@ namespace Ratchet\Application\WebSocket\Util;
/** /**
* A helper class for handling HTTP requests * 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 { class HTTP {
/** /**

View File

@ -9,6 +9,7 @@ use Ratchet\Application\ApplicationInterface;
*/ */
interface WebSocketAppInterface extends 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 * @param string
*/ */
function setHeaders($headers); function setHeaders($headers);

View File

@ -116,6 +116,14 @@ class Socket implements SocketInterface {
return $this; 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 * @see http://ca3.php.net/manual/en/function.socket-recv.php
* @param string Variable to write data to * @param string Variable to write data to

View File

@ -34,6 +34,7 @@ interface SocketInterface {
// function accept(); // function accept();
/** /**
* Bind the socket instance to an address/port
* @param string * @param string
* @param int * @param int
* @return SocketInterface * @return SocketInterface
@ -47,6 +48,7 @@ interface SocketInterface {
function close(); function close();
/** /**
* Initiates a connection to a socket
* @param string * @param string
* @param int * @param int
* @return SocketInterface * @return SocketInterface
@ -70,12 +72,22 @@ interface SocketInterface {
function get_option($level, $optname); function get_option($level, $optname);
/** /**
* Listen for incoming connections on this socket
* @param int * @param int
* @return SocketInterface * @return SocketInterface
* @throws Exception * @throws Exception
*/ */
function listen($backlog = 0); 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 * Called when the client sends data to the server through the socket
* @param string Variable to write data to * @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); // 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 * @return SocketInterface
* @throws Exception * @throws Exception
*/ */
function set_block(); function set_block();
/** /**
* Sets nonblocking mode for socket resource
* @return SocketInterface * @return SocketInterface
* @throws Exception * @throws Exception
*/ */