259 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?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
 | |
|  * TODO: implement routing with some more detailed rules, remove hardcoded client-based routing.
 | |
|  */
 | |
| class Client_ClientManager {
 | |
| 
 | |
| 	/**
 | |
| 	 * @var Connection_ConnectionPool
 | |
| 	 */
 | |
| 	protected $connectionPool;
 | |
| 
 | |
| 	/**
 | |
| 	 * An array that contains all client instances for each connection.
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	protected $clientPool;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	protected $routingRules;
 | |
| 
 | |
| 	/**
 | |
| 	 * 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
 | |
| 	 */
 | |
| 	function __construct() {
 | |
| 		$this->connectionPool = new Connection_ConnectionPool();
 | |
| 		$this->clientPool = array();
 | |
| 		$this->registeredProtocols = array();
 | |
| 		$this->routingRules = array();
 | |
| 		$this->configPool = array();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Default destructor. Closes connections before being killed.
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	function __destruct() {
 | |
| 		unset($this->clientPool);
 | |
| 		unset($this->connectionPool);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @see Connection_ConnectionPool
 | |
| 	 * @return int
 | |
| 	 */
 | |
| 	public function countSockets() {
 | |
| 		return $this->connectionPool->countSockets();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns the amount of connected connection handlers.
 | |
| 	 * @see Connection_ConnectionPool
 | |
| 	 * @return int
 | |
| 	 */
 | |
| 	public function countActiveConnections() {
 | |
| 		return $this->connectionPool->countActiveConnections();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Main worker function.
 | |
| 	 * Processes incoming data, calls clients and much more.
 | |
| 	 * TODO: refactor this? (split it into handleFoobar() functions)
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	public function work() {
 | |
| 		$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) {
 | |
| 					//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.
 | |
| 					$config = $this->configPool[$connectionHandler->getID()];
 | |
| 					$this->configPool[$newConnectionHandler->getID()] = $config;
 | |
| 						//remove old connection
 | |
| 					$this->removeConnection($connectionHandler);
 | |
| 				}
 | |
| 				$this->removeClientForConnectionHandler($connectionHandler);
 | |
| 					//reconnect or not - this connectionHandler won't do that much.
 | |
| 				continue;
 | |
| 			}
 | |
| 				//handle accepted sockets, adopt them and treat them with care :-)
 | |
| 			if($connectionHandler->isListening() === TRUE) {
 | |
| 				$this->addClientForConnectionHandler($connectionHandler);
 | |
| 			}
 | |
| 				//create a client for a connection without one.
 | |
| 			if(!isset($this->clientPool[$connectionHandler->getID()])) {
 | |
| 				$this->addClientForConnectionHandler($connectionHandler);
 | |
| 			}
 | |
| 				//call the registered client
 | |
| 			if(isset($this->clientPool[$connectionHandler->getID()])) {
 | |
| 					//let the client process the data, send the results back.
 | |
| 				while($data = $connectionHandler->read()) {
 | |
| 					$result = $this->clientPool[$connectionHandler->getID()]->processRawData($data);
 | |
| 					if($result !== "") {
 | |
| 						$connectionHandler->write($result);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * 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
 | |
| 	 */
 | |
| 	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
 | |
| 	 */
 | |
| 	public function registerProtocol($protocol, $classNamePartial) {
 | |
| 		$this->registeredProtocols[$protocol] = $classNamePartial;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * 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
 | |
| 		if(!in_array($protocol, $this->registeredProtocols)) {
 | |
| 			throw new Exception_GeneralException("No client registered for protocol: '" . $protocol . "'!", 1290271651);
 | |
| 		}
 | |
| 		$className = "Client_" . $protocol . "Client";
 | |
| 			//look for the class
 | |
| 		if(class_exists($className)) {
 | |
| 			return new $className();
 | |
| 		} 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) {
 | |
| 		$protocol = $this->registeredProtocols[$connectionHandler->getProtocol()];
 | |
| 			//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);
 | |
| 		$protocolHandlerClass = "Protocol_".$protocol."ProtocolHandler";
 | |
| 		$protocolHandler = new $protocolHandlerClass();
 | |
| 		$client->injectProtocolHandler($protocolHandler);
 | |
| 		$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);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * 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);
 | |
| 	}
 | |
| 
 | |
| }
 | |
| ?>
 |