From: Roland Häder Date: Fri, 19 May 2017 16:22:49 +0000 (+0200) Subject: imported from hub project X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=bacc713d9c9f952eeba5bd49197f7f1ca0361ec2;p=core.git imported from hub project Signed-off-by: Roland Häder --- diff --git a/framework/main/classes/registry/socket/.htaccess b/framework/main/classes/registry/socket/.htaccess new file mode 100644 index 00000000..3a428827 --- /dev/null +++ b/framework/main/classes/registry/socket/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/framework/main/classes/registry/socket/class_SocketRegistry.php b/framework/main/classes/registry/socket/class_SocketRegistry.php new file mode 100644 index 00000000..b2c272e0 --- /dev/null +++ b/framework/main/classes/registry/socket/class_SocketRegistry.php @@ -0,0 +1,347 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core 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 . + */ +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; + } + +}