From: Roland Häder Date: Sun, 8 Jul 2018 06:58:33 +0000 (+0200) Subject: Continued: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=d16febd99137708e1ca33cffb69bede5dabbb16a;p=hub.git Continued: - introduced NodeLocatorUtils to avoid monolithic code style - avoided abusing exceptions for program flow control (don't do that) by pre-checking conditions and then avoid bad invocations - updated framework to latest commit Signed-off-by: Roland Häder --- diff --git a/application/hub/classes/class_ b/application/hub/classes/class_ index 679970c1d..d24e845be 100644 --- a/application/hub/classes/class_ +++ b/application/hub/classes/class_ @@ -1,9 +1,9 @@ __toString() . ': packageData=' . print_r($packageData, TRUE); assert(isset($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT])); + // Init instance + $recipientInstance = NULL; + // First try out the direct recipient (session id) try { - // Get instance (should not break) - $recipientInstance = ObjectFactory::createObjectByConfiguredName('direct_recipient_class'); - - // Try to solve it - $recipientInstance->resolveRecipient($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT], $this->getListInstance(), $packageData); - } catch (InvalidSessionIdException $e) { - // Didn't work, so try the non-generic, depending recipient field itself (this may fail) - try { + /* + * Check if recipient is a valid UNL which indicates that the + * recipient must be direct recipient then, otherwise a "virtual" + * recipient. + */ + if (NodeLocatorUtils::isValidUniversalNodeLocator($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT])) { + // Get instance (should not break) + $recipientInstance = ObjectFactory::createObjectByConfiguredName('direct_recipient_class'); + } else { // Try to find the right class $recipientInstance = ObjectFactory::createObjectByConfiguredName(strtolower($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]) . '_recipient_class'); - - // And try to solve again - $recipientInstance->resolveRecipient($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT], $this->getListInstance(), $packageData); - } catch (FrameworkException $e) { - // Could not find class, what ever failed - $this->debugInstance(sprintf('[%s:%d]: Exception: %s,message=%s', __METHOD__, __LINE__, $e->__toString(), $e->getMessage())); } + + // Try to solve it + $recipientInstance->resolveRecipient($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT], $this->getListInstance(), $packageData); + } catch (FrameworkException $e) { + // Could not find class, what ever failed + $this->debugInstance(sprintf('[%s:%d]: Exception: %s,message=%s', __METHOD__, __LINE__, $e->__toString(), $e->getMessage())); } } diff --git a/application/hub/classes/handler/protocol/class_BaseProtocolHandler.php b/application/hub/classes/handler/protocol/class_BaseProtocolHandler.php index fa911ea34..c4e50bb89 100644 --- a/application/hub/classes/handler/protocol/class_BaseProtocolHandler.php +++ b/application/hub/classes/handler/protocol/class_BaseProtocolHandler.php @@ -46,26 +46,6 @@ abstract class BaseProtocolHandler extends BaseHubHandler implements HandleableP parent::__construct($className); } - /** - * Validates given UNL very basicly by given regular expression. You - * normally don't need/want to overwrite this method as this is a very basic - * validation only based on a regex. - * - * @param $unl Universal Node Locator to validate - * @return $isValid Whether the UNL is valid - */ - protected final function isValidUniversalNodeLocator ($unl) { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('PROTOCOL-HANDLER: unl=' . $unl . ' - CALLED!'); - - // Very basic regex check - $isValid = (preg_match($this->getRegularExpression(), $unl) === 1); - - // Return result - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('PROTOCOL-HANDLER: isValid=' . intval($isValid) . ' - EXIT!'); - return $isValid; - } - /** * Getter for protocol name * diff --git a/application/hub/classes/handler/protocol/ipv4/class_BaseIpV4ProtocolHandler.php b/application/hub/classes/handler/protocol/ipv4/class_BaseIpV4ProtocolHandler.php index 439a791d0..4c37f8a1f 100644 --- a/application/hub/classes/handler/protocol/ipv4/class_BaseIpV4ProtocolHandler.php +++ b/application/hub/classes/handler/protocol/ipv4/class_BaseIpV4ProtocolHandler.php @@ -6,6 +6,7 @@ namespace Org\Shipsimu\Hub\Handler\Protocol\Network\IpV4; use Org\Shipsimu\Hub\Factory\Network\Locator\UniversalNodeLocatorFactory; use Org\Shipsimu\Hub\Handler\Protocol\BaseProtocolHandler; use Org\Shipsimu\Hub\Locator\Node\LocateableNode; +use Org\Shipsimu\Hub\Locator\Node\Tools\NodeLocatorUtils; use Org\Shipsimu\Hub\Network\Package\NetworkPackage; /** @@ -45,9 +46,6 @@ abstract class BaseIpV4ProtocolHandler extends BaseProtocolHandler { protected function __construct ($className) { // Call parent constructor parent::__construct($className); - - // Set regex - $this->setRegularExpression(LocateableNode::UNL_REGEX); } /** @@ -89,7 +87,7 @@ abstract class BaseIpV4ProtocolHandler extends BaseProtocolHandler { assert(substr($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT], 0, strlen($this->getHandlerName())) != $this->getHandlerName()); // Default is from generic validation - $isValid = $this->isValidUniversalNodeLocator($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]); + $isValid = NodeLocatorUtils::isValidUniversalNodeLocator($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT]); // Debug message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('IPV4-PROTOCOL-HANDLER: PACKAGE_DATA_RECIPIENT=' . $packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT] . ',isValid[' . gettype($isValid) . ']=' . intval($isValid)); diff --git a/application/hub/classes/locator/class_UniversalNodeLocator.php b/application/hub/classes/locator/class_UniversalNodeLocator.php index 7a283e572..800e84136 100644 --- a/application/hub/classes/locator/class_UniversalNodeLocator.php +++ b/application/hub/classes/locator/class_UniversalNodeLocator.php @@ -5,6 +5,7 @@ namespace Org\Shipsimu\Hub\Locator\Node; // Import application-specific stuff use Org\Shipsimu\Hub\Database\Frontend\Node\Information\NodeInformationDatabaseWrapper; use Org\Shipsimu\Hub\Generic\BaseHubSystem; +use Org\Shipsimu\Hub\Locator\Node\Tools\NodeLocatorUtils; // Import framework stuff use Org\Mxchange\CoreFramework\Registry\Registerable; @@ -49,9 +50,6 @@ class UniversalNodeLocator extends BaseHubSystem implements LocateableNode, Regi protected function __construct () { // Call parent constructor parent::__construct(__CLASS__); - - // Set regex for UNL-validation - $this->setRegularExpression(LocateableNode::UNL_REGEX); } /** @@ -238,7 +236,7 @@ class UniversalNodeLocator extends BaseHubSystem implements LocateableNode, Regi //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('UNIVERSAL-NODE-LOCATOR: unl=[%s]=%s - CALLED!', gettype($unl), $unl)); // Make sure the UNL is valid - if (!$this->isValidUniversalNodeLocator($unl)) { + if (!NodeLocatorUtils::isValidUniversalNodeLocator($unl)) { // UNL is not valid throw new InvalidArgumentException(sprintf('unl[%s]=%s is not valid.', gettype($unl), $unl)); } // END - if @@ -302,24 +300,4 @@ class UniversalNodeLocator extends BaseHubSystem implements LocateableNode, Regi } // END - foreach } - /** - * Validates given UNL very basicly by given regular expression. You - * normally don't need/want to overwrite this method as this is a very basic - * validation only based on a regex. - * - * @param $unl Universal Node Locator to validate - * @return $isValid Whether the UNL is valid - */ - private final function isValidUniversalNodeLocator ($unl) { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('UNIVERSAL-NODE-LOCATOR: unl=' . $unl . ' - CALLED!'); - - // Very basic regex check - $isValid = (preg_match($this->getRegularExpression(), $unl) === 1); - - // Return result - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('UNIVERSAL-NODE-LOCATOR: isValid=' . intval($isValid) . ' - EXIT!'); - return $isValid; - } - } diff --git a/application/hub/classes/tools/class_HubTools.php b/application/hub/classes/tools/class_HubTools.php deleted file mode 100644 index ff6bb9298..000000000 --- a/application/hub/classes/tools/class_HubTools.php +++ /dev/null @@ -1,330 +0,0 @@ - - * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2015 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 . - */ -class HubTools extends BaseHubSystem { - // Constants for exceptions - const EXCEPTION_SESSION_ID_IS_INVALID = 0x200; - const EXCEPTION_HOSTNAME_NOT_FOUND = 0x201; - - /** - * Cache for session ids - */ - private $sessionIdCache = array(); - - /** - * Length for session id (should be 32+salt_length - */ - private $sessionIdLength = 0; - - /** - * Self instance - */ - private static $selfInstance = NULL; - - /** - * Protected constructor - * - * @return void - */ - protected function __construct () { - // Call parent constructor - parent::__construct(__CLASS__); - - // Init salt length - $this->sessionIdLength = 32 + $this->getConfigInstance()->getConfigEntry('salt_length'); - } - - /** - * Singleton getter for self instance - * - * @retuen $selfInstance An instance of this class - */ - public static final function getSelfInstance () { - // Is the instance set - if (is_null(self::$selfInstance)) { - // Then set it - self::$selfInstance = new HubTools(); - } // END - if - - // Return own instance - return self::$selfInstance; - } - - /** - * Getter for session id length - * - * @return $sessionIdLength Length of session ids - */ - protected final function getSessionIdLength () { - return $this->sessionIdLength; - } - - /** - * Resolves a session id into an instance of a LocateableNode class. The opposite method - * is resolveSessionIdByUniversalNodeLocator() - * - * @param $sessionId A valid session id - * @return $recipientUniversalNodeLocator Recipient as Universal Node Locator - */ - protected function resolveUniversalNodeLocatorBySessionId ($sessionId) { - // Init variable - $recipientUniversalNodeLocator = 'invalid://invalid:invalid'; - - // And ask it for Universal Node Locator by given session id - $recipient = DhtObjectFactory::createDhtInstance('node')->findNodeLocalBySessionId($sessionId); - //* DEBUG-DIE: */ die(__METHOD__ . ': UNFINISHED: recipient[' . gettype($recipient) . ']=' . print_r($recipient, TRUE) . ',sessionId=' . $sessionId . PHP_EOL); - - // Is the recipient valid? - if (isset($recipient[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_EXTERNAL_ADDRESS])) { - // Then use this - $recipientUniversalNodeLocator = $recipient[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_EXTERNAL_ADDRESS]; - } else { - // Get the instance, this might throw a NPE - $nodeInstance = NodeObjectFactory::createNodeInstance(); - - // Is the session id the same? - if ($nodeInstance->getSessionId() == $sessionId) { - // Then get an instance of a LocateableNode class from it, assume TCP by default - $recipientUniversalNodeLocator = self::determineOwnExternalAddress() . ':' . $nodeInstance->getConfigInstance()->getConfigEntry('node_listen_port'); - } // END - if - } - - // Return result - return $recipientUniversalNodeLocator; - } - - /** - * Resolves a session id into a node id by asking local DHT. - * - * @param $sessionId Session id - * @return $nodeId Node id - */ - public static function resolveNodeIdBySessionId ($sessionId) { - // Get an own instance - $selfInstance = self::getSelfInstance(); - - // And ask it for session id by given Universal Node Locator - $nodeData = DhtObjectFactory::createDhtInstance('node')->findNodeLocalBySessionId($sessionId); - - // Make sure the node id is there - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: sessionId=' . $sessionId . ', nodeData[' . gettype($nodeData) . ']=' . print_r($nodeData, TRUE)); - assert(isset($nodeData[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_NODE_ID])); - - // Return it - return $nodeData[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_NODE_ID]; - } - - /** - * Resolves a Universal Node Locator into a session id. The "opposite" method - * is resolveUniversalNodeLocatorBySessionId(). - * - * @param $unlInstance Universal Node Locator - * @return $sessionId Valid session id - */ - public static function resolveSessionIdByUniversalNodeLocator (LocateableNode $unlInstance) { - // Get an own instance - $selfInstance = self::getSelfInstance(); - - // And ask it for session id by given Universal Node Locator - $recipient = DhtObjectFactory::createDhtInstance('node')->findNodeByUniversalNodeLocator($unlInstance); - die(__METHOD__.':recipient='.print_r($recipient, TRUE)); - - // Return result - return $sessionId; - } - - /** - * Resolves given session id into an instance of a LocateableNode class, if Universal Node Locator is set, it won't be translated - * - * @param $address Session id or Universal Node Locator - * @return $recipient Recipient as Universal Node Locator - * @throws InvalidSessionIdException If the provided session id is invalid (and no Universal Node Locator) - * @throws NoValidHostnameException If the provided hostname cannot be resolved into an IP address - */ - public static function resolveSessionId ($address) { - // Get an own instance - $selfInstance = self::getSelfInstance(); - - // Default is direct Universal Node Locator - $recipient = $address; - - // Does it match a direct Universal Node Locator? (hint: see www.regexlib.com for the regular expression) - if (preg_match('/([a-z0-9]{3,10})\/\/:([a-z0-9\.]{5,})/', $address)) { - // @TODO ((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])):([0-9]{3,5}) - // Direct Universal Node Locator found - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Direct Universal Node Locator ' . $address . ' detected.'); - } elseif (isset($selfInstance->sessionIdCache[$address])) { - // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Using entry from sessionIdCache[] array.'); - - // Found in cache! - $recipient = $selfInstance->sessionIdCache[$address]; - - // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: sessionIdCache[' . $address . ']=' . $recipient); - } elseif (preg_match('/([a-f0-9]{' . $selfInstance->getSessionIdLength() . '})/', $address)) { - // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Using internal session id resolver.'); - - // Resolve session id into an instance of a LocateableNode class - $recipient = $selfInstance->resolveUniversalNodeLocatorBySessionId($address); - - // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Session id ' . $address . ' resolved to ' . $recipient); - } else { - // Invalid session id/UNL - throw new InvalidSessionIdException($address, self::EXCEPTION_SESSION_ID_IS_INVALID); - } - - // Return it - return $recipient; - } - - /** - * Determine UNL or 'external_address' if set - * - * @return $unl The determined external UNL of this node - */ - public static function determineOwnExternalAddress () { - // Is the external_address config entry set? - if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('external_address') != '') { - // Use it as external address - $unl = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('external_address'); - } else { - // Determine own external address by connecting to my (coder) server at 188.138.90.169 - $unl = self::determineExternalUniversalNodeLocator(); - } - - // Return it - return $unl; - } - - /** - * Determine UNL or 'internal_address' if set - * - * @return $unl The determined internal UNL of this node - */ - public static function determineOwnInternalAddress () { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: CALLED!'); - - // Is the internal_address config entry set? - if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('allow_publish_internal_address') == 'N') { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: Calling self::determineOwnExternalAddress() as allow_publish_internal_address=N is set ...'); - - // Not allowed to publish internal address, so use external - $unl = self::determineOwnExternalAddress(); - } elseif (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('internal_address') != '') { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: Getting config entry internal_address ...'); - - // Use it as internal address - $unl = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('internal_address'); - } else { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: Calling self::determineInternalUniversalNodeLocator() ...'); - - // Determine own internal address - $unl = self::determineInternalUniversalNodeLocator(); - } - - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: unl=' . $unl . ' - EXIT!'); - - // Return it - return $unl; - } - - /** - * Determines the UNL (Universal Node Locator) for the internal address - * - * @return $internalUnl Internal UNL - */ - public static function determineInternalUniversalNodeLocator () { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: CALLED!'); - - // Is there cache? (This shortens a lot calls) - if (!isset($GLOBALS[__METHOD__])) { - // Determine UNL based on this node: - // 1) Get discovery class - $discoveryInstance = ObjectFactory::createObjectByConfiguredName('unl_discovery_class'); - - // 2) "Determine" it - $GLOBALS[__METHOD__] = $discoveryInstance->discoverUniversalNodeLocatorByConfiguredAddress('internal'); - - // Make sure it is valid - // @TODO Find a better validation than empty() - assert(!empty($GLOBALS[__METHOD__])); - } // END - if - - // Return it - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: unl=' . $GLOBALS[__METHOD__] . ' - EXIT!'); - return $GLOBALS[__METHOD__]; - } - - /** - * Determines the UNL (Universal Node Locator) for the external address - * - * @return $externalUnl External UNL - */ - public static function determineExternalUniversalNodeLocator () { - // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: CALLED!'); - - // Is there cache? (This shortens a lot calls) - if (!isset($GLOBALS[__METHOD__])) { - // Determine UNL based on this node: - // 1) Get discovery class - $discoveryInstance = ObjectFactory::createObjectByConfiguredName('unl_discovery_class'); - - // 2) "Determine" it - $GLOBALS[__METHOD__] = $discoveryInstance->discoverUniversalNodeLocatorByConfiguredAddress('external'); - - // Make sure it is valid - // @TODO Find a better validation than empty() - assert(!empty($GLOBALS[__METHOD__])); - } // END - if - - // Return it - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: unl=' . $GLOBALS[__METHOD__] . ' - EXIT!'); - return $GLOBALS[__METHOD__]; - } - -} diff --git a/application/hub/classes/tools/hub/.htaccess b/application/hub/classes/tools/hub/.htaccess new file mode 100644 index 000000000..3a4288278 --- /dev/null +++ b/application/hub/classes/tools/hub/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/application/hub/classes/tools/hub/class_HubTools.php b/application/hub/classes/tools/hub/class_HubTools.php new file mode 100644 index 000000000..ff6bb9298 --- /dev/null +++ b/application/hub/classes/tools/hub/class_HubTools.php @@ -0,0 +1,330 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2015 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 . + */ +class HubTools extends BaseHubSystem { + // Constants for exceptions + const EXCEPTION_SESSION_ID_IS_INVALID = 0x200; + const EXCEPTION_HOSTNAME_NOT_FOUND = 0x201; + + /** + * Cache for session ids + */ + private $sessionIdCache = array(); + + /** + * Length for session id (should be 32+salt_length + */ + private $sessionIdLength = 0; + + /** + * Self instance + */ + private static $selfInstance = NULL; + + /** + * Protected constructor + * + * @return void + */ + protected function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + + // Init salt length + $this->sessionIdLength = 32 + $this->getConfigInstance()->getConfigEntry('salt_length'); + } + + /** + * Singleton getter for self instance + * + * @retuen $selfInstance An instance of this class + */ + public static final function getSelfInstance () { + // Is the instance set + if (is_null(self::$selfInstance)) { + // Then set it + self::$selfInstance = new HubTools(); + } // END - if + + // Return own instance + return self::$selfInstance; + } + + /** + * Getter for session id length + * + * @return $sessionIdLength Length of session ids + */ + protected final function getSessionIdLength () { + return $this->sessionIdLength; + } + + /** + * Resolves a session id into an instance of a LocateableNode class. The opposite method + * is resolveSessionIdByUniversalNodeLocator() + * + * @param $sessionId A valid session id + * @return $recipientUniversalNodeLocator Recipient as Universal Node Locator + */ + protected function resolveUniversalNodeLocatorBySessionId ($sessionId) { + // Init variable + $recipientUniversalNodeLocator = 'invalid://invalid:invalid'; + + // And ask it for Universal Node Locator by given session id + $recipient = DhtObjectFactory::createDhtInstance('node')->findNodeLocalBySessionId($sessionId); + //* DEBUG-DIE: */ die(__METHOD__ . ': UNFINISHED: recipient[' . gettype($recipient) . ']=' . print_r($recipient, TRUE) . ',sessionId=' . $sessionId . PHP_EOL); + + // Is the recipient valid? + if (isset($recipient[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_EXTERNAL_ADDRESS])) { + // Then use this + $recipientUniversalNodeLocator = $recipient[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_EXTERNAL_ADDRESS]; + } else { + // Get the instance, this might throw a NPE + $nodeInstance = NodeObjectFactory::createNodeInstance(); + + // Is the session id the same? + if ($nodeInstance->getSessionId() == $sessionId) { + // Then get an instance of a LocateableNode class from it, assume TCP by default + $recipientUniversalNodeLocator = self::determineOwnExternalAddress() . ':' . $nodeInstance->getConfigInstance()->getConfigEntry('node_listen_port'); + } // END - if + } + + // Return result + return $recipientUniversalNodeLocator; + } + + /** + * Resolves a session id into a node id by asking local DHT. + * + * @param $sessionId Session id + * @return $nodeId Node id + */ + public static function resolveNodeIdBySessionId ($sessionId) { + // Get an own instance + $selfInstance = self::getSelfInstance(); + + // And ask it for session id by given Universal Node Locator + $nodeData = DhtObjectFactory::createDhtInstance('node')->findNodeLocalBySessionId($sessionId); + + // Make sure the node id is there + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: sessionId=' . $sessionId . ', nodeData[' . gettype($nodeData) . ']=' . print_r($nodeData, TRUE)); + assert(isset($nodeData[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_NODE_ID])); + + // Return it + return $nodeData[NodeDistributedHashTableDatabaseWrapper::DB_COLUMN_NODE_ID]; + } + + /** + * Resolves a Universal Node Locator into a session id. The "opposite" method + * is resolveUniversalNodeLocatorBySessionId(). + * + * @param $unlInstance Universal Node Locator + * @return $sessionId Valid session id + */ + public static function resolveSessionIdByUniversalNodeLocator (LocateableNode $unlInstance) { + // Get an own instance + $selfInstance = self::getSelfInstance(); + + // And ask it for session id by given Universal Node Locator + $recipient = DhtObjectFactory::createDhtInstance('node')->findNodeByUniversalNodeLocator($unlInstance); + die(__METHOD__.':recipient='.print_r($recipient, TRUE)); + + // Return result + return $sessionId; + } + + /** + * Resolves given session id into an instance of a LocateableNode class, if Universal Node Locator is set, it won't be translated + * + * @param $address Session id or Universal Node Locator + * @return $recipient Recipient as Universal Node Locator + * @throws InvalidSessionIdException If the provided session id is invalid (and no Universal Node Locator) + * @throws NoValidHostnameException If the provided hostname cannot be resolved into an IP address + */ + public static function resolveSessionId ($address) { + // Get an own instance + $selfInstance = self::getSelfInstance(); + + // Default is direct Universal Node Locator + $recipient = $address; + + // Does it match a direct Universal Node Locator? (hint: see www.regexlib.com for the regular expression) + if (preg_match('/([a-z0-9]{3,10})\/\/:([a-z0-9\.]{5,})/', $address)) { + // @TODO ((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])):([0-9]{3,5}) + // Direct Universal Node Locator found + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Direct Universal Node Locator ' . $address . ' detected.'); + } elseif (isset($selfInstance->sessionIdCache[$address])) { + // Debug message + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Using entry from sessionIdCache[] array.'); + + // Found in cache! + $recipient = $selfInstance->sessionIdCache[$address]; + + // Debug message + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: sessionIdCache[' . $address . ']=' . $recipient); + } elseif (preg_match('/([a-f0-9]{' . $selfInstance->getSessionIdLength() . '})/', $address)) { + // Debug message + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Using internal session id resolver.'); + + // Resolve session id into an instance of a LocateableNode class + $recipient = $selfInstance->resolveUniversalNodeLocatorBySessionId($address); + + // Debug message + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HUB-TOOLS: Session id ' . $address . ' resolved to ' . $recipient); + } else { + // Invalid session id/UNL + throw new InvalidSessionIdException($address, self::EXCEPTION_SESSION_ID_IS_INVALID); + } + + // Return it + return $recipient; + } + + /** + * Determine UNL or 'external_address' if set + * + * @return $unl The determined external UNL of this node + */ + public static function determineOwnExternalAddress () { + // Is the external_address config entry set? + if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('external_address') != '') { + // Use it as external address + $unl = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('external_address'); + } else { + // Determine own external address by connecting to my (coder) server at 188.138.90.169 + $unl = self::determineExternalUniversalNodeLocator(); + } + + // Return it + return $unl; + } + + /** + * Determine UNL or 'internal_address' if set + * + * @return $unl The determined internal UNL of this node + */ + public static function determineOwnInternalAddress () { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: CALLED!'); + + // Is the internal_address config entry set? + if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('allow_publish_internal_address') == 'N') { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: Calling self::determineOwnExternalAddress() as allow_publish_internal_address=N is set ...'); + + // Not allowed to publish internal address, so use external + $unl = self::determineOwnExternalAddress(); + } elseif (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('internal_address') != '') { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: Getting config entry internal_address ...'); + + // Use it as internal address + $unl = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('internal_address'); + } else { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: Calling self::determineInternalUniversalNodeLocator() ...'); + + // Determine own internal address + $unl = self::determineInternalUniversalNodeLocator(); + } + + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: unl=' . $unl . ' - EXIT!'); + + // Return it + return $unl; + } + + /** + * Determines the UNL (Universal Node Locator) for the internal address + * + * @return $internalUnl Internal UNL + */ + public static function determineInternalUniversalNodeLocator () { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: CALLED!'); + + // Is there cache? (This shortens a lot calls) + if (!isset($GLOBALS[__METHOD__])) { + // Determine UNL based on this node: + // 1) Get discovery class + $discoveryInstance = ObjectFactory::createObjectByConfiguredName('unl_discovery_class'); + + // 2) "Determine" it + $GLOBALS[__METHOD__] = $discoveryInstance->discoverUniversalNodeLocatorByConfiguredAddress('internal'); + + // Make sure it is valid + // @TODO Find a better validation than empty() + assert(!empty($GLOBALS[__METHOD__])); + } // END - if + + // Return it + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: unl=' . $GLOBALS[__METHOD__] . ' - EXIT!'); + return $GLOBALS[__METHOD__]; + } + + /** + * Determines the UNL (Universal Node Locator) for the external address + * + * @return $externalUnl External UNL + */ + public static function determineExternalUniversalNodeLocator () { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: CALLED!'); + + // Is there cache? (This shortens a lot calls) + if (!isset($GLOBALS[__METHOD__])) { + // Determine UNL based on this node: + // 1) Get discovery class + $discoveryInstance = ObjectFactory::createObjectByConfiguredName('unl_discovery_class'); + + // 2) "Determine" it + $GLOBALS[__METHOD__] = $discoveryInstance->discoverUniversalNodeLocatorByConfiguredAddress('external'); + + // Make sure it is valid + // @TODO Find a better validation than empty() + assert(!empty($GLOBALS[__METHOD__])); + } // END - if + + // Return it + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('NODE: unl=' . $GLOBALS[__METHOD__] . ' - EXIT!'); + return $GLOBALS[__METHOD__]; + } + +} diff --git a/application/hub/classes/tools/node/.htaccess b/application/hub/classes/tools/node/.htaccess new file mode 100644 index 000000000..3a4288278 --- /dev/null +++ b/application/hub/classes/tools/node/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/application/hub/classes/tools/node/class_NodeLocatorUtils.php b/application/hub/classes/tools/node/class_NodeLocatorUtils.php new file mode 100644 index 000000000..9fe02bcf7 --- /dev/null +++ b/application/hub/classes/tools/node/class_NodeLocatorUtils.php @@ -0,0 +1,67 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2015 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 . + */ +class NodeLocatorUtils extends BaseHubSystem { + + /** + * Regular expression for validating IP:port UNLs + */ + const UNL_REGEX = '/^([a-z]{1,}):\/\/\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b:(6553[0-5]|655[0-2][0-9]\d|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|[1-9](\d){0,3})$/'; + + /** + * Private constructor + * + * @return void + */ + private function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + } + + /** + * Validates given UNL very basicly by given regular expression. You + * normally don't need/want to overwrite this method as this is a very basic + * validation only based on a regex. + * + * @param $unl Universal Node Locator to validate + * @return $isValid Whether the UNL is valid + */ + public static function isValidUniversalNodeLocator ($unl) { + // Debug message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('UNIVERSAL-NODE-LOCATOR: unl=' . $unl . ' - CALLED!'); + + // Very basic regex check + $isValid = (preg_match(self::UNL_REGEX, $unl) === 1); + + // Return result + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('UNIVERSAL-NODE-LOCATOR: isValid=' . intval($isValid) . ' - EXIT!'); + return $isValid; + } + +} diff --git a/application/hub/interfaces/locator/class_LocateableNode.php b/application/hub/interfaces/locator/class_LocateableNode.php index b29ee82f4..f6bbf721c 100644 --- a/application/hub/interfaces/locator/class_LocateableNode.php +++ b/application/hub/interfaces/locator/class_LocateableNode.php @@ -38,11 +38,6 @@ interface LocateableNode extends HubInterface { // Port (if any) const UNL_PART_PORT = 'port'; - /** - * Regular expression for validating IP:port UNLs - */ - const UNL_REGEX = '/^([a-z]{1,}):\/\/\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b:(6553[0-5]|655[0-2][0-9]\d|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|[1-9](\d){0,3})$/'; - /** * Getter for external UNL * diff --git a/core b/core index 868c87760..6bf60b1ac 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 868c877607670760eb36e63ebeb1a04237907be9 +Subproject commit 6bf60b1accb36abe10787a06fc4d663f0c78efa9