Cleaning Up

Cleaned up a lot of the code
Added API documentation
Fixed some unit tests
Much cleaning left to be done
This commit is contained in:
Chris Boden 2011-10-27 19:17:38 -04:00
parent 1c0b8ed32d
commit 7514ce8e85
13 changed files with 102 additions and 39 deletions

View File

@ -3,6 +3,11 @@ namespace Ratchet\Protocol;
use Ratchet\ReceiverInterface; use Ratchet\ReceiverInterface;
interface ProtocolInterface extends ReceiverInterface { interface ProtocolInterface extends ReceiverInterface {
/**
* @param Ratchet\ReceiverInterface
*/
function __construct(ReceiverInterface $application);
/** /**
* @return Array * @return Array
*/ */

View File

@ -4,7 +4,7 @@ use Ratchet\Server;
use Ratchet\Protocol\WebSocket\Client; use Ratchet\Protocol\WebSocket\Client;
use Ratchet\Protocol\WebSocket\Version; use Ratchet\Protocol\WebSocket\Version;
use Ratchet\SocketInterface; use Ratchet\SocketInterface;
use Ratchet\SocketObserver; use Ratchet\ReceiverInterface;
/** /**
* @link http://ca.php.net/manual/en/ref.http.php * @link http://ca.php.net/manual/en/ref.http.php
@ -21,10 +21,11 @@ class WebSocket implements ProtocolInterface {
protected $_lookup; protected $_lookup;
/** /**
* @type Ratchet\ReceiverInterface
*/ */
protected $_app; protected $_app;
public function __construct(SocketObserver $application) { public function __construct(ReceiverInterface $application) {
$this->_lookup = new \SplObjectStorage; $this->_lookup = new \SplObjectStorage;
$this->_app = $application; $this->_app = $application;
} }

View File

@ -9,5 +9,8 @@ interface ReceiverInterface extends SocketObserver {
*/ */
function getName(); function getName();
/**
* @param Ratchet\Server
*/
function setUp(Server $server); function setUp(Server $server);
} }

View File

@ -8,6 +8,7 @@ use Ratchet\Logging\NullLogger;
/** /**
* @todo Consider using _connections as master reference and passing iterator_to_array(_connections) to socket_select * @todo Consider using _connections as master reference and passing iterator_to_array(_connections) to socket_select
* @todo Move SocketObserver methods to separate class, create, wrap class in __construct * @todo Move SocketObserver methods to separate class, create, wrap class in __construct
* @todo Currently passing Socket object down the decorated chain - should be sending reference to it instead; Receivers do not interact with the Socket directly, they do so through the Command pattern
*/ */
class Server implements SocketObserver { class Server implements SocketObserver {
/** /**
@ -19,6 +20,7 @@ class Server implements SocketObserver {
/** /**
* @todo This needs to implement the composite pattern * @todo This needs to implement the composite pattern
* @var array of ReceiverInterface * @var array of ReceiverInterface
* @deprecated maybe?
*/ */
protected $_receivers = array(); protected $_receivers = array();
@ -37,10 +39,15 @@ class Server implements SocketObserver {
*/ */
protected $_log; protected $_log;
protected $_app = null; /**
* @var ReceiverInterface
* Maybe temporary?
*/
protected $_app;
/** /**
* @param Ratchet\Socket * @param Ratchet\Socket
* @param ReceiverInterface
* @param boolean True, enables debug mode and the server doesn't infiniate loop * @param boolean True, enables debug mode and the server doesn't infiniate loop
* @param Logging\LoggerInterface * @param Logging\LoggerInterface
*/ */
@ -60,6 +67,18 @@ class Server implements SocketObserver {
$this->_app->setUp($this); $this->_app->setUp($this);
} }
/**
* @todo Test this method
*/
public function newCommand($cmd, SocketCollection $sockets) {
$class = __NAMESPACE__ . '\\Server\\Command\\' . $cmd;
if (!class_exists($class)) {
throw new \UnexpectedValueException("Command {$cmd} not found");
}
return new $cmd($sockets);
}
/** /**
* @param Logging\LoggerInterface * @param Logging\LoggerInterface
*/ */
@ -94,12 +113,16 @@ class Server implements SocketObserver {
} }
/** /**
* @return ArrayIterator of Sockets * @return ArrayIterator of SocketInterfaces
*/ */
public function getIterator() { public function getIterator() {
return $this->_connections; return $this->_connections;
} }
/**
* @param string
* @param string (note|warning|error)
*/
public function log($msg, $type = 'note') { public function log($msg, $type = 'note') {
call_user_func(array($this->_log, $type), $msg); call_user_func(array($this->_log, $type), $msg);
} }
@ -112,7 +135,7 @@ class Server implements SocketObserver {
* @todo Should I make handling open/close/msg an application? * @todo Should I make handling open/close/msg an application?
*/ */
public function run($address = '127.0.0.1', $port = 1025) { public function run($address = '127.0.0.1', $port = 1025) {
/* /* Put this back if I change the server back to Chain of Responsibility
if (count($this->_receivers) == 0) { if (count($this->_receivers) == 0) {
throw new \RuntimeException("No receiver has been attached to the server"); throw new \RuntimeException("No receiver has been attached to the server");
} }
@ -148,16 +171,13 @@ class Server implements SocketObserver {
$this->onClose($conn); $this->onClose($conn);
} else { } else {
$this->onRecv($conn, $data); $this->onRecv($conn, $data);
// new Message
// $this->_receivers->handleMessage($msg, $conn);
} }
} }
} }
} catch (Exception $e) { } catch (Exception $e) {
$this->_log->error($e->getMessage()); $this->_log->error($e->getMessage());
} catch (\Exception $fuck) { } catch (\Exception $fuck) {
$this->_log->error('Big uh oh: ' . $e->getMessage()); $this->_log->error('Big uh oh: ' . $fuck->getMessage());
} }
} while (true); } while (true);
@ -173,21 +193,16 @@ class Server implements SocketObserver {
$this->_log->note('New connection, ' . count($this->_connections) . ' total'); $this->_log->note('New connection, ' . count($this->_connections) . ' total');
$this->_app->onOpen($new_connection)->execute(); $this->_app->onOpen($new_connection)->execute();
// /here $this->_receivers->handleConnection($new_connection);
// $this->tmpRIterator('handleConnect', $new_connection);
} }
public function onRecv(SocketInterface $from, $msg) { public function onRecv(SocketInterface $from, $msg) {
$this->_log->note('New message "' . $msg . '"'); $this->_log->note('New message "' . $msg . '"');
$this->_app->onRecv($from, $msg)->execute(); $this->_app->onRecv($from, $msg)->execute();
// $this->tmpRIterator('handleMessage', $msg, $from);
} }
public function onClose(SocketInterface $conn) { public function onClose(SocketInterface $conn) {
$resource = $conn->getResource(); $resource = $conn->getResource();
// $this->tmpRIterator('handleClose', $conn);
// $this->_receivers->handleDisconnect($conn);
$this->_app->onClose($conn)->execute(); $this->_app->onClose($conn)->execute();
@ -196,15 +211,4 @@ class Server implements SocketObserver {
$this->_log->note('Connection closed, ' . count($this->_connections) . ' connections remain (' . count($this->_resources) . ')'); $this->_log->note('Connection closed, ' . count($this->_connections) . ' connections remain (' . count($this->_resources) . ')');
} }
/**
* @todo Remove this method, make the receivers container implement the composite pattern
*/
protected function tmpRIterator() {
$args = func_get_args();
$fn = array_shift($args);
foreach ($this->_receivers as $app) {
call_user_func_array(array($app, $fn), $args);
}
}
} }

View File

@ -0,0 +1,14 @@
<?php
namespace Ratchet\Server\Command;
use Ratchet\SocketCollection;
/**
* @todo Move this command to the WebSocket protocol namespace
*/
class Ping implements CommandInterface {
public function __construct(SocketCollection $sockets) {
}
public function execute() {
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Ratchet\Server\Command;
use Ratchet\SocketCollection;
/**
* @todo Move this command to the WebSocket protocol namespace
*/
class Pong implements CommandInterface {
public function __construct(SocketCollection $sockets) {
}
public function execute() {
}
}

View File

@ -5,7 +5,6 @@ use Ratchet\Protocol\ProtocolInterface;
/** /**
* A wrapper for the PHP socket_ functions * A wrapper for the PHP socket_ functions
* @author Chris Boden <shout at chrisboden dot ca> * @author Chris Boden <shout at chrisboden dot ca>
* @todo Needs to be observable, Server needs to know when an applicaiton closes a connection
*/ */
class Socket implements SocketInterface { class Socket implements SocketInterface {
/** /**

View File

@ -2,8 +2,17 @@
namespace Ratchet; namespace Ratchet;
interface SocketInterface { interface SocketInterface {
/**
* @param string
* @param int
*/
function write($buffer, $length = 0); function write($buffer, $length = 0);
/**
* @param string
* @param int
* @param int
*/
function recv(&$buf, $len, $flags); function recv(&$buf, $len, $flags);
function close(); function close();

View File

@ -2,9 +2,19 @@
namespace Ratchet; namespace Ratchet;
interface SocketObserver { interface SocketObserver {
/**
* @param SocketInterface
*/
function onOpen(SocketInterface $conn); function onOpen(SocketInterface $conn);
/**
* @param SocketInterface
* @param string
*/
function onRecv(SocketInterface $from, $msg); function onRecv(SocketInterface $from, $msg);
/**
* @param SocketInterface
*/
function onClose(SocketInterface $conn); function onClose(SocketInterface $conn);
} }

View File

@ -3,7 +3,7 @@ namespace Ratchet\Tests\Mock;
use Ratchet\ReceiverInterface; use Ratchet\ReceiverInterface;
use Ratchet\Server; use Ratchet\Server;
use Ratchet\Tests\Mock\Socket as MockSocket; use Ratchet\Tests\Mock\Socket as MockSocket;
use Ratchet\Socket; use Ratchet\SocketInterface;
class Application implements ReceiverInterface { class Application implements ReceiverInterface {
public function getName() { public function getName() {
@ -13,12 +13,12 @@ class Application implements ReceiverInterface {
public function setUp(Server $server) { public function setUp(Server $server) {
} }
public function handleConnect(Socket $client) { public function onOpen(SocketInterface $conn) {
} }
public function handleMessage($msg, Socket $from) { public function onRecv(SocketInterface $from, $msg) {
} }
public function handleClose(Socket $client) { public function onClose(SocketInterface $conn) {
} }
} }

View File

@ -26,7 +26,7 @@ class FakeSocket extends RealSocket {
public function listen($backlog = 0) { public function listen($backlog = 0) {
} }
public function recv($buf, $len, $flags) { public function recv(&$buf, $len, $flags) {
} }
public function set_option($level, $optname, $optval) { public function set_option($level, $optname, $optval) {

View File

@ -1,10 +1,14 @@
<?php <?php
namespace Ratchet\Tests\Mock; namespace Ratchet\Tests\Mock;
use Ratchet\ReceiverInterface;
use Ratchet\Protocol\ProtocolInterface; use Ratchet\Protocol\ProtocolInterface;
use Ratchet\Server; use Ratchet\Server;
use Ratchet\Socket; use Ratchet\SocketInterface;
class Protocol implements ProtocolInterface { class Protocol implements ProtocolInterface {
public function __construct(ReceiverInterface $application) {
}
public static function getDefaultConfig() { public static function getDefaultConfig() {
return Array( return Array(
'domain' => AF_INET 'domain' => AF_INET
@ -23,12 +27,12 @@ class Protocol implements ProtocolInterface {
public function setUp(Server $server) { public function setUp(Server $server) {
} }
public function handleConnect(Socket $client) { public function onOpen(SocketInterface $conn) {
} }
public function handleMessage($msg, Socket $client) { public function onRecv(SocketInterface $from, $msg) {
} }
public function handleClose(Socket $client) { public function onClose(SocketInterface $conn) {
} }
} }

View File

@ -14,7 +14,7 @@ class ServerTest extends \PHPUnit_Framework_TestCase {
public function setUp() { public function setUp() {
$this->_catalyst = new Socket; $this->_catalyst = new Socket;
$this->_server = new Server($this->_catalyst); $this->_server = new Server($this->_catalyst, new TestApp);
} }
protected function getPrivateProperty($class, $name) { protected function getPrivateProperty($class, $name) {
@ -26,7 +26,7 @@ class ServerTest extends \PHPUnit_Framework_TestCase {
} }
public function testServerHasServerInterface() { public function testServerHasServerInterface() {
$constraint = $this->isInstanceOf('\\Ratchet\\ServerInterface'); $constraint = $this->isInstanceOf('\\Ratchet\\SocketObserver');
$this->assertThat($this->_server, $constraint); $this->assertThat($this->_server, $constraint);
} }
@ -56,7 +56,7 @@ class ServerTest extends \PHPUnit_Framework_TestCase {
$this->assertInstanceOf('\\Iterator', $this->_server->getIterator()); $this->assertInstanceOf('\\Iterator', $this->_server->getIterator());
} }
public function testServerCanNotRunWithoutApplication() { public function SKIPtestServerCanNotRunWithoutApplication() {
$this->setExpectedException('\\RuntimeException'); $this->setExpectedException('\\RuntimeException');
$this->_server->run(); $this->_server->run();
} }