Merge branch 'refs/heads/tickets' into wamp
This commit is contained in:
commit
56768b5963
22
README.md
22
README.md
@ -1,11 +1,11 @@
|
||||
[](http://travis-ci.org/cboden/Ratchet)
|
||||
[](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
|
@ -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"
|
||||
}
|
||||
}
|
20
composer.lock
generated
20
composer.lock
generated
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -52,7 +52,7 @@ class WebSocketComponent implements MessageComponentInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritdoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onOpen(ConnectionInterface $conn) {
|
||||
$conn->WebSocket = new \stdClass;
|
||||
|
@ -21,7 +21,7 @@ class Runtime extends ActionTemplate {
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritdoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute(ComponentInterface $scope = null) {
|
||||
$cmd = $this->_command;
|
||||
|
@ -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) {
|
||||
|
@ -23,7 +23,7 @@ class Composite extends \SplQueue implements CommandInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* @{inheritdoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute(ComponentInterface $scope = null) {
|
||||
$this->setIteratorMode(static::IT_MODE_DELETE);
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Application\Server;
|
||||
namespace Ratchet\Tests\Component\Server;
|
||||
use Ratchet\Component\Server\IOServerComponent;
|
||||
use Ratchet\Tests\Mock\FakeSocket as Socket;
|
||||
use Ratchet\Tests\Mock\Component as TestApp;
|
||||
@ -37,17 +37,17 @@ class IOServerComponentTest extends \PHPUnit_Framework_TestCase {
|
||||
}
|
||||
|
||||
public function testOnOpenPassesClonedSocket() {
|
||||
$this->_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
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Application\WebSocket\Version;
|
||||
namespace Ratchet\Tests\Component\WebSocket\Version;
|
||||
use Ratchet\Component\WebSocket\Version\Hixie76;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Application\WebSocket\Version;
|
||||
namespace Ratchet\Tests\Component\WebSocket\Version;
|
||||
use Ratchet\Component\WebSocket\Version\HyBi10;
|
||||
use Ratchet\Component\WebSocket\Version\RFC6455\Frame;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Application\WebSocket\Version\RFC6455;
|
||||
namespace Ratchet\Tests\Component\WebSocket\Version\RFC6455;
|
||||
use Ratchet\Component\WebSocket\Version\RFC6455\Frame;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Application\WebSocket\Version\RFC6455;
|
||||
namespace Ratchet\Tests\Component\WebSocket\Version\RFC6455;
|
||||
use Ratchet\Component\WebSocket\Version\RFC6455\HandshakeVerifier;
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace Ratchet\Tests\Application\WebSocket\Version;
|
||||
namespace Ratchet\Tests\Component\WebSocket\Version;
|
||||
use Ratchet\Component\WebSocket\Version\RFC6455;
|
||||
use Ratchet\Component\WebSocket\Version\RFC6455\Frame;
|
||||
use Guzzle\Http\Message\RequestFactory;
|
||||
|
@ -12,7 +12,7 @@ class FakeSocket implements SocketInterface {
|
||||
public $_last = array();
|
||||
|
||||
public function getResource() {
|
||||
return null;
|
||||
return "#{$this->_id}";
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -2,4 +2,4 @@
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
require_once dirname(__DIR__) . '/vendor/.composer/autoload.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
Loading…
Reference in New Issue
Block a user