- /**
- * 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 $handlerName Call-back method name for the error handler
- * @throws UnsupportedSocketErrorHandlerException If the error handler is not implemented
- */
- protected function getSocketErrorHandlerFromCode ($errorCode) {
- // Create a name from translated error code
- $handlerName = 'socketError' . self::convertToClassName($this->translateSocketErrorCodeToName($errorCode)) . 'Handler';
-
- // Is the call-back method there?
- if (!method_exists($this, $handlerName)) {
- // Please implement this
- throw new UnsupportedSocketErrorHandlerException(array($this, $handlerName, $errorCode), BaseConnectionHelper::EXCEPTION_UNSUPPORTED_ERROR_HANDLER);
- } // END - if
-
- // Return it
- return $handlerName;
- }
-
- /**
- * 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 translateSocketErrorCodeToName ($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 11: // "Resource temporary unavailable"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_RESOURCE_UNAVAILABLE;
- break;
-
- case 13: // "Permission denied"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_PERMISSION_DENIED;
- break;
-
- case 32: // "Broken pipe"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_BROKEN_PIPE;
- break;
-
- case 104: // "Connection reset by peer"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_CONNECTION_RESET_BY_PEER;
- 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;
-
- case 113: // "No route to host"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_NO_ROUTE_TO_HOST;
- break;
-
- case 114: // "Operation already in progress"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_OPERATION_ALREADY_PROGRESS;
- break;
-
- case 115: // "Operation now in progress"
- $errorName = BaseRawDataHandler::SOCKET_ERROR_OPERATION_IN_PROGRESS;
- break;
-
- 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__)->debugOutput('BASE-HUB[' . __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.
- *
- * @param $socketResource A valid socket resource
- * @return void
- */
- public function shutdownSocket ($socketResource) {
- // Debug message
- self::createDebugInstance(__CLASS__)->debugOutput('HUB-SYSTEM: Shutting down socket resource ' . $socketResource . ' with state ' . $this->getPrintableState() . ' ...');
-
- // Set socket resource
- $this->setSocketResource($socketResource);
-
- // Get a visitor instance
- $visitorInstance = ObjectFactory::createObjectByConfiguredName('shutdown_socket_visitor_class');
-
- // Debug output
- self::createDebugInstance(__CLASS__)->debugOutput('HUB-SYSTEM:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString());
-
- // Call the visitor
- $this->accept($visitorInstance);
- }
-
- /**
- * Half-shuts down a given socket resource. This method does only ease calling
- * an other visitor than shutdownSocket() does.
- *
- * @param $socketResource A valid socket resource
- * @return void
- */
- public function halfShutdownSocket ($socketResource) {
- // Debug message
- self::createDebugInstance(__CLASS__)->debugOutput('HUB-SYSTEM: Half-shutting down socket resource ' . $socketResource . ' with state ' . $this->getPrintableState() . ' ...');
-
- // Set socket resource
- $this->setSocketResource($socketResource);
-
- // Get a visitor instance
- $visitorInstance = ObjectFactory::createObjectByConfiguredName('half_shutdown_socket_visitor_class');
-
- // Debug output
- self::createDebugInstance(__CLASS__)->debugOutput('HUB-SYSTEM:' . $this->__toString() . ': visitorInstance=' . $visitorInstance->__toString());
-
- // Call the visitor
- $this->accept($visitorInstance);
- }
-
- // ************************************************************************
- // Socket error handler call-back methods
- // ************************************************************************
-
- /**
- * Handles socket error 'permission denied', but does not clear it for
- * later debugging purposes.
- *
- * @param $socketResource A valid socket resource
- * @param $socketData A valid socket data array (0 = IP/file name, 1 = port)
- * @return void
- * @throws SocketBindingException The socket could not be bind to
- */
- protected function socketErrorPermissionDeniedHandler ($socketResource, array $socketData) {
- // 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 SocketBindingException(array($this, $socketData, $socketResource, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET);
- }