<?php
+// Own namespace
+namespace Hub\;
+
+// Import application-specific stuff
+use Hub\Generic\BaseHubSystem;
+
/**
* A general ??? class
*
--- /dev/null
+use Hub\Listener\BaseListener;
+
+use CoreFramework\Listener\Listenable;
+
+ /**
+ * Listener instance
+ */
+ private $listenerInstance = NULL;
+
+ /**
+ * Setter for listener instance
+ *
+ * @param $listenerInstance A Listenable instance
+ * @return void
+ */
+ protected final function setListenerInstance (Listenable $listenerInstance) {
+ $this->listenerInstance = $listenerInstance;
+ }
+
+ /**
+ * Getter for listener instance
+ *
+ * @return $listenerInstance A Listenable instance
+ */
+ protected final function getListenerInstance () {
+ return $this->listenerInstance;
+ }
+
+ /**
+ * Handles socket error for given socket resource and peer data. This method
+ * validates $socketResource if it is a valid resource (see is_resource())
+ * but assumes valid data in array $recipientData, except that
+ * count($recipientData) is always 2.
+ *
+ * @param $method Value of __METHOD__ from calling method
+ * @param $line Value of __LINE__ from calling method
+ * @param $socketResource A valid socket resource
+ * @param $socketData A valid socket data array (0 = IP/file name, 1 = port)
+ * @return void
+ * @throws InvalidSocketException If $socketResource is no socket resource
+ * @throws NoSocketErrorDetectedException If socket_last_error() gives zero back
+ * @todo Move all this socket-related stuff into own class, most of it resides in BaseListener
+ */
+ protected final function handleSocketError ($method, $line, $socketResource, array $socketData) {
+ // This method handles only socket resources
+ if (!is_resource($socketResource)) {
+ // No resource, abort here
+ throw new InvalidSocketException(array($this, $socketResource), BaseListener::EXCEPTION_INVALID_SOCKET);
+ } // END - if
+
+ // Check socket array, 1st element is mostly IP address (or file name), 2nd is port number
+ //* DEBUG-DIE: */ die(__METHOD__ . ':socketData=' . print_r($socketData, true));
+ assert(isset($socketData[0]));
+ assert(isset($socketData[1]));
+
+ // Get error code for first validation (0 is not an error)
+ $errorCode = socket_last_error($socketResource);
+
+ // If the error code is zero, someone called this method without an error
+ if ($errorCode == 0) {
+ // No error detected (or previously cleared outside this method)
+ throw new NoSocketErrorDetectedException(array($this, $socketResource), BaseListener::EXCEPTION_NO_SOCKET_ERROR);
+ } // END - if
+
+ // Get handler (method) name
+ $handlerName = $this->getSocketErrorHandlerFromCode($errorCode);
+
+ // Call-back the error handler method
+ call_user_func_array(array($this, $handlerName), array($socketResource, $socketData));
+
+ // Finally clear the error because it has been handled
+ socket_clear_error($socketResource);
+ }
namespace Hub\Generic;
// Import application-specific stuff
+use Hub\Information\ShareableInfo;
use Hub\Network\Receive\Receivable;
+use Hub\Pool\Poolable;
// Import framework stuff
-use CoreFramework\Information\ShareableInfo;
use CoreFramework\Object\BaseFrameworkSystem;
-use CoreFramework\Pool\Poolable;
/**
* A general hub system class
--- /dev/null
+Deny from all
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Container\Socket;
+
+// Import application-specific stuff
+use Hub\Information\ShareableInfo;
+
+// Import framework stuff
+use CoreFramework\Listener\Listenable;
+use CoreFramework\Registry\Registerable;
+
+/**
+ * A Socket Container class
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class SocketContainer extends BaseContainer implements Registerable {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+ }
+
+ /**
+ * Creates an instance of this Container class and prepares it for usage
+ *
+ * @param $socketResource A valid socket resource
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @param $packageData Raw package data
+ * @return $containerInstance An instance of this Container class
+ */
+ public static final function createSocketContainer ($socketResource, ShareableInfo $infoInstance = NULL, array $packageData = array()) {
+ // Get a new instance
+ $containerInstance = new SocketContainer();
+
+ // Remove unneeded entries
+ unset($packageData[NetworkPackage::PACKAGE_DATA_CONTENT]);
+ unset($packageData[NetworkPackage::PACKAGE_DATA_HASH]);
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER[' . __METHOD__ . ':' . __LINE__ . ']:socketResource=' . $socketResource . ',packageData='.print_r($packageData, true));
+
+ // Is the info instance set?
+ if ($infoInstance instanceof ShareableInfo) {
+ // Get listener/helper from info class
+ $listenerInstance = $infoInstance->getListenerInstance();
+ $helperInstance = $infoInstance->getHelperInstance();
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER[' . __METHOD__ . ':' . __LINE__ . ']: listenerInstance[]=' . gettype($listenerInstance));
+
+ // Is there a listener instance set?
+ if ($listenerInstance instanceof Listenable) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER[' . __METHOD__ . ':' . __LINE__ . ']: Setting listenerInstance=' . $listenerInstance->__toString() . ' ...');
+
+ // Set it here for later usage
+ $containerInstance->setListenerInstance($listenerInstance);
+ } elseif ($helperInstance instanceof ConnectionHelper) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER[' . __METHOD__ . ':' . __LINE__ . ']: Setting helperInstance=' . $helperInstance->__toString() . ' ...');
+
+ // Set it here for later usage
+ $containerInstance->setHelperInstance($helperInstance);
+ }
+ } // END - if
+
+ // Set the resource ...
+ $containerInstance->setSocketResource($socketResource);
+
+ // ... and package data
+ $containerInstance->setPackageData($packageData);
+
+ // Return the prepared instance
+ return $containerInstance;
+ }
+
+ /**
+ * Checks whether the given Universal Node Locator matches with the one from package data
+ *
+ * @param $unl A Universal Node Locator
+ * @return $matches Whether $address matches with the one from package data
+ */
+ public final function ifAddressMatches ($unl) {
+ // Get current package data
+ $packageData = $this->getPackageData();
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER[' . __METHOD__ . ':' . __LINE__ . ']: unl=' . $unl . ',packageData=' . print_r($packageData, true));
+
+ // So, does both match?
+ $matches = ((isset($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT])) && ($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT] === $unl));
+
+ // Return result
+ return $matches;
+ }
+
+ /**
+ * Checks whether the given socket matches with stored
+ *
+ * @param $socketResource A valid socket resource
+ * @return $matches Whether given socket matches
+ */
+ public final function ifSocketResourceMatches ($socketResource) {
+ // Debug message
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER[' . __METHOD__ . ':' . __LINE__ . ']: socketResource[' . gettype($socketResource) . ']=' .$socketResource . ',storedResource[' . gettype($this->getSocketResource()) . ']=' . $this->getSocketResource());
+
+ // So, does both match?
+ $matches = ((is_resource($socketResource)) && ($socketResource === $this->getSocketResource()));
+
+ // Return result
+ return $matches;
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+/**
+ * A ??? network package handler
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+class ???NetworkPackageHandler extends BaseNetworkPackageHandler implements Networkable {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set handler name
+ $this->setHandlerName('!!!');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $handlerInstance An instance of a Networkable class
+ */
+ public final static function create???NetworkPackageHandler () {
+ // Get new instance
+ $handlerInstance = new ???NetworkPackageHandler();
+
+ // Return the prepared instance
+ return $handlerInstance;
+ }
+
+ /**
+ * 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 0%
+ */
+ public function processResourcePackage ($resource) {
+ // Check the resource
+ if (!is_resource($resource)) {
+ // Throw an exception
+ throw new InvalidResourceException($this, self::EXCEPTION_INVALID_RESOURCE);
+ } // END - if
+
+ // Implement processing here
+ $this->partialStub('Please implement this method.');
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Handler\Data;
+
+// Import framework stuff
+use CoreFramework\Factory\ObjectFactory;
+use CoreFramework\Generic\FrameworkException;
+use CoreFramework\Handler\BaseHandler;
+
+/**
+ * A general data Handler
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+abstract class BaseDataHandler extends BaseHandler {
+ /**
+ * Last exception instance from database layer or NULL (default)
+ */
+ private $lastException = NULL;
+
+ /**
+ * Array with search criteria elements
+ */
+ protected $searchData = array();
+
+ /**
+ * Array with all data XML nodes (which hold the actual data) and their values
+ */
+ protected $messageDataElements = array();
+
+ /**
+ * Array for translating message data elements (other node's data mostly)
+ * into configuration elements.
+ */
+ protected $messageToConfig = array();
+
+ /**
+ * Array for copying configuration entries
+ */
+ protected $configCopy = array();
+
+ /**
+ * Protected constructor
+ *
+ * @param $className Name of the class
+ * @return void
+ */
+ protected function __construct ($className) {
+ // Call parent constructor
+ parent::__construct($className);
+
+ // Get a DHT instance
+ $dhtInstance = DhtObjectFactory::createDhtInstance('node');
+
+ // Set it here
+ $this->setDhtInstance($dhtInstance);
+ }
+
+ /**
+ * Getter for search data array
+ *
+ * @return $searchData Search data array
+ */
+ public final function getSearchData () {
+ return $this->searchData;
+ }
+
+ /**
+ * Getter for last exception
+ *
+ * @return $lastException Last thrown exception
+ */
+ public final function getLastException () {
+ return $this->lastException;
+ }
+
+ /**
+ * Setter for last exception
+ *
+ * @param $lastException Last thrown exception
+ * @return void
+ */
+ public final function setLastException (FrameworkException $exceptionInstance = NULL) {
+ $this->lastException = $exceptionInstance;
+ }
+
+ /**
+ * Prepares a message as answer for given message data for delivery.
+ *
+ * @param $messageData An array with all message data
+ * @param $packageInstance An instance of a Deliverable instance
+ * @return void
+ */
+ protected function prepareAnswerMessage (array $messageData, Deliverable $packageInstance) {
+ // Debug message
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('MESSAGE-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Going to send an answer message for ' . $this->getHandlerName() . ' ...');
+
+ // Get a helper instance based on this handler's name
+ $helperInstance = ObjectFactory::createObjectByConfiguredName('node_answer_' . $this->getHandlerName() . '_helper_class', array($messageData));
+
+ // Get node instance
+ $nodeInstance = NodeObjectFactory::createNodeInstance();
+
+ // Load descriptor XML
+ $helperInstance->loadDescriptorXml($nodeInstance);
+
+ /*
+ * Set missing (temporary) configuration data, mostly it needs to be
+ * copied from message data array.
+ */
+ $this->initMessageConfigurationData($messageData);
+
+ // Compile any configuration variables
+ $helperInstance->getTemplateInstance()->compileConfigInVariables();
+
+ // Deliver the package
+ $helperInstance->sendPackage($nodeInstance);
+
+ /*
+ * Remove temporary configuration
+ */
+ $this->removeMessageConfigurationData($messageData);
+
+ // Debug message
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('MESSAGE-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Answer message has been prepared.');
+ }
+
+ /**
+ * Prepares the next message
+ *
+ * @param $messageData An array with all message data
+ * @param $packageInstance An instance of a Deliverable instance
+ * @return void
+ */
+ protected function prepareNextMessage (array $messageData, Deliverable $packageInstance) {
+ // Debug message
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('MESSAGE-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Going to send next message ...');
+
+ // Get a helper instance based on this handler's name
+ $helperInstance = ObjectFactory::createObjectByConfiguredName('node_next_' . $this->getHandlerName() . '_helper_class', array($messageData));
+
+ // Get node instance
+ $nodeInstance = NodeObjectFactory::createNodeInstance();
+
+ // Load descriptor XML
+ $helperInstance->loadDescriptorXml($nodeInstance);
+
+ /*
+ * Set missing (temporary) configuration data, mostly it needs to be
+ * copied from message data array.
+ */
+ $this->initMessageConfigurationData($messageData);
+
+ // Compile any configuration variables
+ $helperInstance->getTemplateInstance()->compileConfigInVariables();
+
+ // Deliver the package
+ $helperInstance->sendPackage($nodeInstance);
+
+ /*
+ * Remove temporary configuration
+ */
+ $this->removeMessageConfigurationData($messageData);
+
+ // Debug message
+ /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('MESSAGE-HANDLER[' . __METHOD__ . ':' . __LINE__ . ']: Next message has been prepared.');
+ }
+
+ /**
+ * Initializes configuration data from given message data array
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ */
+ abstract protected function initMessageConfigurationData (array $messageData);
+
+ /**
+ * Removes configuration data with given message data array from global
+ * configuration
+ *
+ * @param $messageData An array with all message data
+ * @return void
+ */
+ abstract protected function removeMessageConfigurationData (array $messageData);
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Handler\RawData;
+
+/**
+ * A !!! raw data handler
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class ???RawDataHandler extends BaseRawDataHandler implements Networkable {
+ /**
+ * Last socket error (default: Success)
+ */
+ private $lastSocketError = 0;
+
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set handler name
+ $this->setHandlerName('|||');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $handlerInstance An instance of a Networkable class
+ */
+ public static final function create???RawDataHandler () {
+ // Get new instance
+ $handlerInstance = new ???RawDataHandler();
+
+ // Return the prepared instance
+ return $handlerInstance;
+ }
+
+ /**
+ * Processes raw data from given resource. This is mostly useful for TCP
+ * package handling and is implemented in the ???Listener class
+ *
+ * @param $resource A valid socket resource array
+ * @return void
+ */
+ public function processRawDataFromResource (array $socketArray) {
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Handler\Raw;
+
+// Import framework stuff
+use CoreFramework\Factory\ObjectFactory;
+use CoreFramework\Handler\BaseHandler;
+
+/**
+ * A general Handler for raw data from sockets
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class BaseRawDataHandler extends BaseHandler {
+ // Error codes:
+ // - Socket raw data stream errors
+ const SOCKET_ERROR_UNKNOWN = 'unknown_error'; // Unknown error (should not happen)
+ const SOCKET_ERROR_TRANSPORT_ENDPOINT = 'transport_endpoint'; // Transport endpoint has closed
+ const SOCKET_ERROR_INVALID_BASE64_MODULO = 'base64_modulo'; // Length is not modulo 4
+ const SOCKET_ERROR_INVALID_BASE64_MESSAGE = 'base64_message'; // Raw data is not Base64-encoded
+ const SOCKET_ERROR_UNHANDLED = 'unhandled_package'; // Unhandled raw data (not bad)
+ const SOCKET_ERROR_CONNECTION_REFUSED = 'connection_refused'; // The name says it: connection refused
+ const SOCKET_ERROR_CONNECTION_TIMED_OUT = 'connection_timed_out'; // The name says it: connection attempt has timed-out
+ const SOCKET_ERROR_OPERATION_IN_PROGRESS = 'operation_in_progress'; // 'Operation now in progress'
+ const SOCKET_ERROR_OPERATION_ALREADY_PROGRESS = 'operation_already_progress'; // 'Operation already in progress'
+ const SOCKET_ERROR_RESOURCE_UNAVAILABLE = 'resource_unavailable'; // 'Resource temporary unavailable'
+ const SOCKET_ERROR_NO_ROUTE_TO_HOST = 'no_route_to_host'; // The name says it: no route to host
+ const SOCKET_ERROR_CONNECTION_RESET_BY_PEER = 'connection_reset_by_peer'; // Connection reset by peer
+ const SOCKET_ERROR_BROKEN_PIPE = 'broken_pipe'; // Broken pipe
+ const SOCKET_ERROR_PERMISSION_DENIED = 'permission_denied'; // Permission denied
+ const SOCKET_CONNECTED = 'connected'; // Nothing errorous happens, socket is connected
+
+ // - Package errors
+ const PACKAGE_ERROR_INVALID_DATA = 'invalid_data'; // Invalid data in package found
+ const PACKAGE_ERROR_INCOMPLETE_DATA = 'incomplete_data'; // Incomplete data sent (e.g. field is missing)
+ const PACKAGE_ERROR_INVALID_CONTENT = 'invalid_content'; // Content is invalid (e.g. not well-formed)
+ const PACKAGE_ERROR_RECIPIENT_MISMATCH = 'recipient_error'; // Recipient is not us
+ const PACKAGE_LEVEL_CHECK_OKAY = 'checked_package'; // Package is fine
+
+ // Package data
+ const PACKAGE_RAW_DATA = 'raw_data';
+ const PACKAGE_ERROR_CODE = 'error_code';
+
+ // Start/end marker
+ const STREAM_START_MARKER = '[[S]]';
+ const STREAM_END_MARKER = '[[E]]';
+
+ /**
+ * Stacker for raw data
+ */
+ const STACKER_NAME_RAW_DATA = 'raw_data';
+
+ /**
+ * Error code from socket
+ */
+ private $errorCode = -1;
+
+ /**
+ * Protected constructor
+ *
+ * @param $className Name of the class
+ * @return void
+ */
+ protected function __construct ($className) {
+ // Call parent constructor
+ parent::__construct($className);
+
+ // Set error code to 'unknown'
+ $this->setErrorCode(self::SOCKET_ERROR_UNKNOWN);
+
+ // Init stacker instance for processed raw data
+ $stackInstance = ObjectFactory::createObjectByConfiguredName('node_raw_data_stacker_class');
+
+ // Remember this in this package handler
+ $this->setStackInstance($stackInstance);
+
+ // Init stacker
+ $this->initStack();
+ }
+
+ /**
+ * Initializes the stacker for raw data
+ *
+ * @return void
+ */
+ protected function initStack () {
+ $this->getStackInstance()->initStack(self::STACKER_NAME_RAW_DATA);
+ }
+
+ /**
+ * Adds given raw data to the raw data stacker
+ *
+ * @param $rawData raw data from the socket resource
+ * @return void
+ */
+ protected function addRawDataToStacker ($rawData) {
+ /*
+ * Add the deocoded data and error code to the stacker so other classes
+ * (e.g. NetworkPackage) can "pop" it from the stacker.
+ */
+ $this->getStackInstance()->pushNamed(self::STACKER_NAME_RAW_DATA, array(
+ self::PACKAGE_RAW_DATA => $rawData,
+ self::PACKAGE_ERROR_CODE => $this->getErrorCode()
+ ));
+ }
+
+ /**
+ * Checks whether raw data is pending for further processing.
+ *
+ * @return $isPending Whether raw data is pending
+ */
+ public function isRawDataPending () {
+ // Does the stacker have some entries (not empty)?
+ $isPending = (!$this->getStackInstance()->isStackEmpty(self::STACKER_NAME_RAW_DATA));
+
+ // Return it
+ return $isPending;
+ }
+
+ /**
+ * "Getter" for next raw data from the stacker
+ *
+ * @return $rawData Raw data from the stacker
+ */
+ public function getNextRawData () {
+ // "Pop" the raw data from the stacker
+ $rawData = $this->getStackInstance()->popNamed(self::STACKER_NAME_RAW_DATA);
+
+ // And return it
+ return $rawData;
+ }
+
+ /**
+ * Checks whether the 'recipient' field matches our own an universal node
+ * locator.
+ *
+ * @param $packageData Raw package data
+ * @return $matches Whether it matches
+ * @todo This method will be moved to a better place
+ */
+ protected function ifRecipientMatchesOwnUniversalNodeLocator (array $packageData) {
+ // Construct own address first
+ $ownAddress = NodeObjectFactory::createNodeInstance()->determineUniversalNodeLocator();
+
+ // Does it match?
+ $matches = ($ownAddress === $packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]);
+
+ // Return result
+ return $matches;
+ }
+
+ /**
+ * Setter for error code
+ *
+ * @param $errorCode The error code we shall set
+ * @return void
+ */
+ public final function setErrorCode ($errorCode) {
+ $this->errorCode = $errorCode;
+ }
+
+ /**
+ * Getter for error code
+ *
+ * @return $errorCode The error code
+ */
+ public final function getErrorCode () {
+ return $this->errorCode;
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Information\;
+
+// Import application-specific stuff
+use Hub\Information\BaseInfo;
+use Hub\Information\ShareableInfo;
+
+/**
+ * A ??? information class
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+class ???Info extends BaseInfo implements ShareableInfo {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $infoInstance An instance of a ShareableInfo class
+ */
+ public final static function create???Info () {
+ // Get new instance
+ $infoInstance = new ???Info();
+
+ // Return the prepared instance
+ return $infoInstance;
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Information;
+
+// Import application-specific stuff
+use Hub\Generic\BaseHubSystem;
+
+/**
+ * A general Info class
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+class BaseInfo extends BaseHubSystem {
+ /**
+ * Protected constructor
+ *
+ * @param $className Name of the class
+ * @return void
+ */
+ protected function __construct ($className) {
+ // Call parent constructor
+ parent::__construct($className);
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Information\Connection;
+
+// Import application-specific stuff
+use Hub\Information\BaseInfo;
+use Hub\Information\ShareableInfo;
+
+// Import framework stuff
+use CoreFramework\Listener\Listenable;
+use CoreFramework\Registry\Registerable;
+
+/**
+ * A Connection information class
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+class ConnectionInfo extends BaseInfo implements ShareableInfo, Registerable {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $infoInstance An instance of a ShareableInfo class
+ */
+ public final static function createConnectionInfo () {
+ // Get new instance
+ $infoInstance = new ConnectionInfo();
+
+ // Return the prepared instance
+ return $infoInstance;
+ }
+
+ /**
+ * Fills the information class with data from a Listenable instance
+ *
+ * @param $listenerInstance An instance of a Listenable class
+ * @return void
+ */
+ public function fillWithListenerInformation (Listenable $listenerInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']: protocolName=' . $listenerInstance->getProtocolName() . ',listenerInstance=' . $listenerInstance->__toString() . ' - CALLED!');
+
+ // Fill the generic array with several data from the listener:
+ $this->setProtocolName($listenerInstance->getProtocolName());
+ $this->setGenericArrayElement('connection', 'dummy', 'dummy', UniversalNodeLocator::UNL_PART_ADDRESS , $listenerInstance->getListenAddress());
+ $this->setGenericArrayElement('connection', 'dummy', 'dummy', UniversalNodeLocator::UNL_PART_PORT , $listenerInstance->getListenPort());
+
+ // Set listener here
+ $this->setListenerInstance($listenerInstance);
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
+ }
+
+ /**
+ * Fills the information class with data from a ConnectionHelper instance
+ *
+ * @param $helperInstance An instance of a ConnectionHelper class
+ * @return void
+ */
+ public function fillWithConnectionHelperInformation (ConnectionHelper $helperInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']: protocolName=' . $helperInstance->getProtocolName() . ',helperInstance=' . $helperInstance->__toString() . ',socketResource=' . $helperInstance->getSocketResource() . ' - CALLED!');
+
+ // Fill the generic array with several data from the listener:
+ $this->setProtocolName($helperInstance->getProtocolName());
+ $this->setGenericArrayElement('connection', 'dummy', 'dummy', UniversalNodeLocator::UNL_PART_ADDRESS , $helperInstance->getAddress());
+ $this->setGenericArrayElement('connection', 'dummy', 'dummy', UniversalNodeLocator::UNL_PART_PORT , $helperInstance->getConnectionPort());
+
+ // Set helper here
+ $this->setHelperInstance($helperInstance);
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ']: EXIT!');
+ }
+
+ /**
+ * Getter for address
+ *
+ * @return $address Address from shared information
+ */
+ public final function getAddress () {
+ // Return it from generic array
+ return $this->getGenericArrayElement('connection', 'dummy', 'dummy', UniversalNodeLocator::UNL_PART_ADDRESS);
+ }
+
+ /**
+ * Getter for port
+ *
+ * @return $port Port from shared information
+ */
+ public final function getPort () {
+ // Return it from generic array
+ return $this->getGenericArrayElement('connection', 'dummy', 'dummy', UniversalNodeLocator::UNL_PART_PORT);
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Listener\!!!;
+
+// Import application-specific stuff
+use Hub\Listener\BaseListener;
+
+// Import framework stuff
+use CoreFramework\Listener\Listenable;
+
+/**
+ * A ??? listener
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+class ???Listener extends BaseListener implements Listenable {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set the protocol to !!!
+ $this->setProtocolName('!!!');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $listenerInstance An instance a prepared listener class
+ */
+ public final static function create???Listener () {
+ // Get new instance
+ $listenerInstance = new ???Listener();
+
+ // Return the prepared instance
+ return $listenerInstance;
+ }
+
+ /**
+ * Initializes the listener by setting up the required socket server
+ *
+ * @return void
+ * @todo 0% done
+ */
+ public function initListener() {
+ $this->partialStub('Need to implement this method.');
+ }
+
+ /**
+ * "Listens" for incoming network packages
+ *
+ * @return void
+ * @todo 0% done
+ */
+ public function doListen() {
+ $this->partialStub('Need to implement this method.');
+ }
+
+ /**
+ * Checks whether the listener would accept the given package data array
+ *
+ * @param $packageData Raw package data
+ * @return $accepts Whether this listener does accept
+ */
+ public function ifListenerAcceptsPackageData (array $packageData) {
+ $this->partialStub('Need to implement this method.') {
+ }
+
+ /**
+ * Monitors incoming raw data from the handler and transfers it to the
+ * given receiver instance.
+ *
+ * @return void
+ */
+ public function monitorIncomingRawData () {
+ $this->partialStub('Need to implement this method.') {
+ }
+
+ /**
+ * Getter for connection type
+ *
+ * @return $connectionType Connection type for this listener
+ */
+ public function getConnectionType () {
+ $this->partialStub('Need to implement this method.') {
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Listener;
+
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+
+// Import framework stuff
+use CoreFramework\Factory\Connection\ConnectionInfoFactory;
+use CoreFramework\Factory\ObjectFactory;
+use CoreFramework\Factory\Registry\Socket\SocketRegistryFactory;
+use CoreFramework\Generic\UnsupportedOperationException;
+use CoreFramework\Object\BaseFrameworkSystem;
+use CoreFramework\Visitor\Visitable;
+use CoreFramework\Visitor\Visitor;
+
+/**
+ * A general listener class
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class BaseListener extends BaseFrameworkSystem implements Visitable {
+ // Exception code constants
+ const EXCEPTION_SOCKET_ALREADY_REGISTERED = 0xa01;
+ const EXCEPTION_SOCKET_CREATION_FAILED = 0xa02;
+ const EXCEPTION_NO_SOCKET_ERROR = 0xa03;
+ const EXCEPTION_CONNECTION_ALREADY_REGISTERED = 0xa04;
+ const EXCEPTION_UNEXPECTED_PACKAGE_STATUS = 0xa05;
+ const EXCEPTION_UNSUPPORTED_PACKAGE_CODE_HANDLER = 0xa06;
+ const EXCEPTION_FINAL_CHUNK_VERIFICATION = 0xa07;
+ const EXCEPTION_INVALID_DATA_CHECKSUM = 0xa08;
+
+ /**
+ * Address (IP mostly) we shall listen on
+ */
+ private $listenAddress = '0.0.0.0'; // This is the default and listens on all interfaces
+
+ /**
+ * Port we shall listen on (or wait for incoming data)
+ */
+ private $listenPort = 0; // This port MUST be changed by your application
+
+ /**
+ * Whether we are in blocking or non-blocking mode (default: non-blocking
+ */
+ private $blockingMode = false;
+
+ /**
+ * A peer pool instance
+ */
+ private $poolInstance = NULL;
+
+ /**
+ * Protected constructor
+ *
+ * @param $className Name of the class
+ * @return void
+ */
+ protected function __construct ($className) {
+ // Call parent constructor
+ parent::__construct($className);
+ }
+
+ /**
+ * Checks whether the given socket resource is a server socket
+ *
+ * @param $socketResource A valid socket resource
+ * @return $isServerSocket Whether the socket resource is a server socket
+ */
+ protected function isServerSocketResource ($socketResource) {
+ // Check it
+ $isServerSocket = ((is_resource($socketResource)) && (!@socket_getpeername($socketResource, $peerName)));
+
+ // We need to clear the error here if it is a resource
+ if ($isServerSocket === true) {
+ // Clear the error
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('socketResource[]=' . gettype($socketResource));
+ socket_clear_error($socketResource);
+ } // END - if
+
+ // Check peer name, it must be empty
+ $isServerSocket = (($isServerSocket) && (empty($peerName)));
+
+ // Return result
+ return $isServerSocket;
+ }
+
+ /**
+ * Setter for listen address
+ *
+ * @param $listenAddress The address this listener should listen on
+ * @return void
+ */
+ protected final function setListenAddress ($listenAddress) {
+ $this->listenAddress = (string) $listenAddress;
+ }
+
+ /**
+ * Getter for listen address
+ *
+ * @return $listenAddress The address this listener should listen on
+ */
+ public final function getListenAddress () {
+ return $this->listenAddress;
+ }
+
+ /**
+ * Setter for listen port
+ *
+ * @param $listenPort The port this listener should listen on
+ * @return void
+ */
+ protected final function setListenPort ($listenPort) {
+ $this->listenPort = (int) $listenPort;
+ }
+
+ /**
+ * Getter for listen port
+ *
+ * @return $listenPort The port this listener should listen on
+ */
+ public final function getListenPort () {
+ return $this->listenPort;
+ }
+
+ /**
+ * "Setter" to set listen address from configuration entry
+ *
+ * @param $configEntry The configuration entry holding our listen address
+ * @return void
+ */
+ public final function setListenAddressByConfiguration ($configEntry) {
+ $this->setListenAddress($this->getConfigInstance()->getConfigEntry($configEntry));
+ }
+
+ /**
+ * "Setter" to set listen port from configuration entry
+ *
+ * @param $configEntry The configuration entry holding our listen port
+ * @return void
+ */
+ public final function setListenPortByConfiguration ($configEntry) {
+ $this->setListenPort($this->getConfigInstance()->getConfigEntry($configEntry));
+ }
+
+ /**
+ * Setter for blocking-mode
+ *
+ * @param $blockingMode Whether blocking-mode is disabled (default) or enabled
+ * @return void
+ */
+ protected final function setBlockingMode ($blockingMode) {
+ $this->blockingMode = (boolean) $blockingMode;
+ }
+
+ /**
+ * Checks whether blocking-mode is enabled or disabled
+ *
+ * @return $blockingMode Whether blocking mode is disabled or enabled
+ */
+ public final function isBlockingModeEnabled () {
+ return $this->blockingMode;
+ }
+
+ /**
+ * Setter for peer pool instance
+ *
+ * @param $poolInstance The peer pool instance we shall set
+ * @return void
+ */
+ protected final function setPoolInstance (PoolablePeer $poolInstance) {
+ $this->poolInstance = $poolInstance;
+ }
+
+ /**
+ * Getter for peer pool instance
+ *
+ * @return $poolInstance The peer pool instance we shall set
+ */
+ public final function getPoolInstance () {
+ return $this->poolInstance;
+ }
+
+ /**
+ * Getter for connection type
+ *
+ * @return $connectionType Connection type for this listener
+ */
+ public final function getConnectionType () {
+ // Wrap the real getter
+ return $this->getProtocolName();
+ }
+
+ /**
+ * Registeres the given socket resource for "this" listener instance. This
+ * will be done in a seperate class to allow package writers to use it
+ * again.
+ *
+ * @param $socketResource A valid server socket resource
+ * @return void
+ * @throws InvalidServerSocketException If the given resource is no server socket
+ * @throws SocketAlreadyRegisteredException If the given resource is already registered
+ */
+ protected function registerServerSocketResource ($socketResource) {
+ // First check if it is valid
+ if (!$this->isServerSocketResource($socketResource)) {
+ // No server socket
+ throw new InvalidServerSocketException(array($this, $socketResource), self::EXCEPTION_INVALID_SOCKET);
+ } elseif ($this->isServerSocketRegistered($socketResource)) {
+ // Already registered
+ throw new SocketAlreadyRegisteredException($this, self::EXCEPTION_SOCKET_ALREADY_REGISTERED);
+ }
+
+ // Get a socket registry instance (singleton)
+ $registryInstance = SocketRegistryFactory::createSocketRegistryInstance();
+
+ // Get a connection info instance
+ $infoInstance = ConnectionInfoFactory::createConnectionInfoInstance($this->getProtocolName(), 'listener');
+
+ // Will the info instance with listener data
+ $infoInstance->fillWithListenerInformation($this);
+
+ // Register the socket
+ $registryInstance->registerSocket($infoInstance, $socketResource);
+
+ // And set it here
+ $this->setSocketResource($socketResource);
+ }
+
+ /**
+ * Checks whether given socket resource is registered in socket registry
+ *
+ * @param $socketResource A valid server socket resource
+ * @return $isRegistered Whether given server socket is registered
+ */
+ protected function isServerSocketRegistered ($socketResource) {
+ // Get a socket registry instance (singleton)
+ $registryInstance = SocketRegistryFactory::createSocketRegistryInstance();
+
+ // Get a connection info instance
+ $infoInstance = ConnectionInfoFactory::createConnectionInfoInstance($this->getProtocolName(), 'listener');
+
+ // Will the info instance with listener data
+ $infoInstance->fillWithListenerInformation($this);
+
+ // Check it
+ $isRegistered = $registryInstance->isSocketRegistered($infoInstance, $socketResource);
+
+ // Return result
+ return $isRegistered;
+ }
+
+ /**
+ * Accepts the visitor to process the visit "request"
+ *
+ * @param $visitorInstance An instance of a Visitor class
+ * @return void
+ */
+ public function accept (Visitor $visitorInstance) {
+ // Debug message
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getProtocolName()) . '-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: ' . $visitorInstance->__toString() . ' has visited ' . $this->__toString() . ' - CALLED!');
+
+ // Visit this listener
+ $visitorInstance->visitListener($this);
+
+ // Visit the pool if set
+ if ($this->getPoolInstance() instanceof Poolable) {
+ $this->getPoolInstance()->accept($visitorInstance);
+ } // END - if
+
+ // Debug message
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getProtocolName()) . '-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: ' . $visitorInstance->__toString() . ' has visited ' . $this->__toString() . ' - EXIT!');
+ }
+
+ /**
+ * Monitors incoming raw data from the handler and transfers it to the
+ * given receiver instance. This method should not be called, please call
+ * the decorator's version instead to separator node/client traffic.
+ *
+ * @return void
+ * @throws UnsupportedOperatorException If this method is called by a mistake
+ */
+ public function monitorIncomingRawData () {
+ throw new UnsupportedOperationException(array($this, __FUNCTION__), self::EXCEPTION_UNSPPORTED_OPERATION);
+ }
+
+ /**
+ * Constructs a callable method name from given socket error code. If the
+ * method is not found, a generic one is used.
+ *
+ * @param $errorCode Error code from socket_last_error()
+ * @return $handlerName Call-back method name for the error handler
+ * @throws UnsupportedSocketErrorHandlerException If the error handler is not implemented
+ */
+ protected function getSocketErrorHandlerFromCode ($errorCode) {
+ // Create a name from translated error code
+ $handlerName = 'socketError' . self::convertToClassName($this->translateSocketErrorCodeToName($errorCode)) . 'Handler';
+
+ // Is the call-back method there?
+ if (!method_exists($this, $handlerName)) {
+ // Please implement this
+ throw new UnsupportedSocketErrorHandlerException(array($this, $handlerName, $errorCode), BaseConnectionHelper::EXCEPTION_UNSUPPORTED_ERROR_HANDLER);
+ } // END - if
+
+ // Return it
+ return $handlerName;
+ }
+
+ /**
+ * Translates socket error codes into our own internal names which can be
+ * used for call-backs.
+ *
+ * @param $errorCode The error code from socket_last_error() to be translated
+ * @return $errorName The translated name (all lower-case, with underlines)
+ */
+ public function translateSocketErrorCodeToName ($errorCode) {
+ // Nothing bad happened by default
+ $errorName = BaseRawDataHandler::SOCKET_CONNECTED;
+
+ // Is the code a number, then we have to change it
+ switch ($errorCode) {
+ case 0: // Silently ignored, the socket is connected
+ break;
+
+ case 11: // "Resource temporary unavailable"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_RESOURCE_UNAVAILABLE;
+ break;
+
+ case 13: // "Permission denied"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_PERMISSION_DENIED;
+ break;
+
+ case 32: // "Broken pipe"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_BROKEN_PIPE;
+ break;
+
+ case 104: // "Connection reset by peer"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_CONNECTION_RESET_BY_PEER;
+ break;
+
+ case 107: // "Transport end-point not connected"
+ case 134: // On some (?) systems for 'transport end-point not connected'
+ // @TODO On some systems it is 134, on some 107?
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_TRANSPORT_ENDPOINT;
+ break;
+
+ case 110: // "Connection timed out"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_CONNECTION_TIMED_OUT;
+ break;
+
+ case 111: // "Connection refused"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_CONNECTION_REFUSED;
+ break;
+
+ case 113: // "No route to host"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_NO_ROUTE_TO_HOST;
+ break;
+
+ case 114: // "Operation already in progress"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_OPERATION_ALREADY_PROGRESS;
+ break;
+
+ case 115: // "Operation now in progress"
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_OPERATION_IN_PROGRESS;
+ break;
+
+ default: // Everything else <> 0
+ // Unhandled error code detected, so first debug it because we may want to handle it like the others
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-HUB[' . __METHOD__ . ':' . __LINE__ . '] UNKNOWN ERROR CODE = ' . $errorCode . ', MESSAGE = ' . socket_strerror($errorCode));
+
+ // Change it only in this class
+ $errorName = BaseRawDataHandler::SOCKET_ERROR_UNKNOWN;
+ break;
+ }
+
+ // Return translated name
+ return $errorName;
+ }
+
+ /**
+ * Shuts down a given socket resource. This method does only ease calling
+ * the right visitor.
+ *
+ * @param $socketResource A valid socket resource
+ * @return void
+ */
+ public function shutdownSocket ($socketResource) {
+ // Debug message
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-SYSTEM: Shutting down socket resource ' . $socketResource . ' with state ' . $this->getPrintableState() . ' ...');
+
+ // Set socket resource
+ $this->setSocketResource($socketResource);
+
+ // Get a visitor instance
+ $visitorInstance = ObjectFactory::createObjectByConfiguredName('shutdown_socket_visitor_class');
+
+ // Debug output
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-SYSTEM:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString());
+
+ // Call the visitor
+ $this->accept($visitorInstance);
+ }
+
+ /**
+ * Half-shuts down a given socket resource. This method does only ease calling
+ * an other visitor than shutdownSocket() does.
+ *
+ * @param $socketResource A valid socket resource
+ * @return void
+ */
+ public function halfShutdownSocket ($socketResource) {
+ // Debug message
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-SYSTEM: Half-shutting down socket resource ' . $socketResource . ' with state ' . $this->getPrintableState() . ' ...');
+
+ // Set socket resource
+ $this->setSocketResource($socketResource);
+
+ // Get a visitor instance
+ $visitorInstance = ObjectFactory::createObjectByConfiguredName('half_shutdown_socket_visitor_class');
+
+ // Debug output
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-SYSTEM:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString());
+
+ // Call the visitor
+ $this->accept($visitorInstance);
+ }
+
+ // ************************************************************************
+ // Socket error handler call-back methods
+ // ************************************************************************
+
+ /**
+ * Handles socket error 'permission denied', but does not clear it for
+ * later debugging purposes.
+ *
+ * @param $socketResource A valid socket resource
+ * @param $socketData A valid socket data array (0 = IP/file name, 1 = port)
+ * @return void
+ * @throws SocketBindingException The socket could not be bind to
+ */
+ protected function socketErrorPermissionDeniedHandler ($socketResource, array $socketData) {
+ // Get socket error code for verification
+ $socketError = socket_last_error($socketResource);
+
+ // Get error message
+ $errorMessage = socket_strerror($socketError);
+
+ // Shutdown this socket
+ $this->shutdownSocket($socketResource);
+
+ // Throw it again
+ throw new SocketBindingException(array($this, $socketData, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
+ }
+
+ /**
+ * "Listens" for incoming network packages
+ *
+ * @param $peerSuffix Suffix for peer name (e.g. :0 for TCP(/UDP?) connections)
+ * @return void
+ * @throws InvalidSocketException If an invalid socket resource has been found
+ */
+ protected function doListenSocketSelect ($peerSuffix) {
+ // Check on all instances
+ assert($this->getPoolInstance() instanceof Poolable);
+ assert(is_resource($this->getSocketResource()));
+
+ // Get all readers
+ $readers = $this->getPoolInstance()->getAllSingleSockets();
+ $writers = array();
+ $excepts = array();
+
+ // Check if we have some peers left
+ $left = socket_select(
+ $readers,
+ $writers,
+ $excepts,
+ 0,
+ 150
+ );
+
+ // Some new peers found?
+ if ($left < 1) {
+ // Debug message
+ //* EXTREME-NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('TCP-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: left=' . $left . ',serverSocket=' . $this->getSocketResource() . ',readers=' . print_r($readers, true));
+
+ // Nothing new found
+ return;
+ } // END - if
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('TCP-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: serverSocket=' . $this->getSocketResource() . ',readers=' . print_r($readers, true));
+
+ // Do we have changed peers?
+ if (in_array($this->getSocketResource(), $readers)) {
+ /*
+ * Then accept it, if this socket is set to non-blocking IO and the
+ * connection is NOT sending any data, socket_read() may throw
+ * error 11 (Resource temporary unavailable). This really nasty
+ * because if you have blocking IO socket_read() will wait and wait
+ * and wait ...
+ */
+ $newSocket = socket_accept($this->getSocketResource());
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('TCP-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: newSocket=' . $newSocket . ',serverSocket=' .$this->getSocketResource());
+
+ // Array for timeout settings
+ $options = array(
+ // Seconds
+ 'sec' => $this->getConfigInstance()->getConfigEntry('tcp_socket_accept_wait_sec'),
+ // Milliseconds
+ 'usec' => $this->getConfigInstance()->getConfigEntry('tcp_socket_accept_wait_usec')
+ );
+
+ // Set timeout to configured seconds
+ // @TODO Does this work on Windozer boxes???
+ if (!socket_set_option($newSocket, SOL_SOCKET, SO_RCVTIMEO, $options)) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $newSocket, array('0.0.0.0', '0'));
+ } // END - if
+
+ // Output result (only for debugging!)
+ /*
+ $option = socket_get_option($newSocket, SOL_SOCKET, SO_RCVTIMEO);
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SO_RCVTIMEO[' . gettype($option) . ']=' . print_r($option, true));
+ */
+
+ // Enable SO_OOBINLINE
+ if (!socket_set_option($newSocket, SOL_SOCKET, SO_OOBINLINE ,1)) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $newSocket, array('0.0.0.0', '0'));
+ } // END - if
+
+ // Set non-blocking
+ if (!socket_set_nonblock($newSocket)) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $newSocket, array('0.0.0.0', '0'));
+ } // END - if
+
+ // Add it to the peers
+ $this->getPoolInstance()->addPeer($newSocket, BaseConnectionHelper::CONNECTION_TYPE_INCOMING);
+
+ // Get peer name
+ if (!socket_getpeername($newSocket, $peerName)) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $newSocket, array('0.0.0.0', '0'));
+ } // END - if
+
+ // Get node instance
+ $nodeInstance = NodeObjectFactory::createNodeInstance();
+
+ // Create a faked package data array
+ $packageData = array(
+ NetworkPackage::PACKAGE_DATA_SENDER => $peerName . $peerSuffix,
+ NetworkPackage::PACKAGE_DATA_RECIPIENT => $nodeInstance->getSessionId(),
+ NetworkPackage::PACKAGE_DATA_STATUS => NetworkPackage::PACKAGE_STATUS_FAKED
+ );
+
+ // Get a connection info instance
+ $infoInstance = ConnectionInfoFactory::createConnectionInfoInstance($this->getProtocolName(), 'listener');
+
+ // Will the info instance with listener data
+ $infoInstance->fillWithListenerInformation($this);
+
+ // Get a socket registry
+ $registryInstance = SocketRegistryFactory::createSocketRegistryInstance();
+
+ // Register the socket with the registry and with the faked array
+ $registryInstance->registerSocket($infoInstance, $newSocket, $packageData);
+ } // END - if
+
+ // Do we have to rewind?
+ if (!$this->getIteratorInstance()->valid()) {
+ // Rewind the list
+ $this->getIteratorInstance()->rewind();
+ } // END - if
+
+ // Get the current value
+ $currentSocket = $this->getIteratorInstance()->current();
+
+ // Handle it here, if not main server socket
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('TCP-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: currentSocket=' . $currentSocket[BasePool::SOCKET_ARRAY_RESOURCE] . ',type=' . $currentSocket[BasePool::SOCKET_ARRAY_CONN_TYPE] . ',serverSocket=' . $this->getSocketResource());
+ if (($currentSocket[BasePool::SOCKET_ARRAY_CONN_TYPE] != BaseConnectionHelper::CONNECTION_TYPE_SERVER) && ($currentSocket[BasePool::SOCKET_ARRAY_RESOURCE] != $this->getSocketResource())) {
+ // ... or else it will raise warnings like 'Transport endpoint is not connected'
+ $this->getHandlerInstance()->processRawDataFromResource($currentSocket);
+ } // END - if
+
+ // Advance to next entry. This should be the last line.
+ $this->getIteratorInstance()->next();
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Listener;
+
+// Import framework stuff
+use CoreFramework\Generic\BaseDecorator;
+use CoreFramework\Visitor\Visitable;
+use CoreFramework\Visitor\Visitor;
+
+/**
+ * A general decorator for listeners to communicate to hubs
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class BaseListenerDecorator extends BaseDecorator implements Visitable {
+ /**
+ * Listener type
+ */
+ private $listenerType = 'invalid';
+
+ /**
+ * Protected constructor
+ *
+ * @param $className Name of the class
+ * @return void
+ */
+ protected function __construct ($className) {
+ // Call parent constructor
+ parent::__construct($className);
+ }
+
+ /**
+ * Getter for listen address
+ *
+ * @return $listenAddress The address this listener should listen on
+ */
+ public final function getListenAddress () {
+ return $this->getListenerInstance()->getListenAddress();
+ }
+
+ /**
+ * Getter for listen port
+ *
+ * @return $listenPort The port this listener should listen on
+ */
+ public final function getListenPort () {
+ return $this->getListenerInstance()->getListenPort();
+ }
+
+ /**
+ * Getter for connection type
+ *
+ * @return $connectionType Connection type for this listener
+ */
+ public final function getConnectionType () {
+ return $this->getListenerInstance()->getConnectionType();
+ }
+
+ /**
+ * Accepts the visitor to process the visit "request"
+ *
+ * @param $visitorInstance An instance of a Visitor class
+ * @return void
+ */
+ public function accept (Visitor $visitorInstance) {
+ // Visit this decorator
+ $visitorInstance->visitDecorator($this);
+
+ // Visit the covered class
+ $visitorInstance->visitListener($this->getListenerInstance());
+ }
+
+ /**
+ * Getter for listener type.
+ *
+ * @return $listenerType The listener's type (hub/peer)
+ */
+ public final function getListenerType () {
+ return $this->listenerType;
+ }
+
+ /**
+ * Setter for listener type.
+ *
+ * @param $listenerType The listener's type (hub/peer)
+ * @return void
+ */
+ protected final function setListenerType ($listenerType) {
+ $this->listenerType = $listenerType;
+ }
+
+ /**
+ * Getter for peer pool instance
+ *
+ * @return $poolInstance A peer pool instance
+ */
+ public final function getPoolInstance () {
+ return $this->getListenerInstance()->getPoolInstance();
+ }
+
+ /**
+ * Monitors incoming raw data from the handler and transfers it to the
+ * given receiver instance.
+ *
+ * @return void
+ */
+ public function monitorIncomingRawData () {
+ // Get the handler instance
+ $handlerInstance = $this->getListenerInstance()->getHandlerInstance();
+
+ /*
+ * Does the deocorated listener (or even a decorator again) have a
+ * handler assigned? Remember that a handler will hold all incoming raw
+ * data and not a listener.
+ */
+ if (!$handlerInstance instanceof Networkable) {
+ // Skip this silently for now. Later on, this will become mandatory!
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('No handler assigned to this listener decorator. this=' . $this->__toString() . ', listenerInstance=' . $this->getListenerInstance()->__toString());
+ return;
+ } // END - if
+
+ // Does the handler have some decoded data pending?
+ if (!$handlerInstance->isRawDataPending()) {
+ // No data is pending so skip further code silently
+ return;
+ } // END - if
+
+ // Get receiver (network package) instance
+ $receiverInstance = NetworkPackageFactory::createNetworkPackageInstance();
+
+ /*
+ * There is some decoded data waiting. The receiver instance is an
+ * abstract network package (which can be received and sent out) so
+ * handle the decoded data over. At this moment it is not needed to
+ * know if the decoded data origins from a TCP or UDP connection so it
+ * can just be passed over to the network package receiver.
+ */
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-LISTENER-DECORATOR[' . __METHOD__ . ':' . __LINE__ . '] Going to handle over some raw data to receiver instance (' . $receiverInstance->__toString() . ') ...');
+ $receiverInstance->addRawDataToIncomingStack($handlerInstance);
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Listener\Socket;
+
+// Import application-specific stuff
+use Hub\Listener\BaseListener;
+
+// Import framework stuff
+use CoreFramework\Bootstrap\FrameworkBootstrap;
+use CoreFramework\Factory\ObjectFactory;
+use CoreFramework\Listener\Listenable;
+
+/**
+ * A file-based socket listener
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+class SocketFileListener extends BaseListener implements Listenable {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set the protocol to file
+ $this->setProtocolName('file');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $listenerInstance An instance a prepared listener class
+ */
+ public final static function createSocketFileListener () {
+ // Get new instance
+ $listenerInstance = new SocketFileListener();
+
+ // Return the prepared instance
+ return $listenerInstance;
+ }
+
+ /**
+ * Initializes the listener by setting up the required socket server
+ *
+ * @return void
+ */
+ public function initListener() {
+ // Init socket
+ $mainSocket = socket_create(AF_UNIX, SOCK_STREAM, 0);
+
+ // Is the socket resource valid?
+ if (!is_resource($mainSocket)) {
+ // Something bad happened
+ throw new InvalidSocketException(array($this, $mainSocket), BaseListener::EXCEPTION_INVALID_SOCKET);
+ } // END - if
+
+ // Get socket error code for verification
+ $socketError = socket_last_error($mainSocket);
+
+ // Check if there was an error else
+ if ($socketError > 0) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array('null', '0'));
+ } // END - if
+
+ // Create file name
+ $socketFile = self::createTempPathForFile($this->getConfigInstance()->getConfigEntry('ipc_socket_file_name'));
+
+ // Debug message
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: socketFile=' . $socketFile . ' ...');
+
+ // File name must not be empty
+ assert(!empty($socketFile));
+
+ // Is the file there?
+ if ((FrameworkBootstrap::isReachableFilePath($socketFile)) && (file_exists($socketFile))) {
+ // Old socket found
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: WARNING: Old socket at ' . $socketFile . ' found. Will not start.');
+
+ // Shutdown this socket
+ $this->shutdownSocket($mainSocket);
+
+ // Quit here
+ exit;
+ } // END - if
+
+ // Debug message
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Binding to ' . $socketFile . ' ...');
+
+ // Try to bind to it
+ if (!socket_bind($mainSocket, $socketFile)) {
+ // Handle error here
+ $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array($socketFile, '0'));
+ /*
+ // Get socket error code for verification
+ $socketError = socket_last_error($mainSocket);
+
+ // Get error message
+ $errorMessage = socket_strerror($socketError);
+
+ // Shutdown this socket
+ $this->shutdownSocket($mainSocket);
+
+ // And throw again
+ throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
+ */
+ } // END - if
+
+ // Start listen for connections
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Listening for connections.');
+ if (!socket_listen($mainSocket)) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array($socketFile, '0'));
+ /*
+ // Get socket error code for verification
+ $socketError = socket_last_error($mainSocket);
+
+ // Get error message
+ $errorMessage = socket_strerror($socketError);
+
+ // Shutdown this socket
+ $this->shutdownSocket($mainSocket);
+
+ // And throw again
+ throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
+ */
+ } // END - if
+
+ // Now, we want non-blocking mode
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Setting non-blocking mode.');
+ if (!socket_set_nonblock($mainSocket)) {
+ // Handle this socket error with a faked recipientData array
+ $this->handleSocketError(__METHOD__, __LINE__, $mainSocket, array($socketFile, '0'));
+ /*
+ // Get socket error code for verification
+ $socketError = socket_last_error($mainSocket);
+
+ // Get error message
+ $errorMessage = socket_strerror($socketError);
+
+ // Shutdown this socket
+ $this->shutdownSocket($mainSocket);
+
+ // And throw again
+ throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
+ */
+ } // END - if
+
+ // Set the main socket
+ $this->registerServerSocketResource($mainSocket);
+
+ // Initialize the peer pool instance
+ $poolInstance = ObjectFactory::createObjectByConfiguredName('application_pool_class', array($this));
+
+ // Add main socket
+ $poolInstance->addPeer($mainSocket, BaseConnectionHelper::CONNECTION_TYPE_SERVER);
+
+ // And add it to this listener
+ $this->setPoolInstance($poolInstance);
+
+ // Initialize iterator for listening on packages
+ $iteratorInstance = ObjectFactory::createObjectByConfiguredName('socket_listen_iterator_class', array($poolInstance->getPoolEntriesInstance()));
+
+ // Rewind it and remember it in this class
+ $iteratorInstance->rewind();
+ $this->setIteratorInstance($iteratorInstance);
+
+ // Initialize the raw data handler
+ $handlerInstance = ObjectFactory::createObjectByConfiguredName('socket_raw_data_handler_class');
+
+ // Set it in this class
+ $this->setHandlerInstance($handlerInstance);
+
+ // Output message
+ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-FILE-LISTENER[' . __METHOD__ . ':' . __LINE__ . ']: Socket listener now ready on socket ' . $socketFile . ' for service.');
+ }
+
+ /**
+ * "Listens" for incoming network packages
+ *
+ * @return void
+ */
+ public function doListen() {
+ // Call super method
+ $this->doListenSocketSelect('');
+ }
+
+ /**
+ * Checks whether the listener would accept the given package data array
+ *
+ * @param $packageData Raw package data
+ * @return $accepts Whether this listener does accept
+ */
+ public function ifListenerAcceptsPackageData (array $packageData) {
+ $this->partialStub('Need to implement this method.');
+ }
+
+ /**
+ * Monitors incoming raw data from the handler and transfers it to the
+ * given receiver instance.
+ *
+ * @return void
+ */
+ public function monitorIncomingRawData () {
+ $this->partialStub('Need to implement this method.');
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Listener\Socket;
+
+// Import framework stuff
+use CoreFramework\Listener\Listenable;
+
+/**
+ * A decorator for the SocketFileListener to communicate to hubs
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class SocketFileListenerDecorator extends BaseListenerDecorator implements Listenable {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set listener type and protocol name
+ $this->setListenerType('hub');
+ $this->setProtocolName('tcp');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @param $listenerInstance A Listener instance
+ * @return $decoratorInstance An instance a prepared listener decorator class
+ */
+ public static final function createSocketFileListenerDecorator (Listenable $listenerInstance) {
+ // Get new instance
+ $decoratorInstance = new SocketFileListenerDecorator();
+
+ // Set the application instance
+ $decoratorInstance->setListenerInstance($listenerInstance);
+
+ // Return the prepared instance
+ return $decoratorInstance;
+ }
+
+ /**
+ * Initializes the listener by setting up the required socket server
+ *
+ * @return void
+ */
+ public function initListener () {
+ $this->partialStub('WARNING: This method should not be called.');
+ }
+
+ /**
+ * "Listens" for incoming network packages
+ *
+ * @return void
+ */
+ public function doListen () {
+ // Handle generic TCP package
+ $this->getListenerInstance()->doListen();
+
+ // Handle hub TCP package
+ $this->partialStub('Need to handle hub TCP package.');
+ }
+
+ /**
+ * Checks whether the listener would accept the given package data array
+ *
+ * @param $packageData Raw package data
+ * @return $accepts Whether this listener does accept
+ */
+ public function ifListenerAcceptsPackageData (array $packageData) {
+ // Get a tags instance
+ $tagsInstance = PackageTagsFactory::createPackageTagsInstance();
+
+ // So is the package accepted with this listener?
+ $accepts = $tagsInstance->ifPackageDataIsAcceptedByListener($packageData, $this);
+
+ // Return the result
+ return $accepts;
+ }
+
+}
use Hub\Helper\Connection\BaseConnectionHelper;
use Hub\Helper\Connection\ConnectionHelper;
use Hub\Helper\HubHelper;
+use Hub\Information\ShareableInfo;
use Hub\Network\Receive\Receivable;
use Hub\Tools\HubTools;
use CoreFramework\Factory\Connection\ConnectionInfoFactory;
use CoreFramework\Factory\ObjectFactory;
use CoreFramework\Factory\Registry\Socket\SocketRegistryFactory;
-use CoreFramework\Information\ShareableInfo;
use CoreFramework\Registry\Registry;
use CoreFramework\Registry\Registerable;
use CoreFramework\Visitor\Visitable;
// Import application-specific stuff
use Hub\Pool\BasePool;
+use Hub\Pool\Poolable;
// Import framework stuff
use CoreFramework\Listener\Listenable;
-use CoreFramework\Pool\Poolable;
/**
*
// Import application-specific stuff
use Hub\Helper\Node\NodeHelper;
use Hub\Pool\BasePool;
+use Hub\Pool\Poolable;
// Import framework stuff
use CoreFramework\Factory\ObjectFactory;
use CoreFramework\Listener\Listenable;
-use CoreFramework\Pool\Poolable;
/**
* A default listener pool
// Import application-specific stuff
use Hub\Pool\BasePool;
+use Hub\Pool\Poolable;
// Import framework stuff
use CoreFramework\Listener\Listenable;
-use CoreFramework\Pool\Poolable;
/**
* A default peer pool class
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Registry\Socket;
+
+// Import application-specific stuff
+use Hub\Information\ShareableInfo;
+
+// Import framework stuff
+use CoreFramework\Factory\ObjectFactory;
+use CoreFramework\Listener\Listenable;
+use CoreFramework\Registry\BaseRegistry;
+use CoreFramework\Registry\Register;
+use Hub\Registry\Socket\RegisterableSocket;
+
+/**
+ * A Socket registry
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class SocketRegistry extends BaseRegistry implements Register, RegisterableSocket {
+ // Exception constants
+ const SOCKET_NOT_REGISTERED = 0xd200;
+
+ /**
+ * Instance of this class
+ */
+ private static $registryInstance = NULL;
+
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+ }
+
+ /**
+ * Creates a singleton instance of this registry class
+ *
+ * @return $registryInstance An instance of this class
+ */
+ public static final function createSocketRegistry () {
+ // Is an instance there?
+ if (is_null(self::$registryInstance)) {
+ // Not yet, so create one
+ self::$registryInstance = new SocketRegistry();
+ } // END - if
+
+ // Return the instance
+ return self::$registryInstance;
+ }
+
+ /**
+ * "Getter" to get a string respresentation for a key for the sub-registry
+ * in this format: class:type:port
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @return $key A string representation of the socket for the registry
+ */
+ private function getSubRegistryKey (ShareableInfo $infoInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: infoInstance=' . $infoInstance->__toString() . ' - CALLED!');
+
+ // Get address and port
+ $address = $infoInstance->getAddress();
+ $port = $infoInstance->getPort();
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: address=' . $address . ',port=' . $port);
+
+ // Get connection type and port number and add both together
+ $key = sprintf('%s:%s:%s:%s',
+ $infoInstance->__toString(),
+ $infoInstance->getProtocolName(),
+ $address,
+ $port
+ );
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ' - EXIT!');
+
+ // Return resulting key
+ return $key;
+ }
+
+ /**
+ * "Getter" to get a string respresentation of the listener
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @return $key A string representation of the listener for the registry
+ */
+ private function getRegistryKeyFromInfo (ShareableInfo $infoInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: this=' . $this->__toString() . ',infoInstance=' . $infoInstance->__toString() . ' - CALLED!');
+
+ // Get the key
+ $key = $infoInstance->getProtocolName();
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ' - EXIT!');
+
+ // Return resulting key
+ return $key;
+ }
+
+ /**
+ * Checks whether the shared connection info is registered
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @return $isRegistered Whether the listener is registered
+ */
+ private function isInfoRegistered (ShareableInfo $infoInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:info=' . $infoInstance->getProtocolName() . ' - CALLED!');
+
+ // Get the key
+ $key = $this->getRegistryKeyFromInfo($infoInstance);
+
+ // Determine it
+ $isRegistered = $this->instanceExists($key);
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:info=' . $infoInstance->getProtocolName() . ',isRegistered=' . intval($isRegistered) . ' - EXIT!');
+
+ // Return result
+ return $isRegistered;
+ }
+
+ /**
+ * Checks whether given socket resource is registered. If $socketResource is
+ * FALSE only the instance will be checked.
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @param $socketResource A valid socket resource
+ * @return $isRegistered Whether the given socket resource is registered
+ */
+ public function isSocketRegistered (ShareableInfo $infoInstance, $socketResource) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:info=' . $infoInstance->getProtocolName() . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ' - CALLED!');
+
+ // Default is not registered
+ $isRegistered = FALSE;
+
+ // First, check for the instance, there can be only once
+ if ($this->isInfoRegistered($infoInstance)) {
+ // That one is found so "get" a registry key from it
+ $key = $this->getRegistryKeyFromInfo($infoInstance);
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: this=' . $this->__toString() . ',info=' . $infoInstance->getProtocolName() . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ',key=' . $key . ' - Trying to get instance ...');
+
+ // Get the registry
+ $registryInstance = $this->getInstance($key);
+
+ // "Get" a key for the socket
+ $socketKey = $this->getSubRegistryKey($infoInstance);
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: this=' . $this->__toString() . ',info=' . $infoInstance->getProtocolName() . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ',key=' . $key . ',socketKey=' . $socketKey . ' - Checking existence ...');
+
+ // Is it there?
+ if ($registryInstance->instanceExists($socketKey)) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: Found instance for socketKey=' . $socketKey . ':' . $registryInstance->getInstance($socketKey));
+
+ // Get the instance
+ $registeredInstance = $registryInstance->getInstance($socketKey);
+
+ // Is it SocketContainer and same socket?
+ $isRegistered = (($registeredInstance instanceof SocketContainer) && ($registeredInstance->ifSocketResourceMatches($socketResource)));
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: Final result: isRegistered(' . $socketResource . ')=' . intval($isRegistered));
+ } // END - if
+ } // END - if
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:info=' . $infoInstance->getProtocolName() . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ',isRegistered=' . intval($isRegistered) . ' - EXIT!');
+
+ // Return the result
+ return $isRegistered;
+ }
+
+ /**
+ * Registeres given socket for listener or throws an exception if it is already registered
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @param $socketResource A valid socket resource
+ * @param $packageData Optional raw package data
+ * @throws SocketAlreadyRegisteredException If the given socket is already registered
+ * @return void
+ */
+ public function registerSocket (ShareableInfo $infoInstance, $socketResource, array $packageData = array()) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:info=' . $infoInstance->getProtocolName() . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ' - CALLED!');
+
+ // Is the socket already registered?
+ if ($this->isSocketRegistered($infoInstance, $socketResource)) {
+ // Throw the exception
+ throw new SocketAlreadyRegisteredException(array($infoInstance, $socketResource), BaseListener::EXCEPTION_SOCKET_ALREADY_REGISTERED);
+ } // END - if
+
+ // Does the instance exist?
+ if (!$this->isInfoRegistered($infoInstance)) {
+ // No, not found so we create a sub registry (not needed to configure!)
+ $registryInstance = SubRegistry::createSubRegistry();
+
+ // Now we can create the sub-registry for this info
+ $this->addInstance($this->getRegistryKeyFromInfo($infoInstance), $registryInstance);
+ } else {
+ // Get the sub-registry back
+ $registryInstance = $this->getInstance($this->getRegistryKeyFromInfo($infoInstance));
+ }
+
+ // Get a key for sub-registries
+ $socketKey = $this->getSubRegistryKey($infoInstance);
+
+ // Get a socket container
+ $socketInstance = ObjectFactory::CreateObjectByConfiguredName('socket_container_class', array($socketResource, $infoInstance, $packageData));
+
+ // We have a sub-registry, the socket key and the socket, now we need to put all together
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: socketKey=' . $socketKey . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ' - adding socket container instance ...');
+ $registryInstance->addInstance($socketKey, $socketInstance);
+ }
+
+ /**
+ * Getter for given listener's socket resource
+ *
+ * @param $listenerInstance An instance of a Listenable class
+ * @return $socketResource A valid socket resource
+ * @throws NoSocketRegisteredException If the requested socket is not registered
+ */
+ public function getRegisteredSocketResource (Listenable $listenerInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:listener=' . $listenerInstance->getConnectionType() . ' - CALLED!');
+
+ // The socket must be registered before we can return it
+ if (!$this->isInfoRegistered($listenerInstance)) {
+ // Throw the exception
+ throw new NoSocketRegisteredException ($listenerInstance, self::SOCKET_NOT_REGISTERED);
+ } // END - if
+
+ // Now get the key from the listener
+ $key = $this->getRegistryKeyFromInfo($listenerInstance);
+
+ // And get the registry
+ $registryInstance = $this->getInstance($key);
+
+ // Get a socket key
+ $socketKey = $this->getSubRegistryKey($listenerInstance);
+
+ // And the final socket resource
+ $socketResource = $registryInstance->getInstance($socketKey)->getSocketResource();
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']:listener=' . $listenerInstance->getConnectionType() . ',socketResource[' . gettype($socketResource) . ']=' . $socketResource . ' - EXIT!');
+
+ // Return the resource
+ return $socketResource;
+ }
+
+ /**
+ * "Getter" for info instance from given package data
+ *
+ * @param $packageData Raw package data
+ * @return $infoInstance An instance of a ShareableInfo class
+ */
+ public function getInfoInstanceFromPackageData (array $packageData) {
+ // Init info instance
+ $infoInstance = NULL;
+ //* DEBUG-DIE: */ die(__METHOD__ . ':packageData=' . print_r($packageData, TRUE));
+
+ // Get all keys and check them
+ foreach ($this->getInstanceRegistry() as $key => $registryInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ',registryInstance=' . $registryInstance->__toString());
+
+ // This is always a SubRegistry instance
+ foreach ($registryInstance->getInstanceRegistry() as $subKey => $containerInstance) {
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ',subKey=' . $subKey . ',containerInstance=' . $containerInstance->__toString());
+
+ // Is this a SocketContainer instance and is the address the same?
+ if (($containerInstance instanceof SocketContainer) && ($containerInstance->ifAddressMatches($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]))) {
+ // Debug die
+ //* DEBUG-DIE: */ die(__METHOD__ . ': containerInstance=' . print_r($containerInstance, TRUE));
+
+ // Get listener and helper instances
+ $listenerInstance = $containerInstance->getListenerInstance();
+ $helperInstance = $containerInstance->getHelperInstance();
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ',subKey=' . $subKey . ',listenerInstance[]=' . gettype($listenerInstance) . ',helperInstance[]=' . gettype($helperInstance));
+
+ // Is a listener or helper set?
+ if ($listenerInstance instanceof Listenable) {
+ // Found a listener, so get the info instance first
+ $infoInstance = ConnectionInfoFactory::createConnectionInfoInstance($listenerInstance->getProtocolName(), 'helper');
+
+ // Fill info instance with listener data
+ $infoInstance->fillWithListenerInformation($listenerInstance);
+ } elseif ($helperInstance instanceof ConnectionHelper) {
+ // Found a helper, so get the info instance first
+ $infoInstance = ConnectionInfoFactory::createConnectionInfoInstance($helperInstance->getProtocolName(), 'helper');
+
+ // Helper is found
+ $infoInstance->fillWithConnectionHelperInformation($helperInstance);
+ } else {
+ // Not supported state!
+ $this->debugInstance('[' . __METHOD__ . ':' . __LINE__ . ']: Invalid state found, please report this to the developers with full debug infos.' . PHP_EOL);
+ }
+
+ // Debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-REGISTRY[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ',subKey=' . $subKey . ',infoInstance[' . gettype($infoInstance) . ']=' . $infoInstance->__toString() . ' with protocol ' . $infoInstance->getProtocolName() . ' - FOUND!');
+ break;
+ } // END - if
+ } // END - foreach
+
+ // Is no longer NULL set?
+ if (!is_null($infoInstance)) {
+ // Then skip here, too
+ break;
+ } // END - if
+ } // END - foreach
+
+ // Return the info instance
+ return $infoInstance;
+ }
+
+}
// Own namespace
namespace Hub\Tag\Network;
+// Import application-specific stuff
+
// Import framework stuff
use CoreFramework\Listener\Listenable;
use CoreFramework\Registry\Registry;
// Own namespace
namespace Hub\Visitor\;
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+
// Import framework stuff
-use CoreFramework\Pool\Poolable;
use CoreFramework\Visitor\BaseVisitor;
use CoreFramework\Visitor\Visitor;
// Own namespace
namespace Hub\Visitor\Handler\;
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+
// Import framework stuff
-use CoreFramework\Pool\Poolable;
use CoreFramework\Visitor\BaseVisitor;
/**
// Import application-specific stuff
use Hub\Network\Receive\Receivable;
+use Hub\Pool\Poolable;
// Import framework stuff
use CoreFramework\Listener\Listenable;
-use CoreFramework\Pool\Poolable;
use CoreFramework\Visitor\BaseVisitor;
/**
// Own namespace
namespace Hub\Visitor\;
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+
// Import framework stuff
-use CoreFramework\Pool\Poolable;
use CoreFramework\Visitor\BaseVisitor;
/**
// Own namespace
namespace Hub\Visitor\Pool\Listener;
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+
// Import framework stuff
use CoreFramework\Listener\Listenable;
-use CoreFramework\Pool\Poolable;
use CoreFramework\Visitor\BaseVisitor;
/**
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Visitor\Task\Active;
+
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+use Hub\Visitor\Pool\PoolVisitor;
+
+// Import framework stuff
+use CoreFramework\Generic\BaseDecorator;
+use CoreFramework\Listener\Listenable;
+use CoreFramework\Task\Taskable;
+use CoreFramework\Visitor\BaseVisitor;
+use CoreFramework\Visitor\Decorator\DecoratorVisitor;
+use CoreFramework\Visitor\Listener\ListenerVisitor;
+use CoreFramework\Visitor\Task\TaskVisitor;
+
+/**
+ * An ActiveTask visitor
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class ActiveTaskVisitor extends BaseVisitor implements TaskVisitor, PoolVisitor, ListenerVisitor, DecoratorVisitor {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set visitor mode
+ $this->setVisitorMode('task');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $visitorInstance An instance a Visitorable class
+ */
+ public static final function createActiveTaskVisitor () {
+ // Get new instance
+ $visitorInstance = new ActiveTaskVisitor();
+
+ // Return the prepared instance
+ return $visitorInstance;
+ }
+
+ /**
+ * Visits the given task instance
+ *
+ * @param $taskInstance A Taskable instance
+ * @return void
+ */
+ public function visitTask (Taskable $taskInstance) {
+ // Execute the task from this visitor
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ' ]: Visiting task ' . $taskInstance->__toString() . ' - CALLED!');
+ $taskInstance->executeTask();
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ' ]: Visiting task ' . $taskInstance->__toString() . ' - EXIT!');
+ }
+
+ /**
+ * Pool visitor method for active tasks
+ *
+ * @param $poolInstance A Poolable instance
+ * @return void
+ */
+ public function visitPool (Poolable $poolInstance) {
+ /**
+ * We don't need to visit a pool as an active task because a pool can
+ * never become a task. Instead e.g. by a listener pool we should visit
+ * all listeners one by one
+ */
+ }
+
+ /**
+ * Visits the given listener instance
+ *
+ * @param $listenerInstance A Listenable instance
+ * @return void
+ */
+ public function visitListener (Listenable $listenerInstance) {
+ // Do "listen" here
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ' ]: Visiting ' . $listenerInstance->__toString() . ' - CALLED!');
+ $listenerInstance->doListen();
+ //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('[' . __METHOD__ . ':' . __LINE__ . ' ]: Visiting ' . $listenerInstance->__toString() . ' - FINISH');
+ }
+
+ /**
+ * Visits the given decorator instance
+ *
+ * @param $decoratorInstance A decorator instance
+ * @return void
+ */
+ public function visitDecorator (BaseDecorator $decoratorInstance) {
+ // A decorator itself can never become an active task so this method
+ // remains empty.
+ }
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Visitor\Task\Shutdown;
+
+// Import application-specific stuff
+use Hub\Pool\Poolable;
+use Hub\Visitor\Pool\PoolVisitor;
+
+// Import framework stuff
+use CoreFramework\Generic\BaseDecorator;
+use CoreFramework\Listener\Listenable;
+use CoreFramework\Task\Taskable;
+use CoreFramework\Visitor\BaseVisitor;
+use CoreFramework\Visitor\Decorator\DecoratorVisitor;
+use CoreFramework\Visitor\Listener\ListenerVisitor;
+use CoreFramework\Visitor\Task\TaskVisitor;
+
+/**
+ * An ShutdownTask visitor
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class ShutdownTaskVisitor extends BaseVisitor implements TaskVisitor, PoolVisitor, ListenerVisitor, DecoratorVisitor {
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+
+ // Set visitor mode
+ $this->setVisitorMode('task');
+ }
+
+ /**
+ * Creates an instance of this class
+ *
+ * @return $visitorInstance An instance a Visitorable class
+ */
+ public static final function createShutdownTaskVisitor () {
+ // Get new instance
+ $visitorInstance = new ShutdownTaskVisitor();
+
+ // Return the prepared instance
+ return $visitorInstance;
+ }
+
+ /**
+ * Visits the given task instance
+ *
+ * @param $taskInstance A Taskable instance
+ * @return void
+ */
+ public function visitTask (Taskable $taskInstance) {
+ // Shutdown the task instance
+ $taskInstance->doShutdown();
+ }
+
+ /**
+ * Pool visitor method for active tasks
+ *
+ * @param $poolInstance A Poolable instance
+ * @return void
+ */
+ public function visitPool (Poolable $poolInstance) {
+ // Shutdown the pool instance
+ $poolInstance->doShutdown();
+ }
+
+ /**
+ * Visits the given listener instance
+ *
+ * @param $listenerInstance A Listenable instance
+ * @return void
+ */
+ public function visitListener (Listenable $listenerInstance) {
+ // Shutdown the listener instance
+ $listenerInstance->doShutdown();
+ }
+
+ /**
+ * Visits the given decorator instance
+ *
+ * @param $decoratorInstance A decorator instance
+ * @return void
+ */
+ public function visitDecorator (BaseDecorator $decoratorInstance) {
+ // Shutdown the decorator instance
+ $decoratorInstance->doShutdown();
+ }
+
+}
$cfg->setConfigEntry('udp_listener_class', 'UdpListener');
// CFG: SOCKET-FILE-LISTENER-CLASS
-$cfg->setConfigEntry('socket_file_listener_class', 'CoreFramework\Listener\Socket\SocketFileListener');
+$cfg->setConfigEntry('socket_file_listener_class', 'Hub\Listener\Socket\SocketFileListener');
// CFG: SOCKET-FILE-DECORATOR-LISTENER-CLASS
-$cfg->setConfigEntry('socket_file_decorator_listener_class', 'CoreFramework\Listener\Socket\SocketFileListenerDecorator');
+$cfg->setConfigEntry('socket_file_decorator_listener_class', 'Hub\Listener\Socket\SocketFileListenerDecorator');
// CFG: NODE-TCP-LISTENER-CLASS
$cfg->setConfigEntry('node_tcp_listener_class', 'HubTcpListenerDecorator');
$cfg->setConfigEntry('raw_package_compressor_class', 'ZlibCompressor');
// CFG: SOCKET-REGISTRY-CLASS
-$cfg->setConfigEntry('socket_registry_class', 'CoreFramework\Registry\Socket\SocketRegistry');
+$cfg->setConfigEntry('socket_registry_class', 'Hub\Registry\Socket\SocketRegistry');
// CFG: SOCKET-CONTAINER-CLASS
$cfg->setConfigEntry('socket_container_class', 'SocketContainer');
$cfg->setConfigEntry('max_dht_recipients', 10);
// CFG: CONNECTION-INFO-CLASS
-$cfg->setConfigEntry('connection_info_class', 'CoreFramework\Information\Connection\ConnectionInfo');
+$cfg->setConfigEntry('connection_info_class', 'Hub\Information\Connection\ConnectionInfo');
// CFG: DEFAULT-HUB-CONSOLE-CONTROLLER
$cfg->setConfigEntry('default_hub_console_controller', 'main');
*
* @author Roland Haeder <webmaster@shipsimu.org>
* @version 0.0.0
- * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
* @license GNU GPL 3.0 or any newer version
*
* This program is free software: you can redistribute it and/or modify
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Socket;
+
+/**
+ * This exception is thrown if the socket cannot be shut down is not error 107
+ * which is "Transport endpoint not connected".
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+class SocketShutdownException extends AbstractSocketException {
+ /**
+ * A Constructor for this exception
+ *
+ * @param $helperInstance An instance of a ConnectionHelper class
+ * @param $code Error code
+ * @return void
+ */
+ public function __construct (ConnectionHelper $helperInstance, $code) {
+ // Get socket resource
+ $socketResource = $helperInstance->getSocketResource();
+
+ // Construct the message
+ $message = sprintf('[%s:] Socket %s cannot be shutdown down. errNo=%s, errStr=%s',
+ $helperInstance->__toString(),
+ $socketResource,
+ socket_last_error($socketResource),
+ socket_strerror(socket_last_error($socketResource))
+ );
+
+ // Call parent exception constructor
+ parent::__construct($message, $code);
+ }
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Pool;
+
+// Import framework stuff
+use CoreFramework\Generic\FrameworkInterface;
+use CoreFramework\Listener\Listenable;
+
+/**
+ * A Poolable interface
+ *
+ * @author Roland Haeder <webmaster@ship-simu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 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 <http://www.gnu.org/licenses/>.
+ */
+interface Poolable extends FrameworkInterface {
+
+ /**
+ * Pre-shuts down the pool
+ *
+ * @return void
+ */
+ function preShutdown ();
+
+ /**
+ * Adds a listener instance to this pool
+ *
+ * @param $poolInstance An instance of a Listenable class
+ * @return void
+ */
+ function addListener (Listenable $poolInstance);
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Registry\Socket;
+
+// Import application-specific stuff
+use Hub\Information\ShareableInfo;
+
+// Import framework stuff
+use CoreFramework\Listener\Listenable;
+use CoreFramework\Registry\Registerable;
+
+/**
+ * A class for registerable socket classes
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+interface RegisterableSocket extends Registerable {
+ /**
+ * Checks whether given socket resource is registered. If $socketResource is
+ * false only the instance will be checked.
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @param $socketResource A valid socket resource
+ * @return $isRegistered Whether the given socket resource is registered
+ */
+ function isSocketRegistered (ShareableInfo $infoInstance, $socketResource);
+
+ /**
+ * Registeres given socket for listener or throws an exception if it is already registered
+ *
+ * @param $infoInstance An instance of a ShareableInfo class
+ * @param $socketResource A valid socket resource
+ * @return void
+ * @throws SocketAlreadyRegisteredException If the given socket is already registered
+ */
+ function registerSocket (ShareableInfo $infoInstance, $socketResource);
+
+ /**
+ * Getter for given listener's socket resource
+ *
+ * @param $listenerInstance An instance of a Listenable class
+ * @return $socketResource A valid socket resource
+ * @throws NoSocketRegisteredException If the requested socket is not registered
+ */
+ function getRegisteredSocketResource (Listenable $listenerInstance);
+
+ /**
+ * "Getter" for info instance from given package data
+ *
+ * @param $packageData Raw package data
+ * @return $infoInstance An instance of a ShareableInfo class
+ */
+ function getInfoInstanceFromPackageData (array $packageData);
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Resolver\State;
+
+// Import framework stuff
+use CoreFramework\Resolver\Resolver;
+
+/**
+ * An instance for state resolver classes
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+interface StateResolver extends Resolver {
+ /**
+ * Returns an state instance for a given package raw data and socket resource
+ *
+ * @param $helperInstance An instance of a ConnectionHelper class
+ * @param $packageData Raw package data
+ * @param $socketResource A valid socket resource
+ * @return $stateInstance An instance of the resolved state
+ */
+ static function resolveStateByPackage (ConnectionHelper $helperInstance, array $packageData, $socketResource);
+
+ /**
+ * Checks whether the given state is valid
+ *
+ * @param $stateName The default state we shall execute
+ * @return $isValid Whether the given state is valid
+ * @throws EmptyVariableException Thrown if given state is not set
+ */
+ function isStateValid ($stateName);
+
+}
--- /dev/null
+Deny from all
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Information;
+
+// Import framework stuff
+use CoreFramework\Generic\FrameworkInterface;
+use CoreFramework\Listener\Listenable;
+
+/**
+ * An interface for shareable informations
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+interface ShareableInfo extends FrameworkInterface {
+ /**
+ * Fills the information class with data from a Listenable instance
+ *
+ * @param $listenerInstance An instance of a Listenable class
+ * @return void
+ */
+ function fillWithListenerInformation (Listenable $listenerInstance);
+
+ /**
+ * Fills the information class with data from a ConnectionHelper instance
+ *
+ * @param $helperInstance An instance of a ConnectionHelper class
+ * @return void
+ */
+ function fillWithConnectionHelperInformation (ConnectionHelper $helperInstance);
+
+}
--- /dev/null
+<?php
+// Own namespace
+namespace Hub\Visitor\Pool;
+
+// Import framework stuff
+use Hub\Pool\Poolable;
+use CoreFramework\Visitor\Visitor;
+
+/**
+ * An interface for the visitor implementation for pools
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Hub Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.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 <http://www.gnu.org/licenses/>.
+ */
+interface PoolVisitor extends Visitor {
+ /**
+ * Visits the given pool instance
+ *
+ * @param $poolInstance A Poolable instance
+ * @return void
+ */
+ function visitPool (Poolable $poolInstance);
+
+}
-Subproject commit 8e72c59c6c3536da832917acf4f2a3903339ad19
+Subproject commit 197d364f62d39e6f731ff62001ac6cafccc0d9cc