* @version 0.0.0 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009, 2010 Hub Developer Team * @license GNU GPL 3.0 or any newer version * @link http://www.ship-simu.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ class TcpNetworkPackageHandler extends BaseNetworkPackageHandler implements Networkable { /** * Protected constructor * * @return void */ protected function __construct () { // Call parent constructor parent::__construct(__CLASS__); // Set handler name $this->setHandlerName('tcp'); } /** * Creates an instance of this class * * @return $handlerInstance An instance of a Networkable class */ public final static function createTcpNetworkPackageHandler () { // Get new instance $handlerInstance = new TcpNetworkPackageHandler(); // Initialize new resolver instance $resolverInstance = ObjectFactory::createObjectByConfiguredName('network_state_resolver_class'); // Set it in this class $handlerInstance->setResolverInstance($resolverInstance); // Return the prepared instance return $handlerInstance; } /** * Verifies the package data itself (only rudymentary check) * * @param $rawData Raw package data (as string * @return $isValid Wether the package data is valid */ private function isPackageDataValid ($rawData) { // Default is not valid $isValid = false; // Convert it back into an array $packageData = explode(NetworkPackage::PACKAGE_DATA_SEPERATOR, $rawData); // This should be at least three entries: sender|recipient|raw data if (count($packageData) < 3) { // Not enougth fields in $packageData! $this->setErrorCode(self::PACKAGE_ERROR_INCOMPLETE_DATA); } elseif (count(explode(NetworkPackage::PACKAGE_MASK_SEPERATOR, $packageData[NetworkPackage::INDEX_PACKAGE_CONTENT])) < 2) { // Not entougth fields in content $this->setErrorCode(self::PACKAGE_ERROR_INVALID_CONTENT); } elseif (!$this->ifRecipientMatchesOwnAddress($packageData)) { // Field 'recipient' doesn't match our address, this must always be the case $this->setErrorCode(self::PACKAGE_ERROR_RECIPIENT_MISMATCH); } else { // This check went fine... $isValid = true; } // Return the result return $isValid; } /** * Processes a package from given resource. This is mostly useful for TCP * package handling and is implemented in the TcpListener class * * @param $resource A valid resource identifier * @return void * @throws InvalidResourceException If the given resource is invalid * @todo ~10% done */ public function processResourcePackage ($resource) { // Check the resource if (!is_resource($resource)) { // Throw an exception throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE); } // END - if // Init package data array $packageData = array(); // Reset error code to unhandled $this->setErrorCode(self::SOCKET_ERROR_UNHANDLED); // Debug message $this->debugOutput('HANDLER: Handling TCP package from peer ' . $resource); // Read the raw data from socket $rawData = socket_read($resource, $this->getConfigInstance()->getConfigEntry('tcp_buffer_length'), PHP_NORMAL_READ); // Is it valid? if (($rawData === false) || (socket_last_error($resource) > 0)) { // Network error or connection lost $this->setErrorCode(socket_last_error($resource)); } elseif (empty($rawData)) { // The peer did send nothing to us $this->setErrorCode(self::SOCKET_ERROR_EMPTY_DATA); } elseif (!$this->isPackageDataValid($rawData)) { // Invalid package data if ($this->getErrorCode() == self::SOCKET_ERROR_UNHANDLED) { // Set it to PACKAGE_ERROR_INVALID_DATA, because SOCKET_ERROR_UNHANDLED should not be used $this->setErrorCode(self::PACKAGE_ERROR_INVALID_DATA); } // END - if } else { // Prepare the package data $packageData = explode(NetworkPackage::PACKAGE_DATA_SEPERATOR, $rawData); // Low-level checks are all green $this->setErrorCode(self::PACKAGE_LEVEL_CHECK_OKAY); } // Get a state from the resolver for this package $stateInstance = $this->getResolverInstance()->resolveStateByPackage($this, $packageData); die('UNFINISHED:'.$stateInstance->__toString()); } } // [EOF] ?>