webserver.php
changeset 57 31ce64a3ff6c
parent 56 53b0f0d7ff6f
child 62 1b73be5346df
equal deleted inserted replaced
56:53b0f0d7ff6f 57:31ce64a3ff6c
   284     }
   284     }
   285     $socket_do_root = ( $allow_root ) ? function_exists('posix_geteuid') : false;
   285     $socket_do_root = ( $allow_root ) ? function_exists('posix_geteuid') : false;
   286     
   286     
   287     $class = 'Socket_' . HTTPD_SOCKET_LAYER;
   287     $class = 'Socket_' . HTTPD_SOCKET_LAYER;
   288     $this->server = new $class();
   288     $this->server = new $class();
   289     $this->server->tcp_listen($address, $port);
   289     if ( is_array($address) )
       
   290     {
       
   291       foreach ( $address as $a )
       
   292       {
       
   293         if ( is_array($port) )
       
   294         {
       
   295           foreach ( $port as $p )
       
   296           {
       
   297             $this->server->tcp_listen($a, $p);
       
   298           }
       
   299         }
       
   300         else
       
   301         {
       
   302           $this->server->tcp_listen($a, $port);
       
   303         }
       
   304       }
       
   305     }
       
   306     else
       
   307     {
       
   308       if ( is_array($port) )
       
   309       {
       
   310         foreach ( $port as $p )
       
   311         {
       
   312           $this->server->tcp_listen($address, $p);
       
   313         }
       
   314       }
       
   315       else
       
   316       {
       
   317         $this->server->tcp_listen($address, $port);
       
   318       }
       
   319     }
   290     
   320     
   291     // if running as root and we made it here, switch credentials
   321     // if running as root and we made it here, switch credentials
   292     if ( $socket_do_root )
   322     if ( $socket_do_root )
   293     {
   323     {
   294       posix_setuid($targetuser);
   324       posix_setuid($targetuser);
  1847  * Socket abstraction layer - low-level socket functions (socket_*)
  1877  * Socket abstraction layer - low-level socket functions (socket_*)
  1848  */
  1878  */
  1849 
  1879 
  1850 class Socket_Raw
  1880 class Socket_Raw
  1851 {
  1881 {
  1852   var $sock;
  1882   var $sock = array();
  1853   var $socket_initted = false;
  1883   var $socket_initted = false;
  1854   
  1884   
  1855   function tcp_listen($address, $port)
  1885   function tcp_listen($address, $port)
  1856   {
  1886   {
  1857     // do we have socket functions?
  1887     // do we have socket functions?
  1858     if ( !function_exists('socket_create') )
  1888     if ( !function_exists('socket_create') )
  1859     {
  1889     {
  1860       burnout('System does not support socket functions. Please rebuild your PHP or install an appropriate extension.');
  1890       burnout('System does not support socket functions. Please rebuild your PHP or install an appropriate extension.');
  1861     }
  1891     }
  1862     
  1892     
  1863     $this->sock = @socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
  1893     $sockid = count($this->sock);
  1864     if ( !$this->sock )
  1894     
       
  1895     $socktype = ( strstr($address, ':') ) ? AF_INET6 : AF_INET;
       
  1896     $this->sock[$sockid] = @socket_create($socktype, SOCK_STREAM, getprotobyname('tcp'));
       
  1897     if ( !$this->sock[$sockid] )
  1865       throw new Exception('Could not create socket');
  1898       throw new Exception('Could not create socket');
  1866     $result = @socket_bind($this->sock, $address, $port);
  1899     $result = @socket_bind($this->sock[$sockid], $address, $port);
  1867     if ( !$result )
  1900     if ( !$result )
  1868       throw new Exception("Could not bind to $address:$port");
  1901       throw new Exception("Could not bind to $address:$port");
  1869     $this->socket_initted = true;
  1902     $this->socket_initted = true;
  1870     $result = @socket_listen($this->sock, SOMAXCONN);
  1903     $result = @socket_listen($this->sock[$sockid], SOMAXCONN);
  1871     if ( !$result )
  1904     if ( !$result )
  1872       throw new Exception("Could not listen for connections $address:$port");
  1905       throw new Exception("Could not listen for connections $address:$port");
  1873     
  1906     
  1874     $this->socket_initted = true;
  1907     $this->socket_initted = true;
  1875   }
  1908   }
  1877   function destroy()
  1910   function destroy()
  1878   {
  1911   {
  1879     if ( $this->socket_initted )
  1912     if ( $this->socket_initted )
  1880     {
  1913     {
  1881       // http://us3.php.net/manual/en/function.socket-bind.php
  1914       // http://us3.php.net/manual/en/function.socket-bind.php
  1882       if ( !@socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 1) )
  1915       if ( is_array($this->sock) )
  1883       {
  1916       {
  1884         echo socket_strerror(socket_last_error($this->sock)) . "\n";
  1917         foreach ( $this->sock as $sock )
  1885       }
  1918         {
  1886       @socket_shutdown($this->sock, 2);
  1919           if ( !@socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1) )
  1887       @socket_close($this->sock);
  1920           {
       
  1921             echo socket_strerror(socket_last_error($sock)) . "\n";
       
  1922           }
       
  1923           @socket_shutdown($sock, 2);
       
  1924           @socket_close($sock);
       
  1925         }
       
  1926       }
       
  1927       else
       
  1928       {
       
  1929         if ( !@socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 1) )
       
  1930         {
       
  1931           echo socket_strerror(socket_last_error($this->sock)) . "\n";
       
  1932         }
       
  1933         @socket_shutdown($this->sock, 2);
       
  1934         @socket_close($this->sock);
       
  1935       }
  1888     }
  1936     }
  1889   }
  1937   }
  1890   
  1938   
  1891   function accept()
  1939   function accept()
  1892   {
  1940   {
  1893     $remote = false;
  1941     $remote = false;
  1894     $timeout = 5;
  1942     foreach ( $this->sock as $sock )
  1895     switch(@socket_select($r = array($this->sock), $w = array($this->sock), $e = array($this->sock), $timeout)) {
  1943     {
  1896       case 2:
  1944       $timeout = 200000;
  1897         return false;
  1945       switch(@socket_select($r = array($sock), $w = array($sock), $e = array($sock), 0, $timeout)) {
  1898       case 1:
  1946         case 2:
  1899         $remote = @socket_accept($this->sock);
  1947           return false;
  1900         $return = new Socket_Raw();
  1948         case 1:
  1901         $return->sock = $remote;
  1949           $remote = @socket_accept($sock);
  1902         $return->socket_initted = true;
  1950           $return = new Socket_Raw();
  1903         return $return;
  1951           $return->sock = $remote;
  1904         break;
  1952           $return->socket_initted = true;
  1905       case 0:
  1953           return $return;
  1906         return false;
  1954           break;
       
  1955         case 0:
       
  1956           continue;
       
  1957       }
  1907     }
  1958     }
  1908   }
  1959   }
  1909   
  1960   
  1910   /**
  1961   /**
  1911    * Closes the socket but doesn't destroy it.
  1962    * Closes the socket but doesn't destroy it.
  1959  * Socket abstraction layer - PHP stream support
  2010  * Socket abstraction layer - PHP stream support
  1960  */
  2011  */
  1961 
  2012 
  1962 class Socket_Stream
  2013 class Socket_Stream
  1963 {
  2014 {
  1964   var $sock;
  2015   var $sock = array();
  1965   var $socket_initted = false;
  2016   var $socket_initted = false;
  1966   
  2017   
  1967   function tcp_listen($address, $port)
  2018   function tcp_listen($address, $port)
  1968   {
  2019   {
  1969     // does PHP support this?
  2020     // does PHP support this?
  1970     if ( !function_exists('stream_socket_server') )
  2021     if ( !function_exists('stream_socket_server') )
  1971     {
  2022     {
  1972       burnout('System does not support stream functions. Please rebuild your PHP or install an appropriate extension.');
  2023       burnout('System does not support stream functions. Please rebuild your PHP or install an appropriate extension.');
  1973     }
  2024     }
  1974     
  2025     
  1975     $this->sock = @stream_socket_server("tcp://$address:$port", $errno, $errstr);
  2026     if ( strstr($address, ':') )
  1976     if ( !$this->sock )
  2027     {
       
  2028       // ipv6 address (probably)
       
  2029       $address = "[$address]";
       
  2030     }
       
  2031     
       
  2032     $sockid = count($this->sock);
       
  2033     
       
  2034     $this->sock[$sockid] = @stream_socket_server("tcp://$address:$port", $errno, $errstr);
       
  2035     if ( !$this->sock[$sockid] )
       
  2036     {
  1977       throw new Exception("Could not create the socket: error $errno: $errstr");
  2037       throw new Exception("Could not create the socket: error $errno: $errstr");
       
  2038     }
  1978   }
  2039   }
  1979   
  2040   
  1980   function destroy()
  2041   function destroy()
  1981   {
  2042   {
  1982     if ( $this->socket_initted )
  2043     if ( $this->socket_initted )
  1983     {
  2044     {
  1984       // PHP >= 5.2.1
  2045       // PHP >= 5.2.1
  1985       if ( function_exists('stream_socket_shutdown') )
  2046       if ( is_array($this->sock) )
  1986       {
  2047       {
  1987         @stream_socket_shutdown($this->sock, STREAM_SHUT_RDWR);
  2048         foreach ( $this->sock as $sock )
  1988       }
  2049         {
  1989       while ( !@fclose($this->sock) )
  2050           if ( function_exists('stream_socket_shutdown') )
  1990       {
  2051           {
  1991         usleep(100000);
  2052             @stream_socket_shutdown($sock, STREAM_SHUT_RDWR);
       
  2053           }
       
  2054           while ( !@fclose($sock) )
       
  2055           {
       
  2056             usleep(100000);
       
  2057           }
       
  2058         }
       
  2059       }
       
  2060       else
       
  2061       {
       
  2062         if ( function_exists('stream_socket_shutdown') )
       
  2063         {
       
  2064           @stream_socket_shutdown($this->sock, STREAM_SHUT_RDWR);
       
  2065         }
       
  2066         while ( !@fclose($this->sock) )
       
  2067         {
       
  2068           usleep(100000);
       
  2069         }
  1992       }
  2070       }
  1993     }
  2071     }
  1994   }
  2072   }
  1995   
  2073   
  1996   function accept()
  2074   function accept()
  1997   {
  2075   {
  1998     // the goal of a custom accept() with *_select() is to tick every 200ms to allow signals.
  2076     // the goal of a custom accept() with *_select() is to tick every 200ms to allow signals.
  1999     stream_set_blocking($this->sock, 1);
  2077     foreach ( $this->sock as $sock )
  2000     $timeout = 5;
  2078     {
  2001     $selection = @stream_select($r = array($this->sock), $w = array($this->sock), $e = array($this->sock), $timeout);
  2079       stream_set_blocking($sock, 1);
  2002     if ( !$selection )
  2080       $timeout = 200000;
  2003     {
  2081       $selection = @stream_select($r = array($sock), $w = array($sock), $e = array($sock), 0, $timeout);
  2004       return false;
  2082       if ( !$selection )
  2005     }
  2083       {
  2006     $remote = stream_socket_accept($this->sock);
  2084         return false;
  2007     $return = new Socket_Stream();
  2085       }
  2008     $return->sock = $remote;
  2086       $remote = stream_socket_accept($sock);
  2009     $return->socket_initted = true;
  2087       $return = new Socket_Stream();
  2010     return $return;
  2088       $return->sock = $remote;
       
  2089       $return->socket_initted = true;
       
  2090       return $return;
       
  2091     }
  2011   }
  2092   }
  2012   
  2093   
  2013   function soft_shutdown()
  2094   function soft_shutdown()
  2014   {
  2095   {
  2015     fclose($this->sock);
  2096     fclose($this->sock);