From ec8c0a417affae2d6099dd4446e788b3dc826fbb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Tue, 7 Feb 2012 20:31:05 +0000 Subject: [PATCH] Refactured handling of socket errors, old code is commeted out and will be removed on-demand (if the proper handler call-back is finished) --- .gitattributes | 1 + application/hub/config.php | 3 + application/hub/exceptions.php | 8 +- application/hub/main/class_BaseHubSystem.php | 112 ++++++++++++++++++ .../class_PeerStateLookupDatabaseWrapper.php | 2 +- .../network/class_BaseRawDataHandler.php | 17 +-- .../connection/class_BaseConnectionHelper.php | 54 ++++++--- .../tcp/class_TcpConnectionHelper.php | 46 ++++--- .../hub/main/listener/class_BaseListener.php | 1 + .../main/listener/tcp/class_TcpListener.php | 38 ++++-- .../main/listener/udp/class_UdpListener.php | 18 ++- .../hub/main/package/class_NetworkPackage.php | 1 + .../main/pools/peer/class_DefaultPeerPool.php | 16 ++- .../state/peer/class_PeerStateResolver.php | 20 +--- .../class_ConnectionTimedOutPeerState.php | 53 +++++++++ 15 files changed, 303 insertions(+), 87 deletions(-) create mode 100644 application/hub/main/states/peer/errors/class_ConnectionTimedOutPeerState.php diff --git a/.gitattributes b/.gitattributes index 8108bb226..b8dd0a023 100644 --- a/.gitattributes +++ b/.gitattributes @@ -476,6 +476,7 @@ application/hub/main/states/peer/connected/.htaccess -text svneol=unset#text/pla application/hub/main/states/peer/connected/class_ConnectedPeerState.php svneol=native#text/plain application/hub/main/states/peer/errors/.htaccess -text svneol=unset#text/plain application/hub/main/states/peer/errors/class_ConnectionRefusedPeerState.php svneol=native#text/plain +application/hub/main/states/peer/errors/class_ConnectionTimedOutPeerState.php svneol=native#text/plain application/hub/main/states/peer/init/.htaccess -text svneol=unset#text/plain application/hub/main/states/peer/init/class_InitPeerState.php svneol=native#text/plain application/hub/main/states/peer/new/.htaccess -text svneol=unset#text/plain diff --git a/application/hub/config.php b/application/hub/config.php index ff8e966b4..345abce40 100644 --- a/application/hub/config.php +++ b/application/hub/config.php @@ -532,6 +532,9 @@ $cfg->setConfigEntry('peer_connected_state_class', 'ConnectedPeerState'); // CFG: PEER-CONNECTION-REFUSED-STATE-CLASS $cfg->setConfigEntry('peer_connection_refused_state_class', 'ConnectionRefusedPeerState'); +// CFG: PEER-CONNECTION-TIMED-OUT-STATE-CLASS +$cfg->setConfigEntry('peer_connection_timed_out_state_class', 'ConnectionTimedOutPeerState'); + // CFG: PEER-TRANSPORT-ENDPOINT-STATE-CLASS $cfg->setConfigEntry('peer_transport_endpoint_state_class', 'TransportEndpointGonePeerState'); diff --git a/application/hub/exceptions.php b/application/hub/exceptions.php index f219040e6..db2f3c44c 100644 --- a/application/hub/exceptions.php +++ b/application/hub/exceptions.php @@ -132,10 +132,10 @@ function __assertHandler ($file, $line, $code) { set_exception_handler('hub_exception_handler'); // Init assert handling -assert_options(ASSERT_ACTIVE, 1); -assert_options(ASSERT_WARNING, 0); -assert_options(ASSERT_BAIL, 0); -assert_options(ASSERT_QUIET_EVAL, 0); +assert_options(ASSERT_ACTIVE, true); +assert_options(ASSERT_WARNING, false); +assert_options(ASSERT_BAIL, false); +assert_options(ASSERT_QUIET_EVAL, false); assert_options(ASSERT_CALLBACK, '__assertHandler'); // [EOF] diff --git a/application/hub/main/class_BaseHubSystem.php b/application/hub/main/class_BaseHubSystem.php index 14ec46a9d..eb1a79f86 100644 --- a/application/hub/main/class_BaseHubSystem.php +++ b/application/hub/main/class_BaseHubSystem.php @@ -22,6 +22,9 @@ * along with this program. If not, see . */ class BaseHubSystem extends BaseFrameworkSystem { + // Exception codes + const EXCEPTION_UNSUPPORTED_ERROR_HANDLER = 0x900; + /** * Seperator for all bootstrap node entries */ @@ -206,6 +209,115 @@ class BaseHubSystem extends BaseFrameworkSystem { return $this->listenerPoolInstance; } + /** + * 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 $methodName Call-back method name for the error handler + * @throws UnsupportedSocketErrorHandlerException If the error handler is not implemented + */ + protected function getSocketErrorHandlerFromCode ($errorCode) { + // Set NULL, so everyone is forced to implement socket error handlers + $handlerName = NULL; + + // Temporary create a possible name from translated error code + $handlerName = 'socketError' . $this->convertToClassName($this->translateErrorCodeToName($errorCode)) . 'Handler'; + + // Is the call-back method there? + if (!method_exists($this, $handlerName)) { + // Please implement this + throw new UnsupportedSocketErrorHandlerException(array($this, $handlerName, $errorCode), self::EXCEPTION_UNSUPPORTED_ERROR_HANDLER); + } // END - if + + // Return it + return $handlerName; + } + + /** + * 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 $socketResource A valid socket resource + * @param $recipientData An array with two elements: 0=IP number, 1=port number + * @return void + * @throws InvalidSocketException If $socketResource is no socket resource + * @throws NoSocketErrorDetectedException If socket_last_error() gives zero back + */ + protected final function handleSocketError ($socketResource, array $recipientData) { + // 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 count of array, should be two + assert(count($recipientData) == 2); + + // 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($this, $handlerName), $socketResource); + + // Finally clear the error because it has been handled + socket_clear_error($socketResource); + } + + /** + * 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 translateErrorCodeToName ($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 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; + + default: // Everything else <> 0 + // Unhandled error code detected, so first debug it because we may want to handle it like the others + $this->debugOutput('[' . __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. diff --git a/application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php b/application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php index 5c850cc24..4ffca6783 100644 --- a/application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php +++ b/application/hub/main/database/wrapper/states/class_PeerStateLookupDatabaseWrapper.php @@ -225,7 +225,7 @@ class PeerStateLookupDatabaseWrapper extends BaseDatabaseWrapper implements Look $lastError = socket_last_error($socketResource); // Doesn't work! - throw new InvalidSocketException(array($this, gettype($socketResource), $lastError, socket_strerror($lastError)), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $socketResource, $lastError, socket_strerror($lastError)), BaseListener::EXCEPTION_INVALID_SOCKET); } // END - if // Debug message diff --git a/application/hub/main/handler/network/class_BaseRawDataHandler.php b/application/hub/main/handler/network/class_BaseRawDataHandler.php index 8bea9a8ed..50710956e 100644 --- a/application/hub/main/handler/network/class_BaseRawDataHandler.php +++ b/application/hub/main/handler/network/class_BaseRawDataHandler.php @@ -24,14 +24,15 @@ 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_EMPTY_DATA = 'empty_data'; // Other peer has sent nothing - 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_CONNECTED = 'connected'; // Nothing errorous happens, socket is connected + 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_EMPTY_DATA = 'empty_data'; // Other peer has sent nothing + 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_CONNECTED = 'connected'; // Nothing errorous happens, socket is connected // - Package errors const PACKAGE_ERROR_INVALID_DATA = 'invalid_data'; // Invalid data in package found diff --git a/application/hub/main/helper/connection/class_BaseConnectionHelper.php b/application/hub/main/helper/connection/class_BaseConnectionHelper.php index 5a2d92443..d7ad4ee35 100644 --- a/application/hub/main/helper/connection/class_BaseConnectionHelper.php +++ b/application/hub/main/helper/connection/class_BaseConnectionHelper.php @@ -22,6 +22,9 @@ * along with this program. If not, see . */ class BaseConnectionHelper extends BaseHubHelper implements Registerable, ProtocolHandler { + // Exception codes + const EXCEPTION_UNSUPPORTED_ERROR_HANDLER = 0x900; + /** * Protocol used */ @@ -72,9 +75,6 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc // Call parent constructor parent::__construct($className); - // Register this connection helper - Registry::getRegistry()->addInstance('connection', $this); - // Initialize output stream $streamInstance = ObjectFactory::createObjectByConfiguredName('node_raw_data_output_stream_class'); @@ -83,14 +83,17 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc // Init state which sets the state to 'init' $this->initState(); + + // Register this connection helper + Registry::getRegistry()->addInstance('connection', $this); } /** - * Getter for real class name + * Getter for real class name, overwrites generic method and is final * * @return $class Name of this class */ - public function __toString () { + public final function __toString () { // Class name representation $class = self::getConnectionClassName($this->getAddress(), $this->getPort(), parent::__toString()); @@ -271,7 +274,7 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc $rawData .= $dataStream; } // END - while - // Nothing to sent is bad news! + // Nothing to sent is bad news, so assert on it assert(strlen($rawData) > 0); // Encode the raw data with our output-stream @@ -294,24 +297,18 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc // If there was an error, we don't continue here if ($sentBytes === false) { - // Get socket error code for verification - $socketError = socket_last_error($socketResource); - - // Get error message - $errorMessage = socket_strerror($socketError); - - // Shutdown this socket - $this->shutdownSocket($socketResource); + // Handle the error with a faked recipientData array + $this->handleSocketError($socketResource, array('0.0.0.0', '0')); // And throw it - throw new InvalidSocketException(array($this, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); } elseif (($sentBytes == 0) && (strlen($encodedData) > 0)) { // Nothing sent means we are done //* NOISY-DEBUG: */ $this->debugOutput('CONNECTION: All sent! (' . __LINE__ . ')'); break; } - // The difference between sent bytes and length of raw data should not be below zero + // The difference between sent bytes and length of raw data should not go below zero assert((strlen($encodedData) - $sentBytes) >= 0); // Add total sent bytes @@ -356,6 +353,31 @@ class BaseConnectionHelper extends BaseHubHelper implements Registerable, Protoc /* NOISY-DEBUG: */ $this->debugOutput('CONNECTION: ' . $this->__toString() . ',shuttedDown=' . intval($this->shuttedDown)); return $this->shuttedDown; } + + // ************************************************************************ + // Socket error handler call-back methods + // ************************************************************************ + + /** + * Handles socket error 'connection timed out', but does not clear it for + * later debugging purposes. + * + * @param $socketResource A valid socket resource + * @throws SocketConnectionException The connection attempts fails with a time-out + */ + private function socketErrorConnectionTimedOutHandler ($socketResource) { + // 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 SocketConnectionException(array($this, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + } } // [EOF] diff --git a/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php b/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php index d945992fd..1990ddd9e 100644 --- a/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php +++ b/application/hub/main/helper/connection/tcp/class_TcpConnectionHelper.php @@ -44,6 +44,7 @@ class TcpConnectionHelper extends BaseConnectionHelper implements ConnectionHelp * @throws SocketCreationException If the socket could not be created * @throws SocketOptionException If a socket option could not be set * @throws SocketConnectionException If a connection could not be opened + * @todo $errorCode/-Message are now in handleSocketError()'s call-back methods */ public static function createConnectionFromPackageData (array $packageData) { // Create an instance @@ -55,7 +56,7 @@ class TcpConnectionHelper extends BaseConnectionHelper implements ConnectionHelp // Is the socket resource valid? if (!is_resource($socketResource)) { // Something bad happened - throw new SocketCreationException(array($helperInstance, gettype($socketResource), 0, 'invalid'), BaseListener::EXCEPTION_SOCKET_CREATION_FAILED); + throw new SocketCreationException(array($helperInstance, gettype($socketResource)), BaseListener::EXCEPTION_SOCKET_CREATION_FAILED); } // END - if // Get socket error code for verification @@ -63,8 +64,8 @@ class TcpConnectionHelper extends BaseConnectionHelper implements ConnectionHelp // Check if there was an error else if ($socketError > 0) { - // Shutdown this socket - $helperInstance->shutdownSocket($socketResource); + // Handle this socket error with a faked recipientData array + $helperInstance->handleSocketError($socketResource, array('0.0.0.0', '0')); // Then throw again throw new SocketCreationException(array($helperInstance, gettype($socketResource), $socketError, socket_strerror($socketError)), BaseListener::EXCEPTION_SOCKET_CREATION_FAILED); @@ -72,17 +73,11 @@ class TcpConnectionHelper extends BaseConnectionHelper implements ConnectionHelp // Set the option to reuse the port if (!socket_set_option($socketResource, SOL_SOCKET, SO_REUSEADDR, 1)) { - // Get socket error code for verification - $socketError = socket_last_error($socketResource); - - // Get error message - $errorMessage = socket_strerror($socketError); - - // Shutdown this socket - $helperInstance->shutdownSocket($socketResource); + // Handle this socket error with a faked recipientData array + $helperInstance->handleSocketError($socketResource, array('0.0.0.0', '0')); // And throw again - throw new SocketOptionException(array($helperInstance, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new SocketOptionException(array($helperInstance, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); } // END - if // Set the resource @@ -131,10 +126,14 @@ class TcpConnectionHelper extends BaseConnectionHelper implements ConnectionHelp // Now connect to it if (!@socket_connect($socketResource, $recipientData[0], $recipientData[1])) { + // Handle socket error + // @TODO Handle 115 error ("operation in progress") + $helperInstance->handleSocketError($socketResource, $recipientData); + /* // Get socket error code for verification $socketError = socket_last_error($socketResource); - // And throw again, but not for 'Operation now in progress', we should wait a little + // And throw again, but not for 'Operation now in progress'; the shutdownSocket() method should wait a little if ($socketError != 115) { // Get error message $errorMessage = socket_strerror($socketError); @@ -143,32 +142,27 @@ class TcpConnectionHelper extends BaseConnectionHelper implements ConnectionHelp $helperInstance->shutdownSocket($socketResource); // Throw it again - throw new SocketConnectionException(array($helperInstance, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new SocketConnectionException(array($helperInstance, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); } else { // Debug output $helperInstance->debugOutput('CONNECTION: Operation is in progress, this usual for non-blocking connections.'); } + */ } // END - if - // Now, we want non-blocking mode + // Set socket in non-blocking mode if (!socket_set_nonblock($socketResource)) { - // Get socket error code for verification - $socketError = socket_last_error($socketResource); - - // Get error message - $errorMessage = socket_strerror($socketError); - - // Shutdown this socket - $helperInstance->shutdownSocket($socketResource); + // Handle this socket error with a faked recipientData array + $helperInstance->handleSocketError($socketResource, array('0.0.0.0', '0')); // And throw again - throw new SocketOptionException(array($helperInstance, gettype($socketResource), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new SocketOptionException(array($helperInstance, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); } // END - if - // We have a connection, so change the state + // Connection is fully established here, so change the state PeerStateFactory::createPeerStateInstanceByName('connected', $helperInstance); - // Okay, that should be it. So return it... + // Okay, that should be it. Return it... return $socketResource; } diff --git a/application/hub/main/listener/class_BaseListener.php b/application/hub/main/listener/class_BaseListener.php index c367b30d4..f0907e595 100644 --- a/application/hub/main/listener/class_BaseListener.php +++ b/application/hub/main/listener/class_BaseListener.php @@ -26,6 +26,7 @@ class BaseListener extends BaseHubSystem implements Visitable { const EXCEPTION_INVALID_SOCKET = 0xa00; const EXCEPTION_SOCKET_ALREADY_REGISTERED = 0xa01; const EXCEPTION_SOCKET_CREATION_FAILED = 0xa02; + const EXCEPTION_NO_SOCKET_ERROR = 0xa03; /** * Used protocol (Default: invalid, which is indeed invalid...) diff --git a/application/hub/main/listener/tcp/class_TcpListener.php b/application/hub/main/listener/tcp/class_TcpListener.php index 6554016d3..fea5cff83 100644 --- a/application/hub/main/listener/tcp/class_TcpListener.php +++ b/application/hub/main/listener/tcp/class_TcpListener.php @@ -65,7 +65,7 @@ class TcpListener extends BaseListener implements Listenable { // Is the socket resource valid? if (!is_resource($mainSocket)) { // Something bad happened - throw new InvalidSocketException(array($this, gettype($mainSocket), 0, 'invalid'), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket), BaseListener::EXCEPTION_INVALID_SOCKET); } // END - if // Get socket error code for verification @@ -73,12 +73,19 @@ class TcpListener extends BaseListener implements Listenable { // Check if there was an error else if ($socketError > 0) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Then throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, socket_strerror($socketError)), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, socket_strerror($socketError)), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Set the option to reuse the port if (!socket_set_option($mainSocket, SOL_SOCKET, SO_REUSEADDR, 1)) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($mainSocket); @@ -89,7 +96,8 @@ class TcpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // "Bind" the socket to the given address, on given port so this means @@ -97,6 +105,9 @@ class TcpListener extends BaseListener implements Listenable { // send/recv data, disconnect, etc.. $this->debugOutput('TCP-LISTENER: Binding to address ' . $this->getListenAddress() . ':' . $this->getListenPort()); if (!socket_bind($mainSocket, $this->getListenAddress(), $this->getListenPort())) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($mainSocket); @@ -107,12 +118,16 @@ class TcpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Start listen for connections $this->debugOutput('TCP-LISTENER: Listening for connections.'); if (!socket_listen($mainSocket)) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($mainSocket); @@ -123,12 +138,16 @@ class TcpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Now, we want non-blocking mode $this->debugOutput('TCP-LISTENER: Setting non-blocking mode.'); if (!socket_set_nonblock($mainSocket)) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($mainSocket); @@ -139,7 +158,8 @@ class TcpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Set the main socket @@ -206,6 +226,9 @@ class TcpListener extends BaseListener implements Listenable { // We want non-blocking here, too if (!socket_set_nonblock($newSocket)) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($newSocket); @@ -216,7 +239,8 @@ class TcpListener extends BaseListener implements Listenable { $this->shutdownSocket($newSocket); // And throw the exception - throw new InvalidSocketException(array($this, gettype($newSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $newSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Add it to the peers diff --git a/application/hub/main/listener/udp/class_UdpListener.php b/application/hub/main/listener/udp/class_UdpListener.php index bae286155..5fac3aa4f 100644 --- a/application/hub/main/listener/udp/class_UdpListener.php +++ b/application/hub/main/listener/udp/class_UdpListener.php @@ -72,6 +72,9 @@ class UdpListener extends BaseListener implements Listenable { // Set the option to reuse the port $this->debugOutput('UDP-LISTENER: Setting re-use address option.'); if (!socket_set_option($mainSocket, SOL_SOCKET, SO_REUSEADDR, 1)) { + // Handle the socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($mainSocket); @@ -82,7 +85,8 @@ class UdpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // "Bind" the socket to the given address, on given port so this means @@ -90,6 +94,9 @@ class UdpListener extends BaseListener implements Listenable { // send/recv data, disconnect, etc.. $this->debugOutput('UDP-LISTENER: Binding to address ' . $this->getListenAddress() . ':' . $this->getListenPort()); if (!socket_bind($mainSocket, $this->getListenAddress(), $this->getListenPort())) { + // Handle the socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($mainSocket); @@ -100,12 +107,16 @@ class UdpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Now, we want non-blocking mode $this->debugOutput('UDP-LISTENER: Setting non-blocking mode.'); if (!socket_set_nonblock($mainSocket)) { + // Handle the socket error with a faked recipientData array + $this->handleSocketError($mainSocket, array('0.0.0.0', '0')); + /* // Get socket error code for verification $socketError = socket_last_error($socket); @@ -116,7 +127,8 @@ class UdpListener extends BaseListener implements Listenable { $this->shutdownSocket($mainSocket); // And throw again - throw new InvalidSocketException(array($this, gettype($mainSocket), $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $mainSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if // Remember the socket in our class diff --git a/application/hub/main/package/class_NetworkPackage.php b/application/hub/main/package/class_NetworkPackage.php index 5ec8f75d2..9a8bcd023 100644 --- a/application/hub/main/package/class_NetworkPackage.php +++ b/application/hub/main/package/class_NetworkPackage.php @@ -641,6 +641,7 @@ class NetworkPackage extends BaseFrameworkSystem implements Deliverable, Receiva * @return void */ public function assembleDecodedDataToPackage () { + $this->getStackerInstance()->debugInstance(); $this->partialStub('Please implement this method.'); } diff --git a/application/hub/main/pools/peer/class_DefaultPeerPool.php b/application/hub/main/pools/peer/class_DefaultPeerPool.php index 86f060773..1ec9cba62 100644 --- a/application/hub/main/pools/peer/class_DefaultPeerPool.php +++ b/application/hub/main/pools/peer/class_DefaultPeerPool.php @@ -60,7 +60,7 @@ class DefaultPeerPool extends BasePool implements PoolablePeer { // Is it a valid resource? if (!is_resource($socketResource)) { // Throw an exception - throw new InvalidSocketException(array($this, gettype($socketResource), 0, 'invalid'), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $socketResource), BaseListener::EXCEPTION_INVALID_SOCKET); } // END - if // Get error code @@ -68,6 +68,9 @@ class DefaultPeerPool extends BasePool implements PoolablePeer { // Is it without any errors? if ($errorCode > 0) { + // Handle the socket error with a faked recipientData array + $this->handleSocketError($socketResource, array('0.0.0.0', '0')); + /* // Get error message $errorMessage = socket_strerror($errorCode); @@ -75,7 +78,8 @@ class DefaultPeerPool extends BasePool implements PoolablePeer { $this->getListenerInstance()->shutdownSocket($socketResource); // And throw again - throw new InvalidSocketException(array($this, gettype($socketResource), $errorCode, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $socketResource, $errorCode, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if } @@ -96,12 +100,16 @@ class DefaultPeerPool extends BasePool implements PoolablePeer { // The socket resource should not match server socket if ($socketResource != $this->getListenerInstance()->getSocketResource()) { // Try to determine the peer's IP number - if (!socket_getpeername($socketResource, $peerName)) { + if (!@socket_getpeername($socketResource, $peerName)) { + // Handle the socket error with a faked recipientData array + $this->handleSocketError($socketResource, array('0.0.0.0', '0')); + /* // Get last error $lastError = socket_last_error($socketResource); // Doesn't work! - throw new InvalidSocketException(array($this, gettype($socketResource), $lastError, socket_strerror($lastError)), BaseListener::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($this, $socketResource, $lastError, socket_strerror($lastError)), BaseListener::EXCEPTION_INVALID_SOCKET); + */ } // END - if } else { // Server sockets won't work with socket_getpeername() diff --git a/application/hub/main/resolver/state/peer/class_PeerStateResolver.php b/application/hub/main/resolver/state/peer/class_PeerStateResolver.php index 077a5bcf2..6f3afd67d 100644 --- a/application/hub/main/resolver/state/peer/class_PeerStateResolver.php +++ b/application/hub/main/resolver/state/peer/class_PeerStateResolver.php @@ -73,24 +73,8 @@ class PeerStateResolver extends BaseStateResolver implements StateResolver { // Get error code from it $errorCode = socket_last_error($socketResource); - // Is the code a number, then we have to change it - if (($errorCode == 134) || ($errorCode == 107)) { - // Transport endpoint not connected, should be handled else! - // @TODO On some systems it is 134, on some 107? - $errorCode = BaseRawDataHandler::SOCKET_ERROR_TRANSPORT_ENDPOINT; - } elseif ($errorCode == 111) { - // Error 'connection refused' - $errorCode = BaseRawDataHandler::SOCKET_ERROR_CONNECTION_REFUSED; - } elseif ($errorCode > 0) { - // Unhandled error code detected, so first debug it because we may want to handle it like the others - $resolverInstance->debugOutput('[' . __METHOD__ . ':' . __LINE__ . '] UNKNOWN ERROR CODE = ' . $errorCode, ', MESSAGE = ' . socket_strerror($errorCode)); - - // Change it only in this class - $errorCode = BaseRawDataHandler::SOCKET_ERROR_UNKNOWN; - } else { - // Nothing bad happend - $errorCode = BaseRawDataHandler::SOCKET_CONNECTED; - } + // Translate the error code to an own name + $errorCode = $helperInstance->translateSocketErrorCodeToName($errorCode); // Create a state instance based on $errorCode. This factory does the hard work for us $stateInstance = PeerStateFactory::createPeerStateInstanceBySocketStatusCode($helperInstance, $packageData, $socketResource, $errorCode); diff --git a/application/hub/main/states/peer/errors/class_ConnectionTimedOutPeerState.php b/application/hub/main/states/peer/errors/class_ConnectionTimedOutPeerState.php new file mode 100644 index 000000000..43855844f --- /dev/null +++ b/application/hub/main/states/peer/errors/class_ConnectionTimedOutPeerState.php @@ -0,0 +1,53 @@ + + * @version 0.0.0 + * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2011 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 ConnectionTimedOutPeerState extends BasePeerState implements PeerStateable { + /** + * Protected constructor + * + * @return void + */ + protected function __construct () { + // Call parent constructor + parent::__construct(__CLASS__); + + // Set state name + $this->setStateName('connection_timed_out'); + } + + /** + * Creates an instance of this class + * + * @return $stateInstance An instance of a PeerStateable class + */ + public final static function createConnectionTimedOutPeerState () { + // Get new instance + $stateInstance = new ConnectionTimedOutPeerState(); + + // Return the prepared instance + return $stateInstance; + } +} + +// [EOF] +?> -- 2.39.5