diff --git a/README.md b/README.md index 39fd4b2..523457b 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[![Build Status](https://secure.travis-ci.org/cboden/Ratchet.png)](http://travis-ci.org/cboden/Ratchet) +[![Build Status](https://secure.travis-ci.org/cboden/Ratchet.png?branch=master)](http://travis-ci.org/cboden/Ratchet) #Ratchet A PHP 5.3 (PSR-0 compliant) component library for serving sockets and building socket based applications. Build up your application through simple interfaces using the decorator and command patterns. Re-use your application without changing any of its code just by combining different components. -Ratchet's primary intention is to be used as a WebSocket server (and a client in 0.6). +Ratchet's primary intention is to be used as a WebSocket server. ##WebSockets @@ -14,21 +14,21 @@ Ratchet's primary intention is to be used as a WebSocket server (and a client in ##Requirements -Shell access is required and a dedicated (virtual) machine with root access is recommended. +Shell access is required and a dedicated machine with root access is recommended. To avoid proxy/firewall blockage it's recommended WebSockets are run on port 80, which requires root access. Note that you can not run two applications (Apache and Ratchet) on the same port, thus the requirement for a separate machine (for now). Cookies from your domain will be passed to the socket server, allowing you to identify users. Accessing your website's session data in Ratchet is a [feature in the works](https://github.com/cboden/Ratchet/tree/symfony/sessions). -See https://github.com/cboden/socket-demos for some out-of-the-box working demos using Ratchet. +See https://github.com/cboden/Ratchet-examples for some out-of-the-box working demos using Ratchet. ###Future considerations Ideally, soon, web servers will start supporting WebSockets to some capacity and PHP will no longer need to run its self from the command line. In theory, the server (like Nginx) would recognize the HTTP handshake request to upgrade the protocol to WebSockets and run/pass data through to a user -configured PHP file. When this happens, you can keep your script the same, just remove the Server Application wrapper and maybe eventually the -WebSocket Application wrapper if the servers recognize the protocol message framing. +configured PHP file. When this happens, you can keep your script the same, just remove the IOServerComponent wrapper and maybe eventually the +WebSocketComponent wrapper if the servers recognize the protocol message framing. --- @@ -39,9 +39,8 @@ WebSocket Application wrapper if the servers recognize the protocol message fram namespace MyApps; use Ratchet\Component\MessageComponentInterface; use Ratchet\Resource\ConnectionInterface; -use Ratchet\Resource\Socket\BSDSocket as Socket; -use Ratchet\Component\Server\IOServerComponent as Server; -use Ratchet\Component\WebSocket\WebSocketComponent as WebSocket; +use Ratchet\Component\Server\IOServerComponent; +use Ratchet\Component\WebSocket\WebSocketComponent; use Ratchet\Resource\Command\Composite as Cmds; use Ratchet\Resource\Command\Action\SendMessage; use Ratchet\Resource\Command\Action\CloseConnection; @@ -84,9 +83,10 @@ class Chat implements MessageComponentInterface { return new CloseConnection($conn); } } + // Run the server application through the WebSocket protocol - $server = new Server(new WebSocket(new Chat)); - $server->run(new Socket, '0.0.0.0', 80); + $server = new IOServerComponent(new WebSocketComponent(new Chat)); + $server->run(80); ``` # php chat.php \ No newline at end of file diff --git a/composer.json b/composer.json index e54a528..0897e66 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,8 @@ "name": "cboden/Ratchet" , "type": "library" , "description": "PHP WebSocket server component library" - , "keywords": ["WebSocket"] + , "keywords": ["WebSockets", "Server", "Ratchet", "Sockets"] + , "website": "http://socketo.me" , "repository": "https://github.com/cboden/Ratchet" , "license": "MIT" , "authors": [ @@ -18,28 +19,8 @@ , "Ratchet": "src" } } - , "repositories": { - "guzzle": { - "type": "package" - , "package": { - "name": "guzzle" - , "type": "library" - , "version": "2.0.2" - , "autoload": { - "psr-0": { - "Guzzle": "src" - } - } - , "source": { - "url": "https://github.com/guzzle/guzzle.git" - , "type": "git" - , "reference": "ac64abc2c05b921efc4623379c1674a282475ae5" - } - } - } - } , "require": { "php": ">=5.3.2" - , "guzzle": "2.0.2" + , "guzzle/guzzle": "v2.0.2" } } \ No newline at end of file diff --git a/composer.lock b/composer.lock index c3e0e39..4018db3 100644 --- a/composer.lock +++ b/composer.lock @@ -1,14 +1,24 @@ { - "hash": "be8f67a3964cca0e4ffe4b98a7527daa", + "hash": "bd52a853cdf4e34ae75e805f32ed97ae", "packages": [ { - "package": "guzzle", - "version": "2.0.2" + "package": "doctrine/common", + "version": "2.2.x-dev", + "source-reference": "1e0aa60d109c630d19543d999f12e2852ef8f932" }, { - "package": "symfony/http-foundation", + "package": "guzzle/guzzle", + "version": "v2.0.2" + }, + { + "package": "symfony/event-dispatcher", "version": "dev-master", - "source-reference": "b9aceabb83f3d03fe451cdd867d987e863e7a25e" + "source-reference": "b98d68d3b8513c62d35504570f09e9d3dc33d083" + }, + { + "package": "symfony/validator", + "version": "dev-master", + "source-reference": "53ec97264f909d29ae01665e8345f8fb763b94f3" } ], "packages-dev": null, diff --git a/src/Ratchet/Component/Client/App.php b/src/Ratchet/Component/Client/App.php deleted file mode 100644 index e69de29..0000000 diff --git a/src/Ratchet/Component/Server/IOServerComponent.php b/src/Ratchet/Component/Server/IOServerComponent.php index d292d57..15bb5f5 100644 --- a/src/Ratchet/Component/Server/IOServerComponent.php +++ b/src/Ratchet/Component/Server/IOServerComponent.php @@ -2,6 +2,7 @@ namespace Ratchet\Component\Server; use Ratchet\Component\MessageComponentInterface; use Ratchet\Resource\Socket\SocketInterface; +use Ratchet\Resource\Socket\BSDSocket; use Ratchet\Resource\ConnectionInterface; use Ratchet\Resource\Connection; use Ratchet\Resource\Command\CommandInterface; @@ -63,12 +64,17 @@ class IOServerComponent implements MessageComponentInterface { /* * Run the server infinitely - * @param Ratchet\Resource\Socket\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 (make sure to run as root if < 1000) + * @param mixed The address to listen for incoming connections on. "0.0.0.0" to listen from anywhere + * @param Ratchet\Resource\Socket\SocketInterface * @throws Ratchet\Exception */ - public function run(SocketInterface $host, $address = '127.0.0.1', $port = 1025) { + public function run($port, $address = '0.0.0.0', SocketInterface $host = null) { + if (null === $host) { + $host = new BSDSocket; + $host->set_option(SOL_SOCKET, SO_REUSEADDR, 1); + } + $this->_connections[$host->getResource()] = new Connection($host); $this->_resources[] = $host->getResource(); @@ -148,13 +154,16 @@ class IOServerComponent implements MessageComponentInterface { } /** - * @{inheritdoc} + * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { $new_socket = clone $conn->getSocket(); $new_socket->set_nonblock(); $new_connection = new Connection($new_socket); + $new_connection->remoteAddress = $new_socket->getRemoteAddress(); + $new_connection->resourceId = (int)substr((string)$new_socket->getResource(), strrpos((string)$new_socket->getResource(), '#') + 1); + $this->_resources[] = $new_connection->getSocket()->getResource(); $this->_connections[$new_connection->getSocket()->getResource()] = $new_connection; @@ -162,14 +171,14 @@ class IOServerComponent implements MessageComponentInterface { } /** - * @{inheritdoc} + * {@inheritdoc} */ public function onMessage(ConnectionInterface $from, $msg) { return $this->_decorating->onMessage($from, $msg); } /** - * @{inheritdoc} + * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { $resource = $conn->getSocket()->getResource(); @@ -182,7 +191,7 @@ class IOServerComponent implements MessageComponentInterface { } /** - * @{inheritdoc} + * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { return $this->_decorating->onError($conn, $e); diff --git a/src/Ratchet/Component/WebSocket/WebSocketComponent.php b/src/Ratchet/Component/WebSocket/WebSocketComponent.php index 454128d..a2267fd 100644 --- a/src/Ratchet/Component/WebSocket/WebSocketComponent.php +++ b/src/Ratchet/Component/WebSocket/WebSocketComponent.php @@ -52,7 +52,7 @@ class WebSocketComponent implements MessageComponentInterface { } /** - * @{inheritdoc} + * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { $conn->WebSocket = new \stdClass; diff --git a/src/Ratchet/Resource/Command/Action/Runtime.php b/src/Ratchet/Resource/Command/Action/Runtime.php index 4211054..17ccd17 100644 --- a/src/Ratchet/Resource/Command/Action/Runtime.php +++ b/src/Ratchet/Resource/Command/Action/Runtime.php @@ -21,7 +21,7 @@ class Runtime extends ActionTemplate { } /** - * @{inheritdoc} + * {@inheritdoc} */ public function execute(ComponentInterface $scope = null) { $cmd = $this->_command; diff --git a/src/Ratchet/Resource/Command/Action/SendMessage.php b/src/Ratchet/Resource/Command/Action/SendMessage.php index 8a9bc84..3eca5fe 100644 --- a/src/Ratchet/Resource/Command/Action/SendMessage.php +++ b/src/Ratchet/Resource/Command/Action/SendMessage.php @@ -30,7 +30,7 @@ class SendMessage extends ActionTemplate { } /** - * @{inheritdoc} + * {@inheritdoc} * @throws \UnexpectedValueException if a message was not set with setMessage() */ public function execute(ComponentInterface $scope = null) { diff --git a/src/Ratchet/Resource/Command/Composite.php b/src/Ratchet/Resource/Command/Composite.php index be44815..1a0f8d3 100644 --- a/src/Ratchet/Resource/Command/Composite.php +++ b/src/Ratchet/Resource/Command/Composite.php @@ -23,7 +23,7 @@ class Composite extends \SplQueue implements CommandInterface { } /** - * @{inheritdoc} + * {@inheritdoc} */ public function execute(ComponentInterface $scope = null) { $this->setIteratorMode(static::IT_MODE_DELETE); diff --git a/src/Ratchet/Resource/Connection.php b/src/Ratchet/Resource/Connection.php index 5d5e015..4f1485c 100644 --- a/src/Ratchet/Resource/Connection.php +++ b/src/Ratchet/Resource/Connection.php @@ -7,8 +7,6 @@ use Ratchet\Resource\Socket\SocketInterface; * This acts as a container to storm data (in memory) about the connection */ class Connection implements ConnectionInterface { - protected $_data = array(); - /** * @var Ratchet\Resource\Socket\SocketInterface */ @@ -18,13 +16,6 @@ class Connection implements ConnectionInterface { $this->_socket = $socket; } - /** - * @return int - */ - public function getID() { - return (int)(string)$this->_socket; - } - /** * This is here because I couldn't figure out a better/easier way to tie a connection and socket together for the server and commands * Anyway, if you're here, it's not recommended you use this/directly interact with the socket in your App... @@ -35,40 +26,4 @@ class Connection implements ConnectionInterface { public function getSocket() { return $this->_socket; } - - /** - * @{inheritdoc} - */ - public function __set($name, $value) { - $this->_data[$name] = $value; - } - - /** - * @{inheritdoc} - */ - public function __get($name) { - if (!$this->__isset($name)) { - throw new \InvalidArgumentException("Attribute '{$name}' not found in Connection {$this->getID()}"); - } - - if (is_callable($this->_data[$name])) { - return $this->_data[$name]($this); - } else { - return $this->_data[$name]; - } - } - - /** - * @{inheritdoc} - */ - public function __isset($name) { - return isset($this->_data[$name]); - } - - /** - * @{inheritdoc} - */ - public function __unset($name) { - unset($this->_data[$name]); - } } \ No newline at end of file diff --git a/src/Ratchet/Resource/ConnectionInterface.php b/src/Ratchet/Resource/ConnectionInterface.php index ed9ad9e..93dd516 100644 --- a/src/Ratchet/Resource/ConnectionInterface.php +++ b/src/Ratchet/Resource/ConnectionInterface.php @@ -2,34 +2,4 @@ namespace Ratchet\Resource; interface ConnectionInterface { - /** - * @return int - */ - function getId(); - - - /** - * Set an attribute to the connection - * @param mixed - * @param mixed - */ - function __set($name, $value); - - /** - * Get a previously set attribute bound to the connection - * @return mixed - * @throws \InvalidArgumentException - */ - function __get($name); - - /** - * @param mixed - * @return bool - */ - function __isset($name); - - /** - * @param mixed - */ - function __unset($name); } \ No newline at end of file diff --git a/src/Ratchet/Resource/Socket/BSDSocket.php b/src/Ratchet/Resource/Socket/BSDSocket.php index 4e15730..353054a 100644 --- a/src/Ratchet/Resource/Socket/BSDSocket.php +++ b/src/Ratchet/Resource/Socket/BSDSocket.php @@ -237,7 +237,6 @@ class BSDSocket implements SocketInterface { $return = array(); foreach ($collection as $key => $socket) { -die("Checking if sock is instance of this: " . (int)($socket instanceof $this) . "\n"); $return[$key] = ($socket instanceof $this ? $socket->getResource() : $socket); } diff --git a/tests/Ratchet/Tests/Component/Server/IOServerComponentTest.php b/tests/Ratchet/Tests/Component/Server/IOServerComponentTest.php index 99b4cfc..f0a3389 100644 --- a/tests/Ratchet/Tests/Component/Server/IOServerComponentTest.php +++ b/tests/Ratchet/Tests/Component/Server/IOServerComponentTest.php @@ -1,5 +1,5 @@ _server->run($this->_catalyst); + $this->_server->run(1025, '127.0.0.1', $this->_catalyst); $master = $this->getMasterConnection(); $this->_server->onOpen($master); $clone = $this->_decorated->_conn_open; - $this->assertEquals($master->getID() + 1, $clone->getID()); + $this->assertEquals($master->resourceId + 1, $clone->resourceId); } public function testOnMessageSendsToApp() { - $this->_server->run($this->_catalyst); + $this->_server->run(1025, '127.0.0.1', $this->_catalyst); $master = $this->getMasterConnection(); // todo, make FakeSocket better, set data in select, recv to pass data when called, then do this check diff --git a/tests/Ratchet/Tests/Component/WebSocket/Version/Hixie76Test.php b/tests/Ratchet/Tests/Component/WebSocket/Version/Hixie76Test.php index 172f024..bf08215 100644 --- a/tests/Ratchet/Tests/Component/WebSocket/Version/Hixie76Test.php +++ b/tests/Ratchet/Tests/Component/WebSocket/Version/Hixie76Test.php @@ -1,5 +1,5 @@ _id}"; } public function __toString() { diff --git a/tests/Ratchet/Tests/Resource/ConnectionTest.php b/tests/Ratchet/Tests/Resource/ConnectionTest.php index 375c09c..97c3994 100644 --- a/tests/Ratchet/Tests/Resource/ConnectionTest.php +++ b/tests/Ratchet/Tests/Resource/ConnectionTest.php @@ -43,31 +43,6 @@ class ConnectionTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($val, $this->_c->{$key}); } - public function testExceptionThrownOnInvalidGet() { - $this->setExpectedException('InvalidArgumentException'); - $ret = $this->_c->faked; - } - - public static function lambdaProvider() { - return array( - array('hello', 'world') - , array('obj', new \stdClass) - , array('arr', array()) - ); - } - - /** - * @dataProvider lambdaProvider - */ - public function testLambdaReturnValueOnGet($key, $val) { - $fn = function() use ($val) { - return $val; - }; - - $this->_c->{$key} = $fn; - $this->assertSame($val, $this->_c->{$key}); - } - /** * @dataProvider keyAndValProvider */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f814127..9c15fdc 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -2,4 +2,4 @@ error_reporting(E_ALL | E_STRICT); - require_once dirname(__DIR__) . '/vendor/.composer/autoload.php'; \ No newline at end of file + require_once dirname(__DIR__) . '/vendor/autoload.php'; \ No newline at end of file