# HG changeset patch # User Dan # Date 1227501832 18000 # Node ID 31ce64a3ff6c88d4a283384100a4a4297030fac0 # Parent 53b0f0d7ff6f4c090db8343e36bd01b10114cef0 Some backend changes to webserver to allow IPv6 binding diff -r 53b0f0d7ff6f -r 31ce64a3ff6c functions.php --- a/functions.php Wed Oct 08 21:56:21 2008 -0400 +++ b/functions.php Sun Nov 23 23:43:52 2008 -0500 @@ -295,7 +295,7 @@ require(GREY_ROOT . '/config.php'); } - foreach ( array('public', 'allowcontrol', 'theme', 'allow_fork', 'use_auth', 'auth_data', 'configpass') as $var ) + foreach ( array('public', 'enable_ipv4', 'enable_ipv6', 'allowcontrol', 'theme', 'allow_fork', 'use_auth', 'auth_data', 'configpass') as $var ) { if ( isset($$var) ) { diff -r 53b0f0d7ff6f -r 31ce64a3ff6c webserver.php --- a/webserver.php Wed Oct 08 21:56:21 2008 -0400 +++ b/webserver.php Sun Nov 23 23:43:52 2008 -0500 @@ -286,7 +286,37 @@ $class = 'Socket_' . HTTPD_SOCKET_LAYER; $this->server = new $class(); - $this->server->tcp_listen($address, $port); + if ( is_array($address) ) + { + foreach ( $address as $a ) + { + if ( is_array($port) ) + { + foreach ( $port as $p ) + { + $this->server->tcp_listen($a, $p); + } + } + else + { + $this->server->tcp_listen($a, $port); + } + } + } + else + { + if ( is_array($port) ) + { + foreach ( $port as $p ) + { + $this->server->tcp_listen($address, $p); + } + } + else + { + $this->server->tcp_listen($address, $port); + } + } // if running as root and we made it here, switch credentials if ( $socket_do_root ) @@ -1849,7 +1879,7 @@ class Socket_Raw { - var $sock; + var $sock = array(); var $socket_initted = false; function tcp_listen($address, $port) @@ -1860,14 +1890,17 @@ burnout('System does not support socket functions. Please rebuild your PHP or install an appropriate extension.'); } - $this->sock = @socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); - if ( !$this->sock ) + $sockid = count($this->sock); + + $socktype = ( strstr($address, ':') ) ? AF_INET6 : AF_INET; + $this->sock[$sockid] = @socket_create($socktype, SOCK_STREAM, getprotobyname('tcp')); + if ( !$this->sock[$sockid] ) throw new Exception('Could not create socket'); - $result = @socket_bind($this->sock, $address, $port); + $result = @socket_bind($this->sock[$sockid], $address, $port); if ( !$result ) throw new Exception("Could not bind to $address:$port"); $this->socket_initted = true; - $result = @socket_listen($this->sock, SOMAXCONN); + $result = @socket_listen($this->sock[$sockid], SOMAXCONN); if ( !$result ) throw new Exception("Could not listen for connections $address:$port"); @@ -1879,31 +1912,49 @@ if ( $this->socket_initted ) { // http://us3.php.net/manual/en/function.socket-bind.php - if ( !@socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 1) ) + if ( is_array($this->sock) ) { - echo socket_strerror(socket_last_error($this->sock)) . "\n"; + foreach ( $this->sock as $sock ) + { + if ( !@socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1) ) + { + echo socket_strerror(socket_last_error($sock)) . "\n"; + } + @socket_shutdown($sock, 2); + @socket_close($sock); + } } - @socket_shutdown($this->sock, 2); - @socket_close($this->sock); + else + { + if ( !@socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 1) ) + { + echo socket_strerror(socket_last_error($this->sock)) . "\n"; + } + @socket_shutdown($this->sock, 2); + @socket_close($this->sock); + } } } function accept() { $remote = false; - $timeout = 5; - switch(@socket_select($r = array($this->sock), $w = array($this->sock), $e = array($this->sock), $timeout)) { - case 2: - return false; - case 1: - $remote = @socket_accept($this->sock); - $return = new Socket_Raw(); - $return->sock = $remote; - $return->socket_initted = true; - return $return; - break; - case 0: - return false; + foreach ( $this->sock as $sock ) + { + $timeout = 200000; + switch(@socket_select($r = array($sock), $w = array($sock), $e = array($sock), 0, $timeout)) { + case 2: + return false; + case 1: + $remote = @socket_accept($sock); + $return = new Socket_Raw(); + $return->sock = $remote; + $return->socket_initted = true; + return $return; + break; + case 0: + continue; + } } } @@ -1961,7 +2012,7 @@ class Socket_Stream { - var $sock; + var $sock = array(); var $socket_initted = false; function tcp_listen($address, $port) @@ -1972,9 +2023,19 @@ burnout('System does not support stream functions. Please rebuild your PHP or install an appropriate extension.'); } - $this->sock = @stream_socket_server("tcp://$address:$port", $errno, $errstr); - if ( !$this->sock ) + if ( strstr($address, ':') ) + { + // ipv6 address (probably) + $address = "[$address]"; + } + + $sockid = count($this->sock); + + $this->sock[$sockid] = @stream_socket_server("tcp://$address:$port", $errno, $errstr); + if ( !$this->sock[$sockid] ) + { throw new Exception("Could not create the socket: error $errno: $errstr"); + } } function destroy() @@ -1982,13 +2043,30 @@ if ( $this->socket_initted ) { // PHP >= 5.2.1 - if ( function_exists('stream_socket_shutdown') ) + if ( is_array($this->sock) ) { - @stream_socket_shutdown($this->sock, STREAM_SHUT_RDWR); + foreach ( $this->sock as $sock ) + { + if ( function_exists('stream_socket_shutdown') ) + { + @stream_socket_shutdown($sock, STREAM_SHUT_RDWR); + } + while ( !@fclose($sock) ) + { + usleep(100000); + } + } } - while ( !@fclose($this->sock) ) + else { - usleep(100000); + if ( function_exists('stream_socket_shutdown') ) + { + @stream_socket_shutdown($this->sock, STREAM_SHUT_RDWR); + } + while ( !@fclose($this->sock) ) + { + usleep(100000); + } } } } @@ -1996,18 +2074,21 @@ function accept() { // the goal of a custom accept() with *_select() is to tick every 200ms to allow signals. - stream_set_blocking($this->sock, 1); - $timeout = 5; - $selection = @stream_select($r = array($this->sock), $w = array($this->sock), $e = array($this->sock), $timeout); - if ( !$selection ) + foreach ( $this->sock as $sock ) { - return false; + stream_set_blocking($sock, 1); + $timeout = 200000; + $selection = @stream_select($r = array($sock), $w = array($sock), $e = array($sock), 0, $timeout); + if ( !$selection ) + { + return false; + } + $remote = stream_socket_accept($sock); + $return = new Socket_Stream(); + $return->sock = $remote; + $return->socket_initted = true; + return $return; } - $remote = stream_socket_accept($this->sock); - $return = new Socket_Stream(); - $return->sock = $remote; - $return->socket_initted = true; - return $return; } function soft_shutdown()