From 39800cef903083fe82bb4e0d599b7c603c7eb44c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Fri, 28 May 2010 01:40:31 +0000 Subject: [PATCH] New visitor added, handling of refused connections basicly implemented: - New ShutdownSocketVisitor added. This visitor should shutdown a socket and may notify other objects later on. - Handling of refused connections (e.g. while announcement phase) basicly implemented. Yet there is some work left to do. --- .gitattributes | 1 + application/hub/config.php | 9 +++ application/hub/main/class_BaseHubSystem.php | 21 ++++++ .../connection/class_BaseConnectionHelper.php | 64 +++++++++++++++++ .../tcp/class_TcpConnectionHelper.php | 24 +++++++ .../hub/main/package/class_NetworkPackage.php | 7 ++ application/hub/main/visitor/class_ | 2 +- application/hub/main/visitor/socket/.htaccess | 1 + .../socket/class_ShutdownSocketVisitor.php | 71 +++++++++++++++++++ 9 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 application/hub/main/visitor/socket/.htaccess create mode 100644 application/hub/main/visitor/socket/class_ShutdownSocketVisitor.php diff --git a/.gitattributes b/.gitattributes index e1c935d89..269bdaf92 100644 --- a/.gitattributes +++ b/.gitattributes @@ -317,6 +317,7 @@ application/hub/main/visitor/pool/handler/class_Handler -text application/hub/main/visitor/pool/shutdown/.htaccess -text application/hub/main/visitor/pool/shutdown/class_Shutdown -text application/hub/main/visitor/pool/shutdown/class_ShutdownListenerPoolVisitor.php -text +application/hub/main/visitor/socket/.htaccess -text application/hub/main/visitor/tasks/.htaccess -text application/hub/main/visitor/tasks/class_ActiveTaskVisitor.php -text application/hub/starter.php -text diff --git a/application/hub/config.php b/application/hub/config.php index 509c9798b..70ff10389 100644 --- a/application/hub/config.php +++ b/application/hub/config.php @@ -105,6 +105,9 @@ $cfg->setConfigEntry('shutdown_listener_pool_visitor_class', 'ShutdownListenerPo // CFG: SHUTDOWN-TASK-VISITOR-CLASS $cfg->setConfigEntry('shutdown_task_visitor_class', 'ShutdownTaskVisitor'); +// CFG: SHUTDOWN-SOCKET-VISITOR-CLASS +$cfg->setConfigEntry('shutdown_socket_visitor_class', 'ShutdownSocketVisitor'); + // CFG: ACTIVE-TASK-VISITOR-CLASS $cfg->setConfigEntry('active_task_visitor_class', 'ActiveTaskVisitor'); @@ -402,5 +405,11 @@ $cfg->setConfigEntry('tcp_buffer_length', 1024); // CFG: UDP-BUFFER-LENGTH $cfg->setConfigEntry('udp_buffer_length', 1024); +// CFG: TCP-CONNECT-RETRY-MAX +$cfg->setConfigEntry('tcp_connect_retry_max', 10); + +// CFG: UDP-CONNECT-RETRY-MAX +$cfg->setConfigEntry('udp_connect_retry_max', 10); + // [EOF] ?> diff --git a/application/hub/main/class_BaseHubSystem.php b/application/hub/main/class_BaseHubSystem.php index 293da4cc0..f1595d161 100644 --- a/application/hub/main/class_BaseHubSystem.php +++ b/application/hub/main/class_BaseHubSystem.php @@ -104,6 +104,27 @@ class BaseHubSystem extends BaseFrameworkSystem { protected final function getPackageInstance () { return $this->packageInstance; } + + /** + * 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 + $this->debugOutput('Shutting down socket ' . $socketResource . ' ...'); + + // Set socket resource + $this->setSocketResource($socketResource); + + // Get a visitor instance + $visitorInstance = ObjectFactory::createObjectByConfiguredName('shutdown_socket_visitor_class'); + + // Call the visitor + $this->accept($visitorInstance); + } } // [EOF] diff --git a/application/hub/main/helper/connection/class_BaseConnectionHelper.php b/application/hub/main/helper/connection/class_BaseConnectionHelper.php index 99f1221f1..8c0a4f82d 100644 --- a/application/hub/main/helper/connection/class_BaseConnectionHelper.php +++ b/application/hub/main/helper/connection/class_BaseConnectionHelper.php @@ -47,6 +47,16 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc */ private $offset = 0; + /** + * Connect retries for this connection + */ + private $retryCount = 0; + + /** + * Wether this connection is shutted down + */ + private $shuttedDown = false; + /** * Protected constructor * @@ -118,6 +128,17 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc $this->address = $address; } + /** + * "Accept" a visitor by simply calling it back + * + * @param $visitorInstance A Visitable instance + * @return void + */ + protected final function accept (Visitor $visitorInstance) { + // Just call the visitor + $visitorInstance->visitConnectionHelper($this); + } + /** * Sends raw package data to the recipient * @@ -166,6 +187,49 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc // Return it return $class; } + + /** + * Checks wether the connect retry is exhausted + * + * @return $isExhaused Wether connect retry is exchausted + */ + public final function isConnectRetryExhausted () { + // Construct config entry + $configEntry = $this->getProtocol() . '_connect_retry_max'; + + // Check it out + $isExhausted = ($this->retryCount >= $this->getConfigInstance()->getConfigEntry($configEntry)); + + // Return it + return $isExhausted; + } + + /** + * Increases the connect retry count + * + * @return void + */ + public final function increaseConnectRetry () { + $this->retryCount++; + } + + /** + * Marks this connection as shutted down + * + * @return void + */ + protected final function markConnectionShutdown () { + $this->shuttedDown = true; + } + + /** + * Getter for shuttedDown + * + * @return $shuttedDown Wether this connection is shutted down + */ + public final function isShuttedDown () { + return $this->shuttedDown; + } } // [EOF] diff --git a/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php b/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php index b8c1295dc..bf92729dd 100644 --- a/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php +++ b/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php @@ -132,6 +132,30 @@ class TcpConnectionHelper extends BaseConnectionHelper { // Okay, that should be it. So return it... return $socketResource; } + + /** + * Do the shutdown sequence for TCP connections + * + * @todo We may want to implement a filter for ease notification of other objects like our pool + * @return void + * @throws SocketShutdownException If the current socket could not be shut down + */ + public function doShutdown () { + // Clear any previous errors + socket_clear_error($this->getSocketResource()); + + // Call the shutdown function on the currently set socket + if (!@socket_shutdown($this->getSocketResource())) { + // Could not shutdown socket, this is fine if e.g. the other side is not connected, so analyse it + if (socket_last_error($this->getSocketResource()) != 107) { + // Something bad happened while we shutdown a socket + throw new SocketShutdownException($this, BaseListener::EXCEPTION_INVALID_SOCKET); + } // END - if + } // END - if + + // Mark this connection as shutted down + $this->markConnectionShutdown(); + } } // [EOF] diff --git a/application/hub/main/package/class_NetworkPackage.php b/application/hub/main/package/class_NetworkPackage.php index 838f4bf4c..5c7f05194 100644 --- a/application/hub/main/package/class_NetworkPackage.php +++ b/application/hub/main/package/class_NetworkPackage.php @@ -243,6 +243,13 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Registe // Get the right connection instance $connectionInstance = SocketRegistry::createSocketRegistry()->getHandlerInstanceFromPackageData($packageData); + // Is this connection still alive? + if ($connectionInstance->isShuttedDown()) { + // This connection is shutting down + // @TODO We may want to do somthing more here? + return; + } // END - if + // Sent it away (we catch exceptions one method above $connectionInstance->sendRawPackageData($packageData); } diff --git a/application/hub/main/visitor/class_ b/application/hub/main/visitor/class_ index 6442569ad..32dd61858 100644 --- a/application/hub/main/visitor/class_ +++ b/application/hub/main/visitor/class_ @@ -38,7 +38,7 @@ class ???Visitor extends BaseVisitor implements Visitor { /** * Creates an instance of this class * - * @return $visitorInstance An instance a Visitorable class + * @return $visitorInstance An instance a Visitorable class */ public final static function create???Visitor () { // Get new instance diff --git a/application/hub/main/visitor/socket/.htaccess b/application/hub/main/visitor/socket/.htaccess new file mode 100644 index 000000000..3a4288278 --- /dev/null +++ b/application/hub/main/visitor/socket/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/application/hub/main/visitor/socket/class_ShutdownSocketVisitor.php b/application/hub/main/visitor/socket/class_ShutdownSocketVisitor.php new file mode 100644 index 000000000..d2abe68c1 --- /dev/null +++ b/application/hub/main/visitor/socket/class_ShutdownSocketVisitor.php @@ -0,0 +1,71 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009, 2010 Hub Developer Team + * @license GNU GPL 3.0 or any newer version + * @link http://www.ship-simu.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +class ShutdownSocketVisitor extends BaseVisitor implements Visitor { + /** + * Protected constructor + * + * @return void + */ + protected function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + + // Set visitor mode + $this->setVisitorMode('ShutdownSocket'); + } + + /** + * Creates an instance of this class + * + * @return $visitorInstance An instance a Visitorable class + */ + public final static function createShutdownSocketVisitor () { + // Get new instance + $visitorInstance = new ShutdownSocketVisitor(); + + // Return the prepared instance + return $visitorInstance; + } + + /** + * "Visit" method to do the actual request. Here we want to shutdown the + * attached socket. + * + * @param $helperInstance A BaseConnectionHelper instance + * @return void + */ + public function visitConnectionHelper (BaseConnectionHelper $helperInstance) { + // Do we have reached the retry count? + if ($helperInstance->isConnectRetryExhausted()) { + // Shutdown the connection + $helperInstance->doShutdown(); + } else { + // We can still move on and retry the connection attempt + $helperInstance->increaseConnectRetry(); + } + } +} + +// [EOF] +?> -- 2.39.5