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

Generated by: LCOV version 1.10

Generated at Thu, 27 Aug 2015 06:06:24 +0000 (7 days ago)

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