PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - main - network.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 197 359 54.9 %
Date: 2014-12-15 Functions: 13 18 72.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Mon, 15 Dec 2014 17:02:55 +0000 (3 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.