From 8fe4d72570ac086e1b23f535055d11591dab8c2c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Sun, 21 May 2017 01:29:11 +0200 Subject: [PATCH] Continued a bit: - implemented visitSocket() - that socket_shutdown() stuff needs rewriting but is now at the right place - added/removed import of StorabelSocket MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Roland Häder --- .../socket/class_SocketContainer.php | 75 ++++++++++++++----- .../ipv4/tcp/class_TcpConnectionHelper.php | 33 +------- .../class_HalfShutdownSocketVisitor.php | 6 +- .../socket/class_ShutdownSocketVisitor.php | 16 +++- .../hub/interfaces/class_HubInterface.php | 1 - .../container/socket/class_StorableSocket.php | 8 ++ 6 files changed, 84 insertions(+), 55 deletions(-) diff --git a/application/hub/classes/container/socket/class_SocketContainer.php b/application/hub/classes/container/socket/class_SocketContainer.php index db6f3d0d3..95b79fc95 100644 --- a/application/hub/classes/container/socket/class_SocketContainer.php +++ b/application/hub/classes/container/socket/class_SocketContainer.php @@ -82,18 +82,18 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable $helperInstance = $infoInstance->getHelperInstance(); // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER: listenerInstance[]=' . gettype($listenerInstance)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: listenerInstance[]=' . gettype($listenerInstance)); // Is there a listener instance set? if ($listenerInstance instanceof Listenable) { // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER: Setting listenerInstance=' . $listenerInstance->__toString() . ' ...'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: Setting listenerInstance=' . $listenerInstance->__toString() . ' ...'); // Set it here for later usage $socketInstance->setListenerInstance($listenerInstance); } elseif ($helperInstance instanceof ConnectionHelper) { // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER: Setting helperInstance=' . $helperInstance->__toString() . ' ...'); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: Setting helperInstance=' . $helperInstance->__toString() . ' ...'); // Set it here for later usage $socketInstance->setHelperInstance($helperInstance); @@ -121,7 +121,7 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable $packageData = $this->getPackageData(); // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER: unl=' . $unl . ',packageData=' . print_r($packageData, true)); + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: unl=' . $unl . ',packageData=' . print_r($packageData, true)); // So, does both match? $matches = ((isset($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT])) && ($packageData[NetworkPackage::PACKAGE_DATA_RECIPIENT] === $unl)); @@ -138,7 +138,7 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable */ public function ifSocketResourceMatches ($socketResource) { // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET-CONTAINER: socketResource[' . gettype($socketResource) . ']=' .$socketResource . ',storedResource[' . gettype($this->getSocketResource()) . ']=' . $this->getSocketResource()); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: socketResource[' . gettype($socketResource) . ']=' .$socketResource . ',storedResource[' . gettype($this->getSocketResource()) . ']=' . $this->getSocketResource()); // So, does both match? $matches = ((is_resource($socketResource)) && ($socketResource === $this->getSocketResource())); @@ -154,7 +154,7 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable */ public function isServerSocketResource () { // Trace message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET: Testing if server socket - CALLED!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: Testing if server socket - CALLED!'); // Init peer address/port $peerAddress = '0.0.0.0'; @@ -171,13 +171,13 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable } // END - if // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('SOCKET: peerAddress=%s,peerPort=%d', $peerAddress, $peerPort)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf(strtoupper($this->getSocketProtocol()) . '-SOCKET: peerAddress=%s,peerPort=%d', $peerAddress, $peerPort)); // Check peer name, it must be empty $isServerSocket = (($isServerSocket) && (empty($peerAddress))); // Trace message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('SOCKET: isServerSocket=%d - EXIT!', intval($isServerSocket))); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf(strtoupper($this->getSocketProtocol()) . '-SOCKET: isServerSocket=%d - EXIT!', intval($isServerSocket))); // Return result return $isServerSocket; @@ -191,13 +191,13 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable */ public function shutdownSocket () { // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET: Shutting down socket resource ' . $this->getSocketResource() . ' with state ' . $this->getPrintableState() . ' ...'); + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: Shutting down socket ' . $this->getSocketResource() . ' with state ' . $this->getPrintableState() . ' ...'); // Get a visitor instance $visitorInstance = ObjectFactory::createObjectByConfiguredName('shutdown_socket_visitor_class'); // Debug output - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString()); + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString()); // Call the visitor $this->accept($visitorInstance); @@ -211,13 +211,13 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable */ public function halfShutdownSocket () { // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET: Half-shutting down socket resource ' . $this->getSocketResource() . ' with state ' . $this->getPrintableState() . ' ...'); + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: Half-shutting down socket resource ' . $this->getSocketResource() . ' with state ' . $this->getPrintableState() . ' ...'); // Get a visitor instance $visitorInstance = ObjectFactory::createObjectByConfiguredName('half_shutdown_socket_visitor_class'); // Debug output - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('SOCKET:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString()); + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString()); // Call the visitor $this->accept($visitorInstance); @@ -231,13 +231,13 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable */ public function accept (Visitor $visitorInstance) { // Debug message - //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getProtocolName()) . '-SOCKET: ' . $visitorInstance->__toString() . ' has visited ' . $this->__toString() . ' - CALLED!'); + /* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: ' . $visitorInstance->__toString() . ' has visited ' . $this->__toString() . ' - CALLED!'); // Visit this listener - $visitorInstance->visitListener($this); + $visitorInstance->visitSocket($this); // Debug message - //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getProtocolName()) . '-SOCKET: ' . $visitorInstance->__toString() . ' has visited ' . $this->__toString() . ' - EXIT!'); + /* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($this->getSocketProtocol()) . '-SOCKET: ' . $visitorInstance->__toString() . ' has visited ' . $this->__toString() . ' - EXIT!'); } /** @@ -292,13 +292,13 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable $socketProtocol = $this->getSocketProtocol(); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('SOCKET-CONTAINER: socketProtocol[%s]=%s', gettype($socketProtocol), $socketProtocol)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf(strtoupper($this->getSocketProtocol()) . '-SOCKET: socketProtocol[%s]=%s', gettype($socketProtocol), $socketProtocol)); // Get socket option $socketType = socket_get_option($this->getSocketResource(), getprotobyname($socketProtocol), SO_TYPE); // Debug message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('SOCKET-CONTAINER: socketType[%s]=%s', gettype($socketType), $socketType)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf(strtoupper($this->getSocketProtocol()) . '-SOCKET: socketType[%s]=%s', gettype($socketType), $socketType)); // Is it valid? if ($socketType === FALSE) { @@ -432,6 +432,45 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable return $result; } + /** + * Do the shutdown sequence for this connection helper + * + * @return void + * @throws SocketShutdownException If the current socket could not be shut down + * @todo We may want to implement a filter for ease notification of other objects like our pool + * @todo rewrite this! + */ + public function doShutdown () { + // Debug message + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HELPER: Shutting down socket ' . $this->getSocketResource()); + $this->partialStub('Please rewrite this method.'); + return; + + // 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, self::EXCEPTION_INVALID_SOCKET); + } // END - if + } // END - if + + // Try to make blocking IO for socket_close() + socket_set_block($this->getSocketResource()); + + // Drop all data (don't sent any on socket closure) + socket_set_option($this->getSocketResource(), SOL_SOCKET, SO_LINGER, array('l_onoff' => 1, 'l_linger' => 0)); + + // Finally close socket to free some resources + socket_close($this->getSocketResource()); + + // Mark this connection as shutted down + $this->markConnectionShuttedDown(); + } + /** * Handles socket error for given socket resource and peer data. This method * validates socket resource stored in given container if it is a valid @@ -544,7 +583,7 @@ class SocketContainer extends BaseContainer implements StorableSocket, Visitable 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(sprintf('SOCKET-CONTAINER: Unsupported errorCode=%d,message=%s', $errorCode, socket_strerror($errorCode))); + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf(strtoupper($this->getSocketProtocol()) . '-SOCKET: Unsupported errorCode=%d,message=%s', $errorCode, socket_strerror($errorCode))); // Change it only in this class $errorName = StorableSocket::SOCKET_ERROR_UNKNOWN; diff --git a/application/hub/classes/helper/connection/ipv4/tcp/class_TcpConnectionHelper.php b/application/hub/classes/helper/connection/ipv4/tcp/class_TcpConnectionHelper.php index b6c086708..d89f0f235 100644 --- a/application/hub/classes/helper/connection/ipv4/tcp/class_TcpConnectionHelper.php +++ b/application/hub/classes/helper/connection/ipv4/tcp/class_TcpConnectionHelper.php @@ -16,7 +16,6 @@ use Hub\Tools\HubTools; * @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 - * @todo Find an interface for hub helper * * 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 @@ -159,37 +158,13 @@ class TcpConnectionHelper extends BaseIpV4ConnectionHelper implements Connection * * @return void * @throws SocketShutdownException If the current socket could not be shut down - * @todo We may want to implement a filter for ease notification of other objects like our pool + * @todo rewrite this! */ public function doShutdown () { // Debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HELPER: Shutting down socket resource ' . $this->getSocketResource()); - - // 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, self::EXCEPTION_INVALID_SOCKET); - } // END - if - } // END - if - - // Try to make blocking IO for socket_close() - socket_set_block($this->getSocketResource()); - - // Drop all data (don't sent any on socket closure) - socket_set_option($this->getSocketResource(), SOL_SOCKET, SO_LINGER, array('l_onoff' => 1, 'l_linger' => 0)); + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('HELPER: Shutting down connection ... - CALLED!'); - // Finally close socket to free some resources - socket_close($this->getSocketResource()); - - // Mark this connection as shutted down - $this->markConnectionShuttedDown(); + $this->partialStub('Please implement this method.'); } -} -// [EOF] -?> +} diff --git a/application/hub/classes/visitor/socket/class_HalfShutdownSocketVisitor.php b/application/hub/classes/visitor/socket/class_HalfShutdownSocketVisitor.php index a26d5ac8e..15cad687d 100644 --- a/application/hub/classes/visitor/socket/class_HalfShutdownSocketVisitor.php +++ b/application/hub/classes/visitor/socket/class_HalfShutdownSocketVisitor.php @@ -72,7 +72,7 @@ class HalfShutdownSocketVisitor extends BaseVisitor implements Visitor { // Also visit the network package to clear any out-going packages NetworkPackageFactory::createNetworkPackageInstance()->accept($this); - // Still shutdown the visitor (look in visitNetworkPackage() for details) + // Shutdown the connection helper (look in visitNetworkPackage() for details) $helperInstance->doShutdown(); } else { // We can still move on and retry the connection attempt @@ -92,7 +92,5 @@ class HalfShutdownSocketVisitor extends BaseVisitor implements Visitor { // Just call it back $packageInstance->removeFirstFailedPackage(); } -} -// [EOF] -?> +} diff --git a/application/hub/classes/visitor/socket/class_ShutdownSocketVisitor.php b/application/hub/classes/visitor/socket/class_ShutdownSocketVisitor.php index 873460e17..0d43470e4 100644 --- a/application/hub/classes/visitor/socket/class_ShutdownSocketVisitor.php +++ b/application/hub/classes/visitor/socket/class_ShutdownSocketVisitor.php @@ -3,6 +3,7 @@ namespace Hub\Visitor\Shutdown\Socket; // Import application-specific stuff +use Hub\Container\Socket\StorableSocket; use Hub\Helper\Connection\ConnectionHelper; use Hub\Network\Deliver\Deliverable; @@ -102,7 +103,16 @@ class ShutdownSocketVisitor extends BaseVisitor implements Visitor { // Clear pending data $assemblerInstance->clearPendingData(); } -} -// [EOF] -?> + /** + * "Visit" the socket instance. + * + * @param $socketInstance An instance of a StorableSocket class + * @return void + */ + public function visitSocket (StorableSocket $socketInstance) { + // Shut down socket + $socketInstance->doShutdown(); + } + +} diff --git a/application/hub/interfaces/class_HubInterface.php b/application/hub/interfaces/class_HubInterface.php index 7ab9b035c..9ba4ce718 100644 --- a/application/hub/interfaces/class_HubInterface.php +++ b/application/hub/interfaces/class_HubInterface.php @@ -3,7 +3,6 @@ namespace Hub\Generic; // Import application-specific stuff -use Hub\Container\Socket\StorableSocket; // Inport frameworks stuff use CoreFramework\Generic\FrameworkInterface; diff --git a/application/hub/interfaces/container/socket/class_StorableSocket.php b/application/hub/interfaces/container/socket/class_StorableSocket.php index 06c072cd6..5b2b9ab46 100644 --- a/application/hub/interfaces/container/socket/class_StorableSocket.php +++ b/application/hub/interfaces/container/socket/class_StorableSocket.php @@ -176,4 +176,12 @@ interface StorableSocket extends FrameworkInterface { */ function translateSocketErrorCodeToName ($errorCode); + /** + * Do the shutdown sequence for this connection helper + * + * @return void + * @throws SocketShutdownException If the current socket could not be shut down + */ + function doShutdown (); + } -- 2.39.5