From 0c6039ea10e0fe026d04fbdd967388b3ec1cb400 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Fri, 18 May 2012 23:03:18 +0000 Subject: [PATCH] Rewrote many parts, made sockets from socket_accept() blocking IO (see comment why) --- application/hub/config.php | 7 ++ .../main/listener/tcp/class_TcpListener.php | 72 +++++++++++-------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/application/hub/config.php b/application/hub/config.php index 00cfefb7d..2be81a813 100644 --- a/application/hub/config.php +++ b/application/hub/config.php @@ -579,6 +579,13 @@ $cfg->setConfigEntry('tcp_connect_retry_max', 5); // CFG: UDP-CONNECT-RETRY-MAX $cfg->setConfigEntry('udp_connect_retry_max', 5); +// CFG: TCP-SOCKET-ACCEPT-WAIT-SEC +// @TODO This and the next value is very static again +$cfg->setConfigEntry('tcp_socket_accept_wait_sec', 3); + +// CFG: TCP-SOCKET-ACCEPT-WAIT-USEC +$cfg->setConfigEntry('tcp_socket_accept_wait_usec', 0); + // CFG: NODE-STATE-CHECKED-PACKAGE-CLASS $cfg->setConfigEntry('node_state_checked_package_class', 'NewConnectionNodeState'); diff --git a/application/hub/main/listener/tcp/class_TcpListener.php b/application/hub/main/listener/tcp/class_TcpListener.php index b314d5964..ce0b8632e 100644 --- a/application/hub/main/listener/tcp/class_TcpListener.php +++ b/application/hub/main/listener/tcp/class_TcpListener.php @@ -81,13 +81,8 @@ class TcpListener extends BaseListener implements Listenable { */ } // END - if - /* - * "Bind" the socket to the given address, on given port so this means - * that all connections on this port are now our resposibility to - * send/recv data, disconnect, etc.. - */ - $this->debugOutput('TCP-LISTENER: Binding to address ' . $this->getListenAddress() . ':' . $this->getListenPort()); - if (!socket_bind($mainSocket, $this->getListenAddress(), $this->getListenPort())) { + // 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')); /* @@ -105,9 +100,13 @@ class TcpListener extends BaseListener implements Listenable { */ } // END - if - // Start listen for connections - $this->debugOutput('TCP-LISTENER: Listening for connections.'); - if (!socket_listen($mainSocket)) { + /* + * "Bind" the socket to the given address, on given port so this means + * that all connections on this port are now our resposibility to + * 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')); /* @@ -125,8 +124,9 @@ class TcpListener extends BaseListener implements Listenable { */ } // END - if - // Set the option to reuse the port - if (!socket_set_option($mainSocket, SOL_SOCKET, SO_REUSEADDR, 1)) { + // 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')); /* @@ -222,27 +222,39 @@ class TcpListener extends BaseListener implements Listenable { // Do we have changed peers? if (in_array($this->getSocketResource(), $readers)) { - // Then accept it + /* + * Then accept it, if this socket is set to non-blocking IO and the + * connection is NOT sending any data, socket_read() may throw + * error 11 (Resource temporary unavailable). This really nasty + * because if you have blocking IO socket_read() will wait and wait + * and wait ... + */ $newSocket = socket_accept($this->getSocketResource()); - //* NOISY-DEBUG: */ $this->debugOutput('TCP-LISTENER: newSocket=' . $newSocket); - - // We want non-blocking here, too - if (!socket_set_nonblock($newSocket)) { + /* NOISY-DEBUG: */ $this->debugOutput('TCP-LISTENER: newSocket=' . $newSocket); + + // Array for timeout settings + $options = array( + // Seconds + 'sec' => $this->getConfigInstance()->getConfigEntry('tcp_socket_accept_wait_sec'), + // Milliseconds + 'usec' => $this->getConfigInstance()->getConfigEntry('tcp_socket_accept_wait_usec') + ); + + // Set timeout to configured seconds + // @TODO Does this work on Windozer boxes??? + if (!socket_set_option($newSocket, SOL_SOCKET, SO_RCVTIMEO, $options)) { // 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); - - // Get error message - $errorMessage = socket_strerror($socketError); + $this->handleSocketError($newSocket, array('0.0.0.0', '0')); + } // END - if - // Shutdown this socket - $this->shutdownSocket($newSocket); + // Output result (only debugging!) + $option = socket_get_option($newSocket, SOL_SOCKET, SO_RCVTIMEO); + $this->debugOutput('SO_RCVTIMEO[' . gettype($option) . ']=' . print_r($option, true)); - // And throw the exception - throw new InvalidSocketException(array($this, $newSocket, $socketError, $errorMessage), BaseListener::EXCEPTION_INVALID_SOCKET); - */ + // Enable SO_OOBINLINE + if (!socket_set_option($newSocket, SOL_SOCKET, SO_OOBINLINE ,1)) { + // Handle this socket error with a faked recipientData array + $this->handleSocketError($newSocket, array('0.0.0.0', '0')); } // END - if // Add it to the peers @@ -261,7 +273,7 @@ class TcpListener extends BaseListener implements Listenable { // Handle it here, if not main socket if ($currentSocket != $this->getSocketResource()) { // ... or else it will raise warnings like 'Transport endpoint is not connected' - //* NOISY-DEBUG: */ $this->debugOutput('TCP-LISTENER: currentSocket=' . $currentSocket . ',server=' . $this->getSocketResource()); + /* NOISY-DEBUG: */ $this->debugOutput('TCP-LISTENER: currentSocket=' . $currentSocket . ',server=' . $this->getSocketResource()); $this->getHandlerInstance()->processRawDataFromResource($currentSocket); } // END - if -- 2.39.5