2010-11-21 23:48:11 +01:00
< ? php
/**
* This class contains the connection handler .
* It handles all the incoming and outgoing data by forwarding it
* to the clients for the specific connection .
* @ author jpt
* @ package Client
* @ depends Connection
2010-11-27 20:59:11 +01:00
* TODO : implement routing with some more detailed rules , remove hardcoded client - based routing .
2010-11-21 23:48:11 +01:00
*/
class Client_ClientManager {
/**
* @ var Connection_ConnectionPool
*/
protected $connectionPool ;
/**
* An array that contains all client instances for each connection .
* @ var array
*/
protected $clientPool ;
/**
* @ var array
*/
2010-11-27 20:59:11 +01:00
protected $routingRules ;
2010-11-21 23:48:11 +01:00
/**
* An array that contains all protocols we have clients for .
* @ var array
*/
protected $registeredProtocols ;
/**
* Contains Connection - attached configurations .
* @ var array
*/
protected $configPool ;
/**
* Default constructor .
* @ return void
*/
2010-12-18 15:42:56 +01:00
public function __construct () {
2010-11-28 19:35:08 +01:00
$this -> connectionPool = new Connection_ConnectionPool ();
2010-11-21 23:48:11 +01:00
$this -> clientPool = array ();
$this -> registeredProtocols = array ();
2010-11-27 20:59:11 +01:00
$this -> routingRules = array ();
2010-11-21 23:48:11 +01:00
$this -> configPool = array ();
}
/**
* Default destructor . Closes connections before being killed .
* @ return void
*/
2010-12-18 15:42:56 +01:00
public function __destruct () {
2010-11-21 23:48:11 +01:00
unset ( $this -> clientPool );
unset ( $this -> connectionPool );
}
/**
* @ see Connection_ConnectionPool
* @ return int
*/
2010-12-08 17:47:04 +01:00
public function countSockets () {
return $this -> connectionPool -> countSockets ();
2010-11-21 23:48:11 +01:00
}
2010-12-08 17:54:08 +01:00
/**
* Returns the amount of connected connection handlers .
* @ see Connection_ConnectionPool
* @ return int
*/
public function countActiveConnections () {
return $this -> connectionPool -> countActiveConnections ();
}
2010-11-21 23:48:11 +01:00
/**
* Main worker function .
* Processes incoming data , calls clients and much more .
2010-12-08 17:47:04 +01:00
* TODO : refactor this ? ( split it into handleFoobar () functions )
2010-11-21 23:48:11 +01:00
* @ return void
*/
public function work () {
2011-06-26 00:13:53 +02:00
//firstly, create clients for connections without one.
foreach ( $this -> connectionPool -> getConnectionHandlers () AS $connectionHandler ) {
if ( ! isset ( $this -> clientPool [ $connectionHandler -> getID ()])) {
//new connections might need a client, so we'll create one here.
$this -> addClientForConnectionHandler ( $connectionHandler );
//allow client to send initial stuff right after connecting to the server.
$this -> clientPool [ $connectionHandler -> getID ()] -> initializeConnection ();
//after initializing, have it process an empty string in order to get stuff to write. >.<
$result = $this -> clientPool [ $connectionHandler -> getID ()] -> processRawData ( " " );
if ( $result !== " " ) $connectionHandler -> write ( $result );
}
}
//then, process all connections that have stuff to read.
2010-11-21 23:48:11 +01:00
$connectionHandlers = $this -> connectionPool -> select ();
if ( isset ( $connectionHandlers [ " read " ]) === FALSE || count ( $connectionHandlers [ " read " ]) === 0 ) return ;
foreach ( $connectionHandlers [ " read " ] AS $connectionHandler ) {
//handle disconnects
if ( $connectionHandler -> isConnected () === FALSE && $connectionHandler -> isListening () === FALSE ) {
2010-11-28 17:38:03 +01:00
//check whether the reconnect-flag is set
if ( $connectionHandler -> getReconnect () === TRUE ) {
//have the connectionHandler do the reconnect.
$newConnectionHandler = $connectionHandler -> reconnect ();
//get the client and reset it.
$client = $this -> clientPool [ $connectionHandler -> getID ()];
$client -> resetConnectionStatus ();
//assign the client to the new connectionHandler.
$this -> clientPool [ $newConnectionHandler -> getID ()] = $client ;
//get the config and assign it to the new connectionHandler, too.
2010-11-28 17:51:43 +01:00
$config = $this -> configPool [ $connectionHandler -> getID ()];
$this -> configPool [ $newConnectionHandler -> getID ()] = $config ;
2010-11-28 17:38:03 +01:00
//remove old connection
$this -> removeConnection ( $connectionHandler );
2011-06-26 00:13:53 +02:00
//re-initialize the client
$this -> clientPool [ $newConnectionHandler -> getID ()] -> initializeConnection ();
//and of course, process stuff to get the buffer filled. :/
$result = $this -> clientPool [ $newConnectionHandler -> getID ()] -> processRawData ( " " );
if ( $result !== " " ) $newConnectionHandler -> write ( $result );
2010-11-28 17:38:03 +01:00
}
2010-11-21 23:48:11 +01:00
$this -> removeClientForConnectionHandler ( $connectionHandler );
2011-06-26 00:13:53 +02:00
//this connectionHandler won't do much anymore - kill it.
2010-11-28 17:38:03 +01:00
continue ;
2010-11-21 23:48:11 +01:00
}
2010-11-27 20:59:11 +01:00
//handle accepted sockets, adopt them and treat them with care :-)
2010-11-21 23:48:11 +01:00
if ( $connectionHandler -> isListening () === TRUE ) {
$this -> addClientForConnectionHandler ( $connectionHandler );
2011-06-26 00:13:53 +02:00
//TODO: maybe we want to trigger the "client" here, too? -- YES
$this -> clientPool [ $connectionHandler -> getID ()] -> initializeConnection ();
2010-11-21 23:48:11 +01:00
}
2011-06-26 00:13:53 +02:00
2010-11-27 20:59:11 +01:00
//call the registered client
2010-11-21 23:48:11 +01:00
if ( isset ( $this -> clientPool [ $connectionHandler -> getID ()])) {
2010-11-28 17:51:43 +01:00
//let the client process the data, send the results back.
2010-11-21 23:48:11 +01:00
while ( $data = $connectionHandler -> read ()) {
2010-11-28 02:15:20 +01:00
$result = $this -> clientPool [ $connectionHandler -> getID ()] -> processRawData ( $data );
2010-11-21 23:48:11 +01:00
if ( $result !== " " ) {
$connectionHandler -> write ( $result );
}
}
}
}
2011-06-26 00:13:53 +02:00
//after that, we're done here.
2010-11-21 23:48:11 +01:00
}
/**
* Calls ConnectionPool in order to create a simple connection .
* @ see Connection_ConnectionPool
* @ param string $group
* @ param boolean $IPv6
* @ return Connection_ConnectionHandler
*/
public function createTcpConnection ( $group = " " , $protocol = " RAW " , $IPv6 = FALSE ) {
return $this -> connectionPool -> createTcpConnection ( $group , $protocol , $IPv6 );
}
/**
* Closes and removes the connection .
* @ param Connection_ConnectionHandler $connectionHandler
2010-12-19 15:26:32 +01:00
* @ return void
2010-11-21 23:48:11 +01:00
*/
public function removeConnection ( $connectionHandler ) {
unset ( $this -> configPool [ $connectionHandler -> getID ()]);
unset ( $this -> clientPool [ $connectionHandler -> getID ()]);
$this -> connectionPool -> removeConnectionHandler ( $connectionHandler );
}
/**
* Registers a protocol with a specific client .
* @ param string $protocol
* @ param string $className
* @ return void
*/
2010-11-28 03:45:25 +01:00
public function registerProtocol ( $protocol , $classNamePartial ) {
$this -> registeredProtocols [ $protocol ] = $classNamePartial ;
2010-11-21 23:48:11 +01:00
}
/**
* Unregisters a protocol .
* @ param string $protocol
* @ return void
*/
public function unregisterProtocol ( $protocol ) {
unset ( $this -> registeredProtocols [ $protocol ]);
}
/**
* Searches for the registered client for the given protocol .
* Returns a client instance or void .
* @ param string $protocol
* @ return mixed
* @ throws Exception_GeneralException
*/
protected function createClientForProtocol ( $protocol ) {
//look for the protocol
2010-11-28 03:45:25 +01:00
if ( ! in_array ( $protocol , $this -> registeredProtocols )) {
2010-11-21 23:48:11 +01:00
throw new Exception_GeneralException ( " No client registered for protocol: ' " . $protocol . " '! " , 1290271651 );
}
2010-11-28 03:45:25 +01:00
$className = " Client_ " . $protocol . " Client " ;
2010-11-21 23:48:11 +01:00
//look for the class
if ( class_exists ( $className )) {
2011-01-22 21:28:10 +01:00
$client = new $className ();
if ( ! $client instanceof Client_AbstractClient ) throw new Exception_GeneralException ( " Class ' " . $className . " ' does not implement the AbstractClient-API! " , 1294837055 );
return $client ;
2010-11-21 23:48:11 +01:00
} else {
throw new Exception_GeneralException ( " Registered class name ' " . $className . " ' does not exist for protocol: ' " . $protocol . " '! " , 1290271773 );
}
}
/**
* Adds a client to our client pool .
* @ param Connection_ConnectionHandler $connectionHandler
* @ return void
*/
protected function addClientForConnectionHandler ( $connectionHandler ) {
2010-11-28 03:45:25 +01:00
$protocol = $this -> registeredProtocols [ $connectionHandler -> getProtocol ()];
2010-11-21 23:48:11 +01:00
//do not try this for raw connections
if ( $protocol === " RAW " ) return ;
$client = $this -> createClientForProtocol ( $protocol );
if ( isset ( $this -> configPool [ $connectionHandler -> getID ()])) {
$client -> loadConfig ( $this -> configPool [ $connectionHandler -> getID ()]);
}
$client -> injectClientManager ( $this );
2010-11-28 03:45:25 +01:00
$protocolHandlerClass = " Protocol_ " . $protocol . " ProtocolHandler " ;
$protocolHandler = new $protocolHandlerClass ();
2010-11-28 02:15:20 +01:00
$client -> injectProtocolHandler ( $protocolHandler );
2010-11-21 23:48:11 +01:00
$client -> setID ( $connectionHandler -> getID ());
$client -> setGroup ( $connectionHandler -> getGroup ());
$this -> clientPool [ $connectionHandler -> getID ()] = $client ;
}
/**
* Removes a client from our client pool .
* @ param Connection_ConnectionHandler $connectionHandler
* @ return void
*/
protected function removeClientForConnectionHandler ( $connectionHandler ) {
unset ( $this -> clientPool [ $connectionHandler -> getID ()]);
$this -> connectionPool -> removeConnectionHandler ( $connectionHandler );
}
/**
* Attaches a configuration to a connection .
* Will overwrite the existing configuration for the connection .
* @ param array $config
* @ param Connection_ConnectionHandler $connectionHandler
* @ return void
*/
public function attachConfig ( $config , $connectionHandler ) {
$this -> configPool [ $connectionHandler -> getID ()] = $config ;
}
/**
* Calls Connection_Pool
* @ see Connection_ConnectionPool
* @ param int $id
* @ param string $data
* @ return void
*/
public function sendToID ( $id , $data ) {
return $this -> connectionPool -> writeToID ( $id , $data );
}
2011-06-26 00:13:53 +02:00
/**
* Returns a list of available connection IDs .
* @ return array
*/
public function getIDs () {
$list = array ();
foreach ( $this -> connectionPool -> getConnectionHandlers () AS $connectionHandler ) {
$list [] = $connectionHandler -> getID ();
}
return $list ;
}
/**
* Returns a list of available connection groups .
* @ return array
*/
public function getGroups () {
$list = array ();
foreach ( $this -> connectionPool -> getConnectionHandlers () AS $connectionHandler ) {
$list [] = $connectionHandler -> getGroup ();
}
return $list ;
}
2010-11-21 23:48:11 +01:00
/**
* Calls Connection_Pool
* @ see Connection_ConnectionPool
* @ param string $group
* @ param string $data
* @ return void
*/
public function sendToGroup ( $group , $data ) {
return $this -> connectionPool -> writeToGroup ( $group , $data );
}
}
?>