LTP GCOV extension - code coverage report
Current view: directory - main - network.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 347
Code covered: 23.1 % Executed lines: 80
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Author: Stig Venaas <venaas@uninett.no>                              |
      16                 :    | Streams work by Wez Furlong <wez@thebrainroom.com>                   |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /* $Id: network.c,v 1.118.2.2.2.4 2007/01/11 15:51:37 tony2001 Exp $ */
      21                 : 
      22                 : /*#define DEBUG_MAIN_NETWORK 1*/
      23                 : 
      24                 : #include "php.h"
      25                 : 
      26                 : #include <stddef.h>
      27                 : 
      28                 : #ifdef PHP_WIN32
      29                 : #define O_RDONLY _O_RDONLY
      30                 : #include "win32/param.h"
      31                 : #elif defined(NETWARE)
      32                 : #include <sys/timeval.h>
      33                 : #include <sys/param.h>
      34                 : #else
      35                 : #include <sys/param.h>
      36                 : #endif
      37                 : 
      38                 : #include <sys/types.h>
      39                 : #if HAVE_SYS_SOCKET_H
      40                 : #include <sys/socket.h>
      41                 : #endif
      42                 : 
      43                 : #ifndef _FCNTL_H
      44                 : #include <fcntl.h>
      45                 : #endif
      46                 : 
      47                 : #ifdef HAVE_SYS_SELECT_H
      48                 : #include <sys/select.h>
      49                 : #endif
      50                 : #if HAVE_SYS_POLL_H
      51                 : #include <sys/poll.h>
      52                 : #endif
      53                 : 
      54                 : #if defined(NETWARE)
      55                 : #ifdef USE_WINSOCK
      56                 : #include <novsock2.h>
      57                 : #else
      58                 : #include <arpa/inet.h>
      59                 : #include <netinet/in.h>
      60                 : #include <netdb.h>
      61                 : #include <sys/select.h>
      62                 : #include <sys/socket.h>
      63                 : #endif
      64                 : #elif !defined(PHP_WIN32)
      65                 : #include <netinet/in.h>
      66                 : #include <netdb.h>
      67                 : #if HAVE_ARPA_INET_H
      68                 : #include <arpa/inet.h>
      69                 : #endif
      70                 : #endif
      71                 : 
      72                 : #ifndef HAVE_INET_ATON
      73                 : int inet_aton(const char *, struct in_addr *);
      74                 : #endif
      75                 : 
      76                 : #include "php_network.h"
      77                 : 
      78                 : #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
      79                 : #undef AF_UNIX
      80                 : #endif
      81                 : 
      82                 : #if defined(AF_UNIX)
      83                 : #include <sys/un.h>
      84                 : #endif
      85                 : 
      86                 : #include "ext/standard/file.h"
      87                 : 
      88                 : #ifdef PHP_WIN32
      89                 : # include "win32/time.h"
      90                 : # define SOCK_ERR INVALID_SOCKET
      91                 : # define SOCK_CONN_ERR SOCKET_ERROR
      92                 : # define PHP_TIMEOUT_ERROR_VALUE                WSAETIMEDOUT
      93                 : #else
      94                 : # define SOCK_ERR -1
      95                 : # define SOCK_CONN_ERR -1
      96                 : # define PHP_TIMEOUT_ERROR_VALUE                ETIMEDOUT
      97                 : #endif
      98                 : 
      99                 : #if HAVE_GETADDRINFO
     100                 : #ifdef HAVE_GAI_STRERROR
     101                 : #  define PHP_GAI_STRERROR(x) (gai_strerror(x))
     102                 : #else
     103                 : #  define PHP_GAI_STRERROR(x) (php_gai_strerror(x))
     104                 : /* {{{ php_gai_strerror
     105                 :  */
     106                 : static const char *php_gai_strerror(int code)
     107                 : {
     108                 :         static struct {
     109                 :                 int code;
     110                 :                 const char *msg;
     111                 :         } values[] = {
     112                 : #  ifdef EAI_ADDRFAMILY
     113                 :                 {EAI_ADDRFAMILY, "Address family for hostname not supported"},
     114                 : #  endif
     115                 :                 {EAI_AGAIN, "Temporary failure in name resolution"},
     116                 :                 {EAI_BADFLAGS, "Bad value for ai_flags"},
     117                 :                 {EAI_FAIL, "Non-recoverable failure in name resolution"},
     118                 :                 {EAI_FAMILY, "ai_family not supported"},
     119                 :                 {EAI_MEMORY, "Memory allocation failure"},
     120                 : #  ifdef EAI_NODATA
     121                 :                 {EAI_NODATA, "No address associated with hostname"},
     122                 : #  endif    
     123                 :                 {EAI_NONAME, "Name or service not known"},
     124                 :                 {EAI_SERVICE, "Servname not supported for ai_socktype"},
     125                 :                 {EAI_SOCKTYPE, "ai_socktype not supported"},
     126                 :                 {EAI_SYSTEM, "System error"},
     127                 :                 {0, NULL}
     128                 :         };
     129                 :         int i;
     130                 : 
     131                 :         for (i = 0; values[i].msg != NULL; i++) {
     132                 :                 if (values[i].code == code) {
     133                 :                         return (char *)values[i].msg;
     134                 :                 }
     135                 :         }
     136                 :         
     137                 :         return "Unknown error";
     138                 : }
     139                 : /* }}} */
     140                 : #endif
     141                 : #endif
     142                 : 
     143                 : /* {{{ php_network_freeaddresses
     144                 :  */
     145                 : static void php_network_freeaddresses(struct sockaddr **sal)
     146              14 : {
     147                 :         struct sockaddr **sap;
     148                 : 
     149              14 :         if (sal == NULL)
     150               0 :                 return;
     151              32 :         for (sap = sal; *sap != NULL; sap++)
     152              18 :                 efree(*sap);
     153              14 :         efree(sal);
     154                 : }
     155                 : /* }}} */
     156                 : 
     157                 : /* {{{ php_network_getaddresses
     158                 :  * Returns number of addresses, 0 for none/error
     159                 :  */
     160                 : static int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
     161              14 : {
     162                 :         struct sockaddr **sap;
     163                 :         int n;
     164                 : #if HAVE_GETADDRINFO
     165                 :         static int ipv6_borked = -1; /* the way this is used *is* thread safe */
     166                 :         struct addrinfo hints, *res, *sai;
     167                 : #else
     168                 :         struct hostent *host_info;
     169                 :         struct in_addr in;
     170                 : #endif
     171                 : 
     172              14 :         if (host == NULL) {
     173               0 :                 return 0;
     174                 :         }
     175                 : #if HAVE_GETADDRINFO
     176              14 :         memset(&hints, '\0', sizeof(hints));
     177                 :                 
     178              14 :         hints.ai_family = AF_INET; /* default to regular inet (see below) */
     179              14 :         hints.ai_socktype = socktype;
     180                 :                 
     181                 : # if HAVE_IPV6
     182                 :         /* probe for a working IPv6 stack; even if detected as having v6 at compile
     183                 :          * time, at runtime some stacks are slow to resolve or have other issues
     184                 :          * if they are not correctly configured.
     185                 :          * static variable use is safe here since simple store or fetch operations
     186                 :          * are atomic and because the actual probe process is not in danger of
     187                 :          * collisions or race conditions. */
     188              14 :         if (ipv6_borked == -1) {
     189                 :                 int s;
     190                 : 
     191               7 :                 s = socket(PF_INET6, SOCK_DGRAM, 0);
     192               7 :                 if (s == SOCK_ERR) {
     193               0 :                         ipv6_borked = 1;
     194                 :                 } else {
     195               7 :                         ipv6_borked = 0;
     196               7 :                         closesocket(s);
     197                 :                 }
     198                 :         }
     199              14 :         hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC;
     200                 : # endif
     201                 :                 
     202              14 :         if ((n = getaddrinfo(host, NULL, &hints, &res))) {
     203               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
     204               0 :                 return 0;
     205              14 :         } else if (res == NULL) {
     206               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)");
     207               0 :                 return 0;
     208                 :         }
     209                 : 
     210              14 :         sai = res;
     211              14 :         for (n = 1; (sai = sai->ai_next) != NULL; n++)
     212                 :                 ;
     213                 :         
     214              14 :         *sal = safe_emalloc((n + 1), sizeof(*sal), 0);
     215              14 :         sai = res;
     216              14 :         sap = *sal;
     217                 :         
     218                 :         do {
     219              18 :                 *sap = emalloc(sai->ai_addrlen);
     220              18 :                 memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
     221              18 :                 sap++;
     222              18 :         } while ((sai = sai->ai_next) != NULL);
     223                 :         
     224              14 :         freeaddrinfo(res);
     225                 : #else
     226                 :         if (!inet_aton(host, &in)) {
     227                 :                 /* XXX NOT THREAD SAFE (is safe under win32) */
     228                 :                 host_info = gethostbyname(host);
     229                 :                 if (host_info == NULL) {
     230                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: gethostbyname failed");
     231                 :                         return 0;
     232                 :                 }
     233                 :                 in = *((struct in_addr *) host_info->h_addr);
     234                 :         }
     235                 : 
     236                 :         *sal = safe_emalloc(2, sizeof(*sal), 0);
     237                 :         sap = *sal;
     238                 :         *sap = emalloc(sizeof(struct sockaddr_in));
     239                 :         (*sap)->sa_family = AF_INET;
     240                 :         ((struct sockaddr_in *)*sap)->sin_addr = in;
     241                 :         sap++;
     242                 :         n = 1;
     243                 : #endif
     244                 : 
     245              14 :         *sap = NULL;
     246              14 :         return n;
     247                 : }
     248                 : /* }}} */
     249                 : 
     250                 : #ifndef O_NONBLOCK
     251                 : #define O_NONBLOCK O_NDELAY
     252                 : #endif
     253                 : 
     254                 : #if !defined(__BEOS__)
     255                 : # define HAVE_NON_BLOCKING_CONNECT 1
     256                 : # ifdef PHP_WIN32
     257                 : typedef u_long php_non_blocking_flags_t;
     258                 : #  define SET_SOCKET_BLOCKING_MODE(sock, save) \
     259                 :      save = TRUE; ioctlsocket(sock, FIONBIO, &save)
     260                 : #  define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
     261                 :          ioctlsocket(sock, FIONBIO, &save)
     262                 : # else
     263                 : typedef int php_non_blocking_flags_t;
     264                 : #  define SET_SOCKET_BLOCKING_MODE(sock, save) \
     265                 :          save = fcntl(sock, F_GETFL, 0); \
     266                 :          fcntl(sock, F_SETFL, save | O_NONBLOCK)
     267                 : #  define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
     268                 :          fcntl(sock, F_SETFL, save)
     269                 : # endif
     270                 : #endif
     271                 : 
     272                 : /* Connect to a socket using an interruptible connect with optional timeout.
     273                 :  * Optionally, the connect can be made asynchronously, which will implicitly
     274                 :  * enable non-blocking mode on the socket.
     275                 :  * */
     276                 : /* {{{ php_network_connect_socket */
     277                 : PHPAPI int php_network_connect_socket(php_socket_t sockfd,
     278                 :                 const struct sockaddr *addr,
     279                 :                 socklen_t addrlen,
     280                 :                 int asynchronous,
     281                 :                 struct timeval *timeout,
     282                 :                 char **error_string,
     283                 :                 int *error_code)
     284              14 : {
     285                 : #if HAVE_NON_BLOCKING_CONNECT
     286                 :         php_non_blocking_flags_t orig_flags;
     287                 :         int n;
     288              14 :         int error = 0;
     289                 :         socklen_t len;
     290              14 :         int ret = 0;
     291                 : 
     292              14 :         SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
     293                 :         
     294              14 :         if ((n = connect(sockfd, addr, addrlen)) < 0) {
     295              14 :                 error = php_socket_errno();
     296                 : 
     297              14 :                 if (error_code) {
     298              14 :                         *error_code = error;
     299                 :                 }
     300                 : 
     301              14 :                 if (error != EINPROGRESS) {
     302               0 :                         if (error_string) {
     303               0 :                                 *error_string = php_socket_strerror(error, NULL, 0);
     304                 :                         }
     305                 : 
     306               0 :                         return -1;
     307                 :                 }
     308              14 :                 if (asynchronous && error == EINPROGRESS) {
     309                 :                         /* this is fine by us */
     310               0 :                         return 0;
     311                 :                 }
     312                 :         }
     313                 : 
     314              14 :         if (n == 0) {
     315               0 :                 goto ok;
     316                 :         }
     317                 : 
     318              14 :         if ((n = php_pollfd_for(sockfd, PHP_POLLREADABLE|POLLOUT, timeout)) == 0) {
     319               0 :                 error = PHP_TIMEOUT_ERROR_VALUE;
     320                 :         }
     321                 : 
     322              14 :         if (n > 0) {
     323              14 :                 len = sizeof(error);
     324                 :                 /*
     325                 :                    BSD-derived systems set errno correctly
     326                 :                    Solaris returns -1 from getsockopt in case of error
     327                 :                    */
     328              14 :                 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) < 0) {
     329               0 :                         ret = -1;
     330                 :                 }
     331                 :         } else {
     332                 :                 /* whoops: sockfd has disappeared */
     333               0 :                 ret = -1;
     334                 :         }
     335                 : 
     336              14 : ok:
     337              14 :         if (!asynchronous) {
     338                 :                 /* back to blocking mode */
     339              14 :                 RESTORE_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
     340                 :         }
     341                 : 
     342              14 :         if (error_code) {
     343              14 :                 *error_code = error;
     344                 :         }
     345                 : 
     346              14 :         if (error && error_string) {
     347               0 :                 *error_string = php_socket_strerror(error, NULL, 0);
     348               0 :                 ret = -1;
     349                 :         }
     350              14 :         return ret;
     351                 : #else
     352                 :         if (asynchronous) {
     353                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Asynchronous connect() not supported on this platform");
     354                 :         }
     355                 :         return connect(sockfd, addr, addrlen);
     356                 : #endif
     357                 : }
     358                 : /* }}} */
     359                 : 
     360                 : /* {{{ sub_times */
     361                 : static inline void sub_times(struct timeval a, struct timeval b, struct timeval *result)
     362               0 : {
     363               0 :         result->tv_usec = a.tv_usec - b.tv_usec;
     364               0 :         if (result->tv_usec < 0L) {
     365               0 :                 a.tv_sec--;
     366               0 :                 result->tv_usec += 1000000L;
     367                 :         }
     368               0 :         result->tv_sec = a.tv_sec - b.tv_sec;
     369               0 :         if (result->tv_sec < 0L) {
     370               0 :                 result->tv_sec++;
     371               0 :                 result->tv_usec -= 1000000L;
     372                 :         }
     373               0 : }
     374                 : /* }}} */
     375                 : 
     376                 : /* Bind to a local IP address.
     377                 :  * Returns the bound socket, or -1 on failure.
     378                 :  * */
     379                 : /* {{{ php_network_bind_socket_to_local_addr */
     380                 : php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port,
     381                 :                 int socktype, char **error_string, int *error_code
     382                 :                 TSRMLS_DC)
     383               0 : {
     384               0 :         int num_addrs, n, err = 0;
     385                 :         php_socket_t sock;
     386                 :         struct sockaddr **sal, **psal, *sa;
     387                 :         socklen_t socklen;
     388                 : 
     389               0 :         num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
     390                 : 
     391               0 :         if (num_addrs == 0) {
     392                 :                 /* could not resolve address(es) */
     393               0 :                 return -1;
     394                 :         }
     395                 : 
     396               0 :         for (sal = psal; *sal != NULL; sal++) {
     397               0 :                 sa = *sal;
     398                 : 
     399                 :                 /* create a socket for this address */
     400               0 :                 sock = socket(sa->sa_family, socktype, 0);
     401                 : 
     402               0 :                 if (sock == SOCK_ERR) {
     403               0 :                         continue;
     404                 :                 }
     405                 : 
     406               0 :                 switch (sa->sa_family) {
     407                 : #if HAVE_GETADDRINFO && HAVE_IPV6
     408                 :                         case AF_INET6:
     409               0 :                                 ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
     410               0 :                                 ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
     411               0 :                                 socklen = sizeof(struct sockaddr_in6);
     412               0 :                                 break;
     413                 : #endif
     414                 :                         case AF_INET:
     415               0 :                                 ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
     416               0 :                                 ((struct sockaddr_in *)sa)->sin_port = htons(port);
     417               0 :                                 socklen = sizeof(struct sockaddr_in);
     418               0 :                                 break;
     419                 :                         default:
     420                 :                                 /* Unknown family */
     421               0 :                                 socklen = 0;
     422               0 :                                 sa = NULL;
     423                 :                 }
     424                 : 
     425               0 :                 if (sa) {
     426                 :                         /* attempt to bind */
     427                 :                 
     428                 : #ifdef SO_REUSEADDR
     429                 :                         {
     430               0 :                                 int val = 1;
     431               0 :                                 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
     432                 :                         }
     433                 : #endif
     434                 :                         
     435               0 :                         n = bind(sock, sa, socklen);
     436                 : 
     437               0 :                         if (n != SOCK_CONN_ERR) {
     438               0 :                                 goto bound;
     439                 :                         }
     440                 : 
     441               0 :                         err = php_socket_errno();
     442                 :                 }
     443                 : 
     444               0 :                 closesocket(sock);
     445                 :         }
     446               0 :         sock = -1;
     447                 : 
     448               0 :         if (error_code) {
     449               0 :                 *error_code = err;
     450                 :         }
     451               0 :         if (error_string) {
     452               0 :                 *error_string = php_socket_strerror(err, NULL, 0);
     453                 :         }
     454                 :         
     455               0 : bound:
     456                 : 
     457               0 :         php_network_freeaddresses(psal);
     458                 :         
     459               0 :         return sock;
     460                 :         
     461                 : }
     462                 : /* }}} */
     463                 : 
     464                 : PHPAPI int php_network_parse_network_address_with_port(const char *addr, long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC)
     465               0 : {
     466                 :         char *colon;
     467                 :         char *tmp;
     468               0 :         int ret = FAILURE;
     469                 :         short port;
     470               0 :         struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
     471                 :         struct sockaddr **psal;
     472                 :         int n;
     473               0 :         char *errstr = NULL;
     474                 : #if HAVE_IPV6
     475               0 :         struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
     476                 : #endif
     477                 : 
     478               0 :         if (*addr == '[') {
     479               0 :                 colon = memchr(addr + 1, ']', addrlen-1);
     480               0 :                 if (!colon || colon[1] != ':') {
     481               0 :                         return FAILURE;
     482                 :                 }
     483               0 :                 port = atoi(colon + 2);
     484               0 :                 addr++;
     485                 :         } else {
     486               0 :                 colon = memchr(addr, ':', addrlen);
     487               0 :                 if (!colon) {
     488               0 :                         return FAILURE;
     489                 :                 }
     490               0 :                 port = atoi(colon + 1);
     491                 :         }
     492                 : 
     493               0 :         tmp = estrndup(addr, colon - addr);
     494                 : 
     495                 :         /* first, try interpreting the address as a numeric address */
     496                 : 
     497                 : #if HAVE_IPV6 && HAVE_INET_PTON
     498               0 :         if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) {
     499               0 :                 in6->sin6_port = htons(port);
     500               0 :                 in6->sin6_family = AF_INET6;
     501               0 :                 *sl = sizeof(struct sockaddr_in6);
     502               0 :                 ret = SUCCESS;
     503               0 :                 goto out;
     504                 :         }
     505                 : #endif
     506               0 :         if (inet_aton(tmp, &in4->sin_addr) > 0) {
     507               0 :                 in4->sin_port = htons(port);
     508               0 :                 in4->sin_family = AF_INET;
     509               0 :                 *sl = sizeof(struct sockaddr_in);
     510               0 :                 ret = SUCCESS;
     511               0 :                 goto out;
     512                 :         }
     513                 : 
     514                 :         /* looks like we'll need to resolve it */
     515               0 :         n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr TSRMLS_CC);
     516                 : 
     517               0 :         if (n == 0) {
     518               0 :                 if (errstr) {
     519               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr);
     520               0 :                         STR_FREE(errstr);
     521                 :                 }
     522               0 :                 goto out;
     523                 :         }
     524                 : 
     525                 :         /* copy the details from the first item */
     526               0 :         switch ((*psal)->sa_family) {
     527                 : #if HAVE_GETADDRINFO && HAVE_IPV6
     528                 :                 case AF_INET6:
     529               0 :                         *in6 = **(struct sockaddr_in6**)psal;
     530               0 :                         in6->sin6_port = htons(port);
     531               0 :                         *sl = sizeof(struct sockaddr_in6);
     532               0 :                         ret = SUCCESS;
     533               0 :                         break;
     534                 : #endif
     535                 :                 case AF_INET:
     536               0 :                         *in4 = **(struct sockaddr_in**)psal;
     537               0 :                         in4->sin_port = htons(port);
     538               0 :                         *sl = sizeof(struct sockaddr_in);
     539               0 :                         ret = SUCCESS;
     540                 :                         break;
     541                 :         }
     542                 : 
     543               0 :         php_network_freeaddresses(psal);
     544                 : 
     545               0 : out:
     546               0 :         STR_FREE(tmp);
     547               0 :         return ret;
     548                 : }
     549                 : 
     550                 : 
     551                 : PHPAPI void php_network_populate_name_from_sockaddr(
     552                 :                 /* input address */
     553                 :                 struct sockaddr *sa, socklen_t sl,
     554                 :                 /* output readable address */
     555                 :                 char **textaddr, long *textaddrlen,
     556                 :                 /* output address */
     557                 :                 struct sockaddr **addr,
     558                 :                 socklen_t *addrlen
     559                 :                 TSRMLS_DC)
     560               0 : {
     561               0 :         if (addr) {
     562               0 :                 *addr = emalloc(sl);
     563               0 :                 memcpy(*addr, sa, sl);
     564               0 :                 *addrlen = sl;
     565                 :         }
     566                 : 
     567               0 :         if (textaddr) {
     568                 : #if HAVE_IPV6 && HAVE_INET_NTOP
     569                 :                 char abuf[256];
     570                 : #endif
     571               0 :                 char *buf = NULL;
     572                 : 
     573               0 :                 switch (sa->sa_family) {
     574                 :                         case AF_INET:
     575                 :                                 /* generally not thread safe, but it *is* thread safe under win32 */
     576               0 :                                 buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
     577               0 :                                 if (buf) {
     578               0 :                                         *textaddrlen = spprintf(textaddr, 0, "%s:%d", 
     579                 :                                                 buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
     580                 :                                 }
     581                 : 
     582               0 :                                 break;
     583                 : 
     584                 : #if HAVE_IPV6 && HAVE_INET_NTOP
     585                 :                         case AF_INET6:
     586               0 :                                 buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
     587               0 :                                 if (buf) {
     588               0 :                                         *textaddrlen = spprintf(textaddr, 0, "%s:%d", 
     589                 :                                                 buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
     590                 :                                 }
     591                 : 
     592               0 :                                 break;
     593                 : #endif
     594                 : #ifdef AF_UNIX
     595                 :                         case AF_UNIX:
     596                 :                                 {
     597               0 :                                         struct sockaddr_un *ua = (struct sockaddr_un*)sa;
     598                 : 
     599               0 :                                         if (ua->sun_path[0] == '\0') {
     600                 :                                                 /* abstract name */
     601               0 :                                                 int len = strlen(ua->sun_path + 1) + 1;
     602               0 :                                                 *textaddrlen = len;
     603               0 :                                                 *textaddr = emalloc(len + 1);
     604               0 :                                                 memcpy(*textaddr, ua->sun_path, len);
     605               0 :                                                 (*textaddr)[len] = '\0';
     606                 :                                         } else {
     607               0 :                                                 *textaddrlen = strlen(ua->sun_path);
     608               0 :                                                 *textaddr = estrndup(ua->sun_path, *textaddrlen);
     609                 :                                         }
     610                 :                                 }
     611                 :                                 break;
     612                 : #endif
     613                 : 
     614                 :                 }
     615                 : 
     616                 :         }
     617               0 : }
     618                 : 
     619                 : PHPAPI int php_network_get_peer_name(php_socket_t sock, 
     620                 :                 char **textaddr, long *textaddrlen,
     621                 :                 struct sockaddr **addr,
     622                 :                 socklen_t *addrlen
     623                 :                 TSRMLS_DC)
     624               0 : {
     625                 :         php_sockaddr_storage sa;
     626               0 :         socklen_t sl = sizeof(sa);
     627                 :         
     628               0 :         if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
     629               0 :                 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
     630                 :                                 textaddr, textaddrlen,
     631                 :                                 addr, addrlen
     632                 :                                 TSRMLS_CC);
     633               0 :                 return 0;
     634                 :         }
     635               0 :         return -1;
     636                 : }
     637                 : 
     638                 : PHPAPI int php_network_get_sock_name(php_socket_t sock, 
     639                 :                 char **textaddr, long *textaddrlen,
     640                 :                 struct sockaddr **addr,
     641                 :                 socklen_t *addrlen
     642                 :                 TSRMLS_DC)
     643               0 : {
     644                 :         php_sockaddr_storage sa;
     645               0 :         socklen_t sl = sizeof(sa);
     646                 :         
     647               0 :         if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
     648               0 :                 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
     649                 :                                 textaddr, textaddrlen,
     650                 :                                 addr, addrlen
     651                 :                                 TSRMLS_CC);
     652               0 :                 return 0;
     653                 :         }
     654               0 :         return -1;
     655                 : 
     656                 : }
     657                 : 
     658                 : 
     659                 : /* Accept a client connection from a server socket,
     660                 :  * using an optional timeout.
     661                 :  * Returns the peer address in addr/addrlen (it will emalloc
     662                 :  * these, so be sure to efree the result).
     663                 :  * If you specify textaddr/textaddrlen, a text-printable
     664                 :  * version of the address will be emalloc'd and returned.
     665                 :  * */
     666                 : 
     667                 : /* {{{ php_network_accept_incoming */
     668                 : PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
     669                 :                 char **textaddr, long *textaddrlen,
     670                 :                 struct sockaddr **addr,
     671                 :                 socklen_t *addrlen,
     672                 :                 struct timeval *timeout,
     673                 :                 char **error_string,
     674                 :                 int *error_code
     675                 :                 TSRMLS_DC)
     676               0 : {
     677               0 :         php_socket_t clisock = -1;
     678               0 :         int error = 0, n;
     679                 :         php_sockaddr_storage sa;
     680                 :         socklen_t sl;
     681                 :                 
     682               0 :         n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout);
     683                 : 
     684               0 :         if (n == 0) {
     685               0 :                 error = PHP_TIMEOUT_ERROR_VALUE;
     686               0 :         } else if (n == -1) {
     687               0 :                 error = php_socket_errno();
     688                 :         } else {
     689               0 :                 sl = sizeof(sa);
     690                 : 
     691               0 :                 clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);
     692                 : 
     693               0 :                 if (clisock >= 0) {
     694               0 :                         php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
     695                 :                                         textaddr, textaddrlen,
     696                 :                                         addr, addrlen
     697                 :                                         TSRMLS_CC);
     698                 :                 } else {
     699               0 :                         error = php_socket_errno();
     700                 :                 }
     701                 :         }
     702                 :         
     703               0 :         if (error_code) {
     704               0 :                 *error_code = error;
     705                 :         }
     706               0 :         if (error_string) {
     707               0 :                 *error_string = php_socket_strerror(error, NULL, 0);
     708                 :         }
     709                 :         
     710               0 :         return clisock;
     711                 : }
     712                 : /* }}} */
     713                 :         
     714                 : 
     715                 : 
     716                 : /* Connect to a remote host using an interruptible connect with optional timeout.
     717                 :  * Optionally, the connect can be made asynchronously, which will implicitly
     718                 :  * enable non-blocking mode on the socket.
     719                 :  * Returns the connected (or connecting) socket, or -1 on failure.
     720                 :  * */
     721                 : 
     722                 : /* {{{ php_network_connect_socket_to_host */
     723                 : php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
     724                 :                 int socktype, int asynchronous, struct timeval *timeout, char **error_string,
     725                 :                 int *error_code, char *bindto, unsigned short bindport 
     726                 :                 TSRMLS_DC)
     727              14 : {
     728              14 :         int num_addrs, n, fatal = 0;
     729                 :         php_socket_t sock;
     730                 :         struct sockaddr **sal, **psal, *sa;
     731                 :         struct timeval working_timeout;
     732                 :         socklen_t socklen;
     733                 : #if HAVE_GETTIMEOFDAY
     734                 :         struct timeval limit_time, time_now;
     735                 : #endif
     736                 : 
     737              14 :         num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
     738                 : 
     739              14 :         if (num_addrs == 0) {
     740                 :                 /* could not resolve address(es) */
     741               0 :                 return -1;
     742                 :         }
     743                 : 
     744              14 :         if (timeout) {
     745              14 :                 memcpy(&working_timeout, timeout, sizeof(working_timeout));
     746                 : #if HAVE_GETTIMEOFDAY
     747              14 :                 gettimeofday(&limit_time, NULL);
     748              14 :                 limit_time.tv_sec += working_timeout.tv_sec;
     749              14 :                 limit_time.tv_usec += working_timeout.tv_usec;
     750              14 :                 if (limit_time.tv_usec >= 1000000) {
     751               0 :                         limit_time.tv_usec -= 1000000;
     752               0 :                         limit_time.tv_sec++;
     753                 :                 }
     754                 : #endif
     755                 :         }
     756                 : 
     757              14 :         for (sal = psal; !fatal && *sal != NULL; sal++) {
     758              14 :                 sa = *sal;
     759                 : 
     760                 :                 /* create a socket for this address */
     761              14 :                 sock = socket(sa->sa_family, socktype, 0);
     762                 : 
     763              14 :                 if (sock == SOCK_ERR) {
     764               0 :                         continue;
     765                 :                 }
     766                 : 
     767              14 :                 switch (sa->sa_family) {
     768                 : #if HAVE_GETADDRINFO && HAVE_IPV6
     769                 :                         case AF_INET6:
     770               0 :                                 ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
     771               0 :                                 ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
     772               0 :                                 socklen = sizeof(struct sockaddr_in6);
     773               0 :                                 break;
     774                 : #endif
     775                 :                         case AF_INET:
     776              14 :                                 ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
     777              14 :                                 ((struct sockaddr_in *)sa)->sin_port = htons(port);
     778              14 :                                 socklen = sizeof(struct sockaddr_in);
     779              14 :                                 break;
     780                 :                         default:
     781                 :                                 /* Unknown family */
     782               0 :                                 socklen = 0;
     783               0 :                                 sa = NULL;
     784                 :                 }
     785                 : 
     786              14 :                 if (sa) {
     787                 :                         /* make a connection attempt */
     788                 : 
     789              14 :                         if (bindto) {
     790               0 :                                 struct sockaddr *local_address = NULL;
     791               0 :                                 int local_address_len = 0;
     792                 :                         
     793               0 :                                 if (sa->sa_family == AF_INET) {
     794               0 :                                         struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));
     795                 : 
     796               0 :                                         local_address = (struct sockaddr*)in4;
     797               0 :                                         local_address_len = sizeof(struct sockaddr_in);
     798                 :                                 
     799               0 :                                         in4->sin_family = sa->sa_family;
     800               0 :                                         in4->sin_port = htons(bindport);
     801               0 :                                         if (!inet_aton(bindto, &in4->sin_addr)) {
     802               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
     803               0 :                                                 goto skip_bind;
     804                 :                                         }
     805               0 :                                         memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
     806                 :                                 }
     807                 : #if HAVE_IPV6 && HAVE_INET_PTON
     808                 :                                  else { /* IPV6 */
     809               0 :                                         struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));
     810                 : 
     811               0 :                                         local_address = (struct sockaddr*)in6;
     812               0 :                                         local_address_len = sizeof(struct sockaddr_in6);
     813                 :                                 
     814               0 :                                         in6->sin6_family = sa->sa_family;
     815               0 :                                         in6->sin6_port = htons(bindport);
     816               0 :                                         if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
     817               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
     818               0 :                                                 goto skip_bind;
     819                 :                                         }
     820                 :                                 }
     821                 : #endif
     822               0 :                                 if (!local_address || bind(sock, local_address, local_address_len)) {
     823               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
     824                 :                                 }
     825               0 : skip_bind:
     826               0 :                                 if (local_address) {
     827               0 :                                         efree(local_address);
     828                 :                                 }
     829                 :                         }
     830                 :                         /* free error string recieved during previous iteration (if any) */
     831              14 :                         if (error_string && *error_string) {
     832               0 :                                 efree(*error_string);
     833               0 :                                 *error_string = NULL;
     834                 :                         }
     835                 :                         
     836              14 :                         n = php_network_connect_socket(sock, sa, socklen, asynchronous,
     837                 :                                         timeout ? &working_timeout : NULL,
     838                 :                                         error_string, error_code);
     839                 : 
     840              14 :                         if (n != SOCK_CONN_ERR) {
     841              14 :                                 goto connected;
     842                 :                         }
     843                 : 
     844                 :                         /* adjust timeout for next attempt */
     845                 : #if HAVE_GETTIMEOFDAY
     846               0 :                         if (timeout) {
     847               0 :                                 gettimeofday(&time_now, NULL);
     848                 : 
     849               0 :                                 if (timercmp(&time_now, &limit_time, >=)) {
     850                 :                                         /* time limit expired; don't attempt any further connections */
     851               0 :                                         fatal = 1;
     852                 :                                 } else {
     853                 :                                         /* work out remaining time */
     854               0 :                                         sub_times(limit_time, time_now, &working_timeout);
     855                 :                                 }
     856                 :                         }
     857                 : #else
     858                 :                         if (error_code && *error_code == PHP_TIMEOUT_ERROR_VALUE) {
     859                 :                                 /* Don't even bother trying to connect to the next alternative;
     860                 :                                  * we have no way to determine how long we have already taken
     861                 :                                  * and it is quite likely that the next attempt will fail too. */
     862                 :                                 fatal = 1;
     863                 :                         } else {
     864                 :                                 /* re-use the same initial timeout.
     865                 :                                  * Not the best thing, but in practice it should be good-enough */
     866                 :                                 if (timeout) {
     867                 :                                         memcpy(&working_timeout, timeout, sizeof(working_timeout));
     868                 :                                 }
     869                 :                         }
     870                 : #endif
     871                 :                 }
     872                 : 
     873               0 :                 closesocket(sock);
     874                 :         }
     875               0 :         sock = -1;
     876                 : 
     877              14 : connected:
     878                 : 
     879              14 :         php_network_freeaddresses(psal);
     880                 :         
     881              14 :         return sock;
     882                 : }
     883                 : /* }}} */
     884                 : 
     885                 : /* {{{ php_any_addr
     886                 :  * Fills the any (wildcard) address into php_sockaddr_storage
     887                 :  */
     888                 : PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
     889               0 : {
     890               0 :         memset(addr, 0, sizeof(php_sockaddr_storage));
     891               0 :         switch (family) {
     892                 : #if HAVE_IPV6
     893                 :         case AF_INET6: {
     894               0 :                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
     895               0 :                 sin6->sin6_family = AF_INET6;
     896               0 :                 sin6->sin6_port = htons(port);
     897               0 :                 sin6->sin6_addr = in6addr_any;
     898               0 :                 break;
     899                 :         }
     900                 : #endif
     901                 :         case AF_INET: {
     902               0 :                 struct sockaddr_in *sin = (struct sockaddr_in *) addr;
     903               0 :                 sin->sin_family = AF_INET;
     904               0 :                 sin->sin_port = htons(port);
     905               0 :                 sin->sin_addr.s_addr = htonl(INADDR_ANY);
     906                 :                 break;
     907                 :         }
     908                 :         }
     909               0 : }
     910                 : /* }}} */
     911                 : 
     912                 : /* {{{ php_sockaddr_size
     913                 :  * Returns the size of struct sockaddr_xx for the family
     914                 :  */
     915                 : PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
     916               0 : {
     917               0 :         switch (((struct sockaddr *)addr)->sa_family) {
     918                 :         case AF_INET:
     919               0 :                 return sizeof(struct sockaddr_in);
     920                 : #if HAVE_IPV6
     921                 :         case AF_INET6:
     922               0 :                 return sizeof(struct sockaddr_in6);
     923                 : #endif
     924                 : #ifdef AF_UNIX
     925                 :         case AF_UNIX:
     926               0 :                 return sizeof(struct sockaddr_un);
     927                 : #endif
     928                 :         default:
     929               0 :                 return 0;
     930                 :         }
     931                 : }
     932                 : /* }}} */
     933                 : 
     934                 : /* Given a socket error code, if buf == NULL:
     935                 :  *   emallocs storage for the error message and returns
     936                 :  * else
     937                 :  *   sprintf message into provided buffer and returns buf
     938                 :  */
     939                 : /* {{{ php_socket_strerror */
     940                 : PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
     941               0 : {
     942                 : #ifndef PHP_WIN32
     943                 :         char *errstr;
     944                 : 
     945               0 :         errstr = strerror(err);
     946               0 :         if (buf == NULL) {
     947               0 :                 buf = estrdup(errstr);
     948                 :         } else {
     949               0 :                 strncpy(buf, errstr, bufsize);
     950                 :         }
     951               0 :         return buf;
     952                 : #else
     953                 :         char *sysbuf;
     954                 :         int free_it = 1;
     955                 : 
     956                 :         if (!FormatMessage(
     957                 :                                 FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     958                 :                                 FORMAT_MESSAGE_FROM_SYSTEM |
     959                 :                                 FORMAT_MESSAGE_IGNORE_INSERTS,
     960                 :                                 NULL,
     961                 :                                 err,
     962                 :                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     963                 :                                 (LPTSTR)&sysbuf,
     964                 :                                 0,
     965                 :                                 NULL)) {
     966                 :                 free_it = 0;
     967                 :                 sysbuf = "Unknown Error";
     968                 :         }
     969                 : 
     970                 :         if (buf == NULL) {
     971                 :                 buf = estrdup(sysbuf);
     972                 :         } else {
     973                 :                 strncpy(buf, sysbuf, bufsize);
     974                 :         }
     975                 : 
     976                 :         if (free_it) {
     977                 :                 LocalFree(sysbuf);
     978                 :         }
     979                 : 
     980                 :         return buf;
     981                 : #endif
     982                 : }
     983                 : /* }}} */
     984                 : 
     985                 : /* deprecated */
     986                 : PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC TSRMLS_DC)
     987               0 : {
     988                 :         php_stream *stream;
     989                 :         php_netstream_data_t *sock;
     990                 : 
     991               0 :         sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
     992               0 :         memset(sock, 0, sizeof(php_netstream_data_t));
     993                 : 
     994               0 :         sock->is_blocked = 1;
     995               0 :         sock->timeout.tv_sec = FG(default_socket_timeout);
     996               0 :         sock->timeout.tv_usec = 0;
     997               0 :         sock->socket = socket;
     998                 : 
     999               0 :         stream = php_stream_alloc_rel(&php_stream_generic_socket_ops, sock, persistent_id, "r+");
    1000                 : 
    1001               0 :         if (stream == NULL) {
    1002               0 :                 pefree(sock, persistent_id ? 1 : 0);
    1003                 :         } else {
    1004               0 :                 stream->flags |= PHP_STREAM_FLAG_AVOID_BLOCKING;
    1005                 :         }
    1006                 : 
    1007               0 :         return stream;
    1008                 : }
    1009                 : 
    1010                 : PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short port,
    1011                 :                 int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC TSRMLS_DC)
    1012               0 : {
    1013                 :         char *res;
    1014                 :         long reslen;
    1015                 :         php_stream *stream;
    1016                 : 
    1017               0 :         reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
    1018                 : 
    1019               0 :         stream = php_stream_xport_create(res, reslen, ENFORCE_SAFE_MODE | REPORT_ERRORS,
    1020                 :                         STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);
    1021                 : 
    1022               0 :         efree(res);
    1023                 : 
    1024               0 :         return stream;
    1025                 : }
    1026                 : 
    1027                 : PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC)
    1028               0 : {
    1029               0 :       int ret = SUCCESS;
    1030                 :       int flags;
    1031               0 :       int myflag = 0;
    1032                 : 
    1033                 : #ifdef PHP_WIN32
    1034                 :       /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
    1035                 :           flags = !block;
    1036                 :           if (ioctlsocket(socketd, FIONBIO, &flags)==SOCKET_ERROR){
    1037                 :                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", WSAGetLastError());
    1038                 :                   ret = FALSE;
    1039                 :       }
    1040                 : #else
    1041               0 :       flags = fcntl(socketd, F_GETFL);
    1042                 : #ifdef O_NONBLOCK
    1043               0 :       myflag = O_NONBLOCK; /* POSIX version */
    1044                 : #elif defined(O_NDELAY)
    1045                 :       myflag = O_NDELAY;   /* old non-POSIX version */
    1046                 : #endif
    1047               0 :       if (!block) {
    1048               0 :               flags |= myflag;
    1049                 :       } else {
    1050               0 :                 flags &= ~myflag;
    1051                 :       }
    1052               0 :       fcntl(socketd, F_SETFL, flags);
    1053                 : #endif
    1054               0 :       return ret;
    1055                 : }
    1056                 : 
    1057                 : PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
    1058               0 : {
    1059                 :         TSRMLS_FETCH();
    1060                 : 
    1061                 : #ifdef PHP_WIN32
    1062                 :         php_error_docref(NULL TSRMLS_CC, E_WARNING,
    1063                 :                 "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
    1064                 :                 "If this binary is from an official www.php.net package, file a bug report\n"
    1065                 :                 "at http://bugs.php.net, including the following information:\n"
    1066                 :                 "FD_SETSIZE=%d, but you are using %d.\n"
    1067                 :                 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
    1068                 :                 "to match to maximum number of sockets each script will work with at\n"
    1069                 :                 "one time, in order to avoid seeing this error again at a later date.",
    1070                 :                 FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
    1071                 : #else
    1072               0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING,
    1073                 :                 "You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
    1074                 :                 "It is set to %d, but you have descriptors numbered at least as high as %d.\n"
    1075                 :                 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
    1076                 :                 "to equal the maximum number of open files supported by your system,\n"
    1077                 :                 "in order to avoid seeing this error again at a later date.",
    1078                 :                 FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
    1079                 : #endif
    1080               0 : }
    1081                 : 
    1082                 : #if defined(PHP_USE_POLL_2_EMULATION)
    1083                 : 
    1084                 : /* emulate poll(2) using select(2), safely. */
    1085                 : 
    1086                 : PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
    1087                 : {
    1088                 :         fd_set rset, wset, eset;
    1089                 :         php_socket_t max_fd = SOCK_ERR;
    1090                 :         unsigned int i, n;
    1091                 :         struct timeval tv;
    1092                 : 
    1093                 :         /* check the highest numbered descriptor */
    1094                 :         for (i = 0; i < nfds; i++) {
    1095                 :                 if (ufds[i].fd > max_fd)
    1096                 :                         max_fd = ufds[i].fd;
    1097                 :         }
    1098                 : 
    1099                 :         PHP_SAFE_MAX_FD(max_fd, nfds + 1);
    1100                 : 
    1101                 :         FD_ZERO(&rset);
    1102                 :         FD_ZERO(&wset);
    1103                 :         FD_ZERO(&eset);
    1104                 : 
    1105                 :         for (i = 0; i < nfds; i++) {
    1106                 :                 if (ufds[i].events & PHP_POLLREADABLE) {
    1107                 :                         PHP_SAFE_FD_SET(ufds[i].fd, &rset);
    1108                 :                 }
    1109                 :                 if (ufds[i].events & POLLOUT) {
    1110                 :                         PHP_SAFE_FD_SET(ufds[i].fd, &wset);
    1111                 :                 }
    1112                 :                 if (ufds[i].events & POLLPRI) {
    1113                 :                         PHP_SAFE_FD_SET(ufds[i].fd, &eset);
    1114                 :                 }
    1115                 :         }
    1116                 : 
    1117                 :         if (timeout >= 0) {
    1118                 :                 tv.tv_sec = timeout / 1000;
    1119                 :                 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
    1120                 :         }
    1121                 :         n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL);
    1122                 : 
    1123                 :         if (n >= 0) {
    1124                 :                 for (i = 0; i < nfds; i++) {
    1125                 :                         ufds[i].revents = 0;
    1126                 : 
    1127                 :                         if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) {
    1128                 :                                 /* could be POLLERR or POLLHUP but can't tell without probing */
    1129                 :                                 ufds[i].revents |= POLLIN;
    1130                 :                         }
    1131                 :                         if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) {
    1132                 :                                 ufds[i].revents |= POLLOUT;
    1133                 :                         }
    1134                 :                         if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) {
    1135                 :                                 ufds[i].revents |= POLLPRI;
    1136                 :                         }
    1137                 :                 }
    1138                 :         }
    1139                 :         return n;
    1140                 : }
    1141                 : 
    1142                 : #endif
    1143                 : 
    1144                 : 
    1145                 : /*
    1146                 :  * Local variables:
    1147                 :  * tab-width: 8
    1148                 :  * c-basic-offset: 8
    1149                 :  * End:
    1150                 :  * vim600: sw=4 ts=4 fdm=marker
    1151                 :  * vim<600: sw=4 ts=4
    1152                 :  */

Generated by: LTP GCOV extension version 1.5