Restructure Overhaul
Server accepts single Observable object (was Chain of Responsibility) WebSocket is decorator of application implementing Observable Observable interface returns Command pattern object Interfaced all the things Code is a mess Unit tests are broken
This commit is contained in:
parent
ed1a35ff74
commit
1c0b8ed32d
@ -3,8 +3,8 @@ namespace Ratchet\Protocol;
|
||||
use Ratchet\Server;
|
||||
use Ratchet\Protocol\WebSocket\Client;
|
||||
use Ratchet\Protocol\WebSocket\Version;
|
||||
use Ratchet\Server\Message;
|
||||
use Ratchet\Socket;
|
||||
use Ratchet\SocketInterface;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
/**
|
||||
* @link http://ca.php.net/manual/en/ref.http.php
|
||||
@ -20,8 +20,13 @@ class WebSocket implements ProtocolInterface {
|
||||
*/
|
||||
protected $_lookup;
|
||||
|
||||
public function __construct() {
|
||||
/**
|
||||
*/
|
||||
protected $_app;
|
||||
|
||||
public function __construct(SocketObserver $application) {
|
||||
$this->_lookup = new \SplObjectStorage;
|
||||
$this->_app = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,24 +52,40 @@ class WebSocket implements ProtocolInterface {
|
||||
|
||||
public function setUp(Server $server) {
|
||||
$this->_server = $server;
|
||||
$this->_app->setUp($server);
|
||||
}
|
||||
|
||||
public function handleConnect(Socket $client) {
|
||||
$this->_lookup[$client] = new Client;
|
||||
public function onOpen(SocketInterface $conn) {
|
||||
$this->_lookup[$conn] = new Client;
|
||||
return $this->_app->onOpen($conn);
|
||||
}
|
||||
|
||||
public function handleMessage($message, Socket $from) {
|
||||
$headers = $this->getHeaders($message);
|
||||
public function onRecv(SocketInterface $from, $msg) {
|
||||
$client = $this->_lookup[$from];
|
||||
if (true !== $client->isHandshakeComplete()) {
|
||||
$headers = $this->getHeaders($msg);
|
||||
$header = $client->doHandshake($this->getVersion($headers));
|
||||
|
||||
$from->write($header, strlen($header));
|
||||
}
|
||||
// $from->write($header, strlen($header));
|
||||
$to = new \Ratchet\SocketCollection;
|
||||
$to->enqueue($from);
|
||||
$cmd = new \Ratchet\Server\Command\SendMessage($to);
|
||||
$cmd->setMessage($header);
|
||||
|
||||
// call my decorated onRecv()
|
||||
|
||||
$this->_server->log('Returning handshake: ' . $header);
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
public function handleClose(Socket $client) {
|
||||
unset($this->_lookup[$client]);
|
||||
return $this->_app->onRecv($from, $msg);
|
||||
}
|
||||
|
||||
public function onClose(SocketInterface $conn) {
|
||||
$cmd = $this->_app->onClose($conn);
|
||||
unset($this->_lookup[$conn]);
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,20 +1,13 @@
|
||||
<?php
|
||||
namespace Ratchet;
|
||||
use Ratchet\Server;
|
||||
use Ratchet\Server\Client;
|
||||
use Ratchet\Server\Message;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
interface ReceiverInterface {
|
||||
interface ReceiverInterface extends SocketObserver {
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getName();
|
||||
|
||||
function setUp(Server $server);
|
||||
|
||||
function handleConnect(Socket $client);
|
||||
|
||||
function handleMessage($message, Socket $from);
|
||||
|
||||
function handleClose(Socket $client);
|
||||
}
|
@ -5,7 +5,11 @@ use Ratchet\Protocol\ProtocolInterface;
|
||||
use Ratchet\Logging\LoggerInterface;
|
||||
use Ratchet\Logging\NullLogger;
|
||||
|
||||
class Server implements ServerInterface {
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
class Server implements SocketObserver {
|
||||
/**
|
||||
* The master socket, receives all connections
|
||||
* @type Socket
|
||||
@ -33,12 +37,14 @@ class Server implements ServerInterface {
|
||||
*/
|
||||
protected $_log;
|
||||
|
||||
protected $_app = null;
|
||||
|
||||
/**
|
||||
* @param Ratchet\Socket
|
||||
* @param boolean True, enables debug mode and the server doesn't infiniate loop
|
||||
* @param Logging\LoggerInterface
|
||||
*/
|
||||
public function __construct(Socket $host, LoggerInterface $logger = null) {
|
||||
public function __construct(SocketInterface $host, ReceiverInterface $application, LoggerInterface $logger = null) {
|
||||
$this->_master = $host;
|
||||
$socket = $host->getResource();
|
||||
$this->_resources[] = $socket;
|
||||
@ -49,6 +55,9 @@ class Server implements ServerInterface {
|
||||
$this->_log = $logger;
|
||||
|
||||
$this->_connections = new \ArrayIterator(array());
|
||||
|
||||
$this->_app = $application;
|
||||
$this->_app->setUp($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,6 +76,8 @@ class Server implements ServerInterface {
|
||||
/**
|
||||
* @param ReceiverInterface
|
||||
* @return Server
|
||||
* @deprecated
|
||||
* @todo Consider making server chain of responsibility, currently 1-1 relation w/ receivers
|
||||
*/
|
||||
public function attatchReceiver(ReceiverInterface $receiver) {
|
||||
$receiver->setUp($this);
|
||||
@ -76,7 +87,7 @@ class Server implements ServerInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Socket
|
||||
* @return SocketInterface
|
||||
*/
|
||||
public function getMaster() {
|
||||
return $this->_master;
|
||||
@ -101,9 +112,11 @@ class Server implements ServerInterface {
|
||||
* @todo Should I make handling open/close/msg an application?
|
||||
*/
|
||||
public function run($address = '127.0.0.1', $port = 1025) {
|
||||
/*
|
||||
if (count($this->_receivers) == 0) {
|
||||
throw new \RuntimeException("No receiver has been attached to the server");
|
||||
}
|
||||
*/
|
||||
|
||||
set_time_limit(0);
|
||||
ob_implicit_flush();
|
||||
@ -125,7 +138,7 @@ class Server implements ServerInterface {
|
||||
|
||||
foreach($changed as $resource) {
|
||||
if ($this->_master->getResource() === $resource) {
|
||||
$this->onConnect($this->_master);
|
||||
$this->onOpen($this->_master);
|
||||
} else {
|
||||
$conn = $this->_connections[$resource];
|
||||
$data = null;
|
||||
@ -134,7 +147,7 @@ class Server implements ServerInterface {
|
||||
if ($bytes == 0) {
|
||||
$this->onClose($conn);
|
||||
} else {
|
||||
$this->onMessage($data, $conn);
|
||||
$this->onRecv($conn, $data);
|
||||
|
||||
// new Message
|
||||
// $this->_receivers->handleMessage($msg, $conn);
|
||||
@ -143,6 +156,8 @@ class Server implements ServerInterface {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->_log->error($e->getMessage());
|
||||
} catch (\Exception $fuck) {
|
||||
$this->_log->error('Big uh oh: ' . $e->getMessage());
|
||||
}
|
||||
} while (true);
|
||||
|
||||
@ -150,27 +165,32 @@ class Server implements ServerInterface {
|
||||
// declare(ticks = 1);
|
||||
}
|
||||
|
||||
protected function onConnect(Socket $master) {
|
||||
$new_connection = clone $master;
|
||||
public function onOpen(SocketInterface $conn) {
|
||||
$new_connection = clone $conn;
|
||||
$this->_resources[] = $new_connection->getResource();
|
||||
$this->_connections[$new_connection->getResource()] = $new_connection;
|
||||
|
||||
$this->_log->note('New connection, ' . count($this->_connections) . ' total');
|
||||
|
||||
$this->_app->onOpen($new_connection)->execute();
|
||||
// /here $this->_receivers->handleConnection($new_connection);
|
||||
$this->tmpRIterator('handleConnect', $new_connection);
|
||||
// $this->tmpRIterator('handleConnect', $new_connection);
|
||||
}
|
||||
|
||||
protected function onMessage($msg, Socket $from) {
|
||||
public function onRecv(SocketInterface $from, $msg) {
|
||||
$this->_log->note('New message "' . $msg . '"');
|
||||
$this->tmpRIterator('handleMessage', $msg, $from);
|
||||
|
||||
$this->_app->onRecv($from, $msg)->execute();
|
||||
// $this->tmpRIterator('handleMessage', $msg, $from);
|
||||
}
|
||||
|
||||
protected function onClose(Socket $conn) {
|
||||
public function onClose(SocketInterface $conn) {
|
||||
$resource = $conn->getResource();
|
||||
$this->tmpRIterator('handleClose', $conn);
|
||||
// $this->tmpRIterator('handleClose', $conn);
|
||||
// $this->_receivers->handleDisconnect($conn);
|
||||
|
||||
$this->_app->onClose($conn)->execute();
|
||||
|
||||
unset($this->_connections[$resource]);
|
||||
unset($this->_resources[array_search($resource, $this->_resources)]);
|
||||
|
||||
|
15
lib/Ratchet/Server/Command/CloseConnection.php
Normal file
15
lib/Ratchet/Server/Command/CloseConnection.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace Ratchet\Server\Command;
|
||||
use Ratchet\SocketCollection;
|
||||
|
||||
class CloseConnection implements CommandInterface {
|
||||
protected $_sockets;
|
||||
|
||||
public function __construct(SocketCollection $sockets) {
|
||||
$this->_sockets = $sockets;
|
||||
}
|
||||
|
||||
function execute() {
|
||||
$this->_sockets->close();
|
||||
}
|
||||
}
|
9
lib/Ratchet/Server/Command/CommandInterface.php
Normal file
9
lib/Ratchet/Server/Command/CommandInterface.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace Ratchet\Server\Command;
|
||||
use Ratchet\SocketCollection;
|
||||
|
||||
interface CommandInterface {
|
||||
function __construct(SocketCollection $sockets);
|
||||
|
||||
function execute();
|
||||
}
|
11
lib/Ratchet/Server/Command/Null.php
Normal file
11
lib/Ratchet/Server/Command/Null.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
namespace Ratchet\Server\Command;
|
||||
use Ratchet\SocketCollection;
|
||||
|
||||
class Null implements CommandInterface {
|
||||
public function __construct(SocketCollection $sockets) {
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
}
|
||||
}
|
0
lib/Ratchet/Server/Command/Ping.php
Normal file
0
lib/Ratchet/Server/Command/Ping.php
Normal file
0
lib/Ratchet/Server/Command/Pong.php
Normal file
0
lib/Ratchet/Server/Command/Pong.php
Normal file
30
lib/Ratchet/Server/Command/SendMessage.php
Normal file
30
lib/Ratchet/Server/Command/SendMessage.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Ratchet\Server\Command;
|
||||
use Ratchet\SocketCollection;
|
||||
|
||||
class SendMessage implements CommandInterface {
|
||||
protected $_sockets;
|
||||
protected $_message = '';
|
||||
|
||||
public function __construct(SocketCollection $sockets) {
|
||||
$this->_sockets = $sockets;
|
||||
}
|
||||
|
||||
public function setMessage($msg) {
|
||||
$this->_message = (string)$msg;
|
||||
}
|
||||
|
||||
public function getMessage() {
|
||||
return $this->_message;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if (empty($this->_message)) {
|
||||
throw new \UnexpectedValueException("Message is empty");
|
||||
}
|
||||
|
||||
foreach ($this->_sockets as $current) {
|
||||
$current->write($this->_message, strlen($this->_message));
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ use Ratchet\Protocol\ProtocolInterface;
|
||||
* @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 {
|
||||
class Socket implements SocketInterface {
|
||||
/**
|
||||
* @type resource
|
||||
*/
|
||||
@ -80,6 +80,14 @@ class Socket {
|
||||
return $num;
|
||||
}
|
||||
|
||||
public function write($buffer, $length = 0) {
|
||||
return $this->__call('write', array($buffer, $length));
|
||||
}
|
||||
|
||||
public function close() {
|
||||
return $this->__call('close', array());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://ca3.php.net/manual/en/function.socket-recv.php
|
||||
* @param string
|
||||
|
13
lib/Ratchet/SocketCollection.php
Normal file
13
lib/Ratchet/SocketCollection.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace Ratchet;
|
||||
|
||||
class SocketCollection extends \SplQueue {
|
||||
public function __construct() {
|
||||
// parent::__construct();
|
||||
$this->setIteratorMode(static::IT_MODE_DELETE);
|
||||
}
|
||||
|
||||
public function enqueue(SocketInterface $value) {
|
||||
parent::enqueue($value);
|
||||
}
|
||||
}
|
10
lib/Ratchet/SocketInterface.php
Normal file
10
lib/Ratchet/SocketInterface.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace Ratchet;
|
||||
|
||||
interface SocketInterface {
|
||||
function write($buffer, $length = 0);
|
||||
|
||||
function recv(&$buf, $len, $flags);
|
||||
|
||||
function close();
|
||||
}
|
10
lib/Ratchet/SocketObserver.php
Normal file
10
lib/Ratchet/SocketObserver.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace Ratchet;
|
||||
|
||||
interface SocketObserver {
|
||||
function onOpen(SocketInterface $conn);
|
||||
|
||||
function onRecv(SocketInterface $from, $msg);
|
||||
|
||||
function onClose(SocketInterface $conn);
|
||||
}
|
Loading…
Reference in New Issue
Block a user