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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_3/main - network.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 358
Code covered: 53.9 % Executed lines: 193
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Author: Stig Venaas <venaas@uninett.no>                              |
      16                 :    | Streams work by Wez Furlong <wez@thebrainroom.com>                   |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /* $Id: network.c 289019 2009-09-30 20:48:41Z iliaa $ */
      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                 : static void php_network_freeaddresses(struct sockaddr **sal)
     152             139 : {
     153                 :         struct sockaddr **sap;
     154                 : 
     155             139 :         if (sal == NULL)
     156               0 :                 return;
     157             278 :         for (sap = sal; *sap != NULL; sap++)
     158             139 :                 efree(*sap);
     159             139 :         efree(sal);
     160                 : }
     161                 : /* }}} */
     162                 : 
     163                 : /* {{{ php_network_getaddresses
     164                 :  * Returns number of addresses, 0 for none/error
     165                 :  */
     166                 : static int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
     167             149 : {
     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             149 :         if (host == NULL) {
     181               0 :                 return 0;
     182                 :         }
     183                 : #if HAVE_GETADDRINFO
     184             149 :         memset(&hints, '\0', sizeof(hints));
     185                 :                 
     186             149 :         hints.ai_family = AF_INET; /* default to regular inet (see below) */
     187             149 :         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             149 :         if (ipv6_borked == -1) {
     197                 :                 int s;
     198                 : 
     199              71 :                 s = socket(PF_INET6, SOCK_DGRAM, 0);
     200              71 :                 if (s == SOCK_ERR) {
     201               0 :                         ipv6_borked = 1;
     202                 :                 } else {
     203              71 :                         ipv6_borked = 0;
     204              71 :                         closesocket(s);
     205                 :                 }
     206                 :         }
     207             149 :         hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC;
     208                 : # endif
     209                 :                 
     210             149 :         if ((n = getaddrinfo(host, NULL, &hints, &res))) {
     211              10 :                 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               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
     216                 :                 }
     217              10 :                 return 0;
     218             139 :         } 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             139 :         sai = res;
     229             139 :         for (n = 1; (sai = sai->ai_next) != NULL; n++)
     230                 :                 ;
     231                 :         
     232             139 :         *sal = safe_emalloc((n + 1), sizeof(*sal), 0);
     233             139 :         sai = res;
     234             139 :         sap = *sal;
     235                 :         
     236                 :         do {
     237             139 :                 *sap = emalloc(sai->ai_addrlen);
     238             139 :                 memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
     239             139 :                 sap++;
     240             139 :         } while ((sai = sai->ai_next) != NULL);
     241                 :         
     242             139 :         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             139 :         *sap = NULL;
     269             139 :         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                 : 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            1745 : {
     308                 : #if HAVE_NON_BLOCKING_CONNECT
     309                 :         php_non_blocking_flags_t orig_flags;
     310                 :         int n;
     311            1745 :         int error = 0;
     312                 :         socklen_t len;
     313            1745 :         int ret = 0;
     314                 : 
     315            1745 :         SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
     316                 :         
     317            1745 :         if ((n = connect(sockfd, addr, addrlen)) != 0) {
     318              69 :                 error = php_socket_errno();
     319                 : 
     320              69 :                 if (error_code) {
     321              41 :                         *error_code = error;
     322                 :                 }
     323                 : 
     324              69 :                 if (error != EINPROGRESS) {
     325               0 :                         if (error_string) {
     326               0 :                                 *error_string = php_socket_strerror(error, NULL, 0);
     327                 :                         }
     328                 : 
     329               0 :                         return -1;
     330                 :                 }
     331              69 :                 if (asynchronous && error == EINPROGRESS) {
     332                 :                         /* this is fine by us */
     333               1 :                         return 0;
     334                 :                 }
     335                 :         }
     336                 : 
     337            1744 :         if (n == 0) {
     338            1676 :                 goto ok;
     339                 :         }
     340                 : 
     341              68 :         if ((n = php_pollfd_for(sockfd, PHP_POLLREADABLE|POLLOUT, timeout)) == 0) {
     342               0 :                 error = PHP_TIMEOUT_ERROR_VALUE;
     343                 :         }
     344                 : 
     345              68 :         if (n > 0) {
     346              68 :                 len = sizeof(error);
     347                 :                 /*
     348                 :                    BSD-derived systems set errno correctly
     349                 :                    Solaris returns -1 from getsockopt in case of error
     350                 :                    */
     351              68 :                 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
     352               0 :                         ret = -1;
     353                 :                 }
     354                 :         } else {
     355                 :                 /* whoops: sockfd has disappeared */
     356               0 :                 ret = -1;
     357                 :         }
     358                 : 
     359            1744 : ok:
     360            1744 :         if (!asynchronous) {
     361                 :                 /* back to blocking mode */
     362            1744 :                 RESTORE_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
     363                 :         }
     364                 : 
     365            1744 :         if (error_code) {
     366            1716 :                 *error_code = error;
     367                 :         }
     368                 : 
     369            1744 :         if (error && error_string) {
     370               5 :                 *error_string = php_socket_strerror(error, NULL, 0);
     371               5 :                 ret = -1;
     372                 :         }
     373            1744 :         return ret;
     374                 : #else
     375                 :         if (asynchronous) {
     376                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Asynchronous connect() not supported on this platform");
     377                 :         }
     378                 :         return (connect(sockfd, addr, addrlen) == 0) ? 0 : -1;
     379                 : #endif
     380                 : }
     381                 : /* }}} */
     382                 : 
     383                 : /* {{{ sub_times */
     384                 : static inline void sub_times(struct timeval a, struct timeval b, struct timeval *result)
     385               5 : {
     386               5 :         result->tv_usec = a.tv_usec - b.tv_usec;
     387               5 :         if (result->tv_usec < 0L) {
     388               4 :                 a.tv_sec--;
     389               4 :                 result->tv_usec += 1000000L;
     390                 :         }
     391               5 :         result->tv_sec = a.tv_sec - b.tv_sec;
     392               5 :         if (result->tv_sec < 0L) {
     393               0 :                 result->tv_sec++;
     394               0 :                 result->tv_usec -= 1000000L;
     395                 :         }
     396               5 : }
     397                 : /* }}} */
     398                 : 
     399                 : /* Bind to a local IP address.
     400                 :  * Returns the bound socket, or -1 on failure.
     401                 :  * */
     402                 : /* {{{ php_network_bind_socket_to_local_addr */
     403                 : php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port,
     404                 :                 int socktype, char **error_string, int *error_code
     405                 :                 TSRMLS_DC)
     406              65 : {
     407              65 :         int num_addrs, n, err = 0;
     408                 :         php_socket_t sock;
     409                 :         struct sockaddr **sal, **psal, *sa;
     410                 :         socklen_t socklen;
     411                 : 
     412              65 :         num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
     413                 : 
     414              65 :         if (num_addrs == 0) {
     415                 :                 /* could not resolve address(es) */
     416               0 :                 return -1;
     417                 :         }
     418                 : 
     419              65 :         for (sal = psal; *sal != NULL; sal++) {
     420              65 :                 sa = *sal;
     421                 : 
     422                 :                 /* create a socket for this address */
     423              65 :                 sock = socket(sa->sa_family, socktype, 0);
     424                 : 
     425              65 :                 if (sock == SOCK_ERR) {
     426               0 :                         continue;
     427                 :                 }
     428                 : 
     429              65 :                 switch (sa->sa_family) {
     430                 : #if HAVE_GETADDRINFO && HAVE_IPV6
     431                 :                         case AF_INET6:
     432               2 :                                 ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
     433               2 :                                 ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
     434               2 :                                 socklen = sizeof(struct sockaddr_in6);
     435               2 :                                 break;
     436                 : #endif
     437                 :                         case AF_INET:
     438              63 :                                 ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
     439              63 :                                 ((struct sockaddr_in *)sa)->sin_port = htons(port);
     440              63 :                                 socklen = sizeof(struct sockaddr_in);
     441              63 :                                 break;
     442                 :                         default:
     443                 :                                 /* Unknown family */
     444               0 :                                 socklen = 0;
     445               0 :                                 sa = NULL;
     446                 :                 }
     447                 : 
     448              65 :                 if (sa) {
     449                 :                         /* attempt to bind */
     450                 :                 
     451                 : #ifdef SO_REUSEADDR
     452                 :                         {
     453              65 :                                 int val = 1;
     454              65 :                                 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
     455                 :                         }
     456                 : #endif
     457                 :                         
     458              65 :                         n = bind(sock, sa, socklen);
     459                 : 
     460              65 :                         if (n != SOCK_CONN_ERR) {
     461              65 :                                 goto bound;
     462                 :                         }
     463                 : 
     464               0 :                         err = php_socket_errno();
     465                 :                 }
     466                 : 
     467               0 :                 closesocket(sock);
     468                 :         }
     469               0 :         sock = -1;
     470                 : 
     471               0 :         if (error_code) {
     472               0 :                 *error_code = err;
     473                 :         }
     474               0 :         if (error_string) {
     475               0 :                 *error_string = php_socket_strerror(err, NULL, 0);
     476                 :         }
     477                 :         
     478              65 : bound:
     479                 : 
     480              65 :         php_network_freeaddresses(psal);
     481                 :         
     482              65 :         return sock;
     483                 :         
     484                 : }
     485                 : /* }}} */
     486                 : 
     487                 : PHPAPI int php_network_parse_network_address_with_port(const char *addr, long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC)
     488               0 : {
     489                 :         char *colon;
     490                 :         char *tmp;
     491               0 :         int ret = FAILURE;
     492                 :         short port;
     493               0 :         struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
     494                 :         struct sockaddr **psal;
     495                 :         int n;
     496               0 :         char *errstr = NULL;
     497                 : #if HAVE_IPV6
     498               0 :         struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
     499                 : #endif
     500                 : 
     501               0 :         if (*addr == '[') {
     502               0 :                 colon = memchr(addr + 1, ']', addrlen-1);
     503               0 :                 if (!colon || colon[1] != ':') {
     504               0 :                         return FAILURE;
     505                 :                 }
     506               0 :                 port = atoi(colon + 2);
     507               0 :                 addr++;
     508                 :         } else {
     509               0 :                 colon = memchr(addr, ':', addrlen);
     510               0 :                 if (!colon) {
     511               0 :                         return FAILURE;
     512                 :                 }
     513               0 :                 port = atoi(colon + 1);
     514                 :         }
     515                 : 
     516               0 :         tmp = estrndup(addr, colon - addr);
     517                 : 
     518                 :         /* first, try interpreting the address as a numeric address */
     519                 : 
     520                 : #if HAVE_IPV6 && HAVE_INET_PTON
     521               0 :         if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) {
     522               0 :                 in6->sin6_port = htons(port);
     523               0 :                 in6->sin6_family = AF_INET6;
     524               0 :                 *sl = sizeof(struct sockaddr_in6);
     525               0 :                 ret = SUCCESS;
     526               0 :                 goto out;
     527                 :         }
     528                 : #endif
     529               0 :         if (inet_aton(tmp, &in4->sin_addr) > 0) {
     530               0 :                 in4->sin_port = htons(port);
     531               0 :                 in4->sin_family = AF_INET;
     532               0 :                 *sl = sizeof(struct sockaddr_in);
     533               0 :                 ret = SUCCESS;
     534               0 :                 goto out;
     535                 :         }
     536                 : 
     537                 :         /* looks like we'll need to resolve it */
     538               0 :         n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr TSRMLS_CC);
     539                 : 
     540               0 :         if (n == 0) {
     541               0 :                 if (errstr) {
     542               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr);
     543               0 :                         STR_FREE(errstr);
     544                 :                 }
     545               0 :                 goto out;
     546                 :         }
     547                 : 
     548                 :         /* copy the details from the first item */
     549               0 :         switch ((*psal)->sa_family) {
     550                 : #if HAVE_GETADDRINFO && HAVE_IPV6
     551                 :                 case AF_INET6:
     552               0 :                         *in6 = **(struct sockaddr_in6**)psal;
     553               0 :                         in6->sin6_port = htons(port);
     554               0 :                         *sl = sizeof(struct sockaddr_in6);
     555               0 :                         ret = SUCCESS;
     556               0 :                         break;
     557                 : #endif
     558                 :                 case AF_INET:
     559               0 :                         *in4 = **(struct sockaddr_in**)psal;
     560               0 :                         in4->sin_port = htons(port);
     561               0 :                         *sl = sizeof(struct sockaddr_in);
     562               0 :                         ret = SUCCESS;
     563                 :                         break;
     564                 :         }
     565                 : 
     566               0 :         php_network_freeaddresses(psal);
     567                 : 
     568               0 : out:
     569               0 :         STR_FREE(tmp);
     570               0 :         return ret;
     571                 : }
     572                 : 
     573                 : 
     574                 : PHPAPI void php_network_populate_name_from_sockaddr(
     575                 :                 /* input address */
     576                 :                 struct sockaddr *sa, socklen_t sl,
     577                 :                 /* output readable address */
     578                 :                 char **textaddr, long *textaddrlen,
     579                 :                 /* output address */
     580                 :                 struct sockaddr **addr,
     581                 :                 socklen_t *addrlen
     582                 :                 TSRMLS_DC)
     583              41 : {
     584              41 :         if (addr) {
     585               0 :                 *addr = emalloc(sl);
     586               0 :                 memcpy(*addr, sa, sl);
     587               0 :                 *addrlen = sl;
     588                 :         }
     589                 : 
     590              41 :         if (textaddr) {
     591                 : #if HAVE_IPV6 && HAVE_INET_NTOP
     592                 :                 char abuf[256];
     593                 : #endif
     594               0 :                 char *buf = NULL;
     595                 : 
     596               0 :                 switch (sa->sa_family) {
     597                 :                         case AF_INET:
     598                 :                                 /* generally not thread safe, but it *is* thread safe under win32 */
     599               0 :                                 buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
     600               0 :                                 if (buf) {
     601               0 :                                         *textaddrlen = spprintf(textaddr, 0, "%s:%d", 
     602                 :                                                 buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
     603                 :                                 }
     604                 : 
     605               0 :                                 break;
     606                 : 
     607                 : #if HAVE_IPV6 && HAVE_INET_NTOP
     608                 :                         case AF_INET6:
     609               0 :                                 buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
     610               0 :                                 if (buf) {
     611               0 :                                         *textaddrlen = spprintf(textaddr, 0, "%s:%d", 
     612                 :                                                 buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
     613                 :                                 }
     614                 : 
     615               0 :                                 break;
     616                 : #endif
     617                 : #ifdef AF_UNIX
     618                 :                         case AF_UNIX:
     619                 :                                 {
     620               0 :                                         struct sockaddr_un *ua = (struct sockaddr_un*)sa;
     621                 : 
     622               0 :                                         if (ua->sun_path[0] == '\0') {
     623                 :                                                 /* abstract name */
     624               0 :                                                 int len = strlen(ua->sun_path + 1) + 1;
     625               0 :                                                 *textaddrlen = len;
     626               0 :                                                 *textaddr = emalloc(len + 1);
     627               0 :                                                 memcpy(*textaddr, ua->sun_path, len);
     628               0 :                                                 (*textaddr)[len] = '\0';
     629                 :                                         } else {
     630               0 :                                                 *textaddrlen = strlen(ua->sun_path);
     631               0 :                                                 *textaddr = estrndup(ua->sun_path, *textaddrlen);
     632                 :                                         }
     633                 :                                 }
     634                 :                                 break;
     635                 : #endif
     636                 : 
     637                 :                 }
     638                 : 
     639                 :         }
     640              41 : }
     641                 : 
     642                 : PHPAPI int php_network_get_peer_name(php_socket_t sock, 
     643                 :                 char **textaddr, long *textaddrlen,
     644                 :                 struct sockaddr **addr,
     645                 :                 socklen_t *addrlen
     646                 :                 TSRMLS_DC)
     647               0 : {
     648                 :         php_sockaddr_storage sa;
     649               0 :         socklen_t sl = sizeof(sa);
     650               0 :         memset(&sa, 0, sizeof(sa));
     651                 :         
     652               0 :         if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
     653               0 :                 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
     654                 :                                 textaddr, textaddrlen,
     655                 :                                 addr, addrlen
     656                 :                                 TSRMLS_CC);
     657               0 :                 return 0;
     658                 :         }
     659               0 :         return -1;
     660                 : }
     661                 : 
     662                 : PHPAPI int php_network_get_sock_name(php_socket_t sock, 
     663                 :                 char **textaddr, long *textaddrlen,
     664                 :                 struct sockaddr **addr,
     665                 :                 socklen_t *addrlen
     666                 :                 TSRMLS_DC)
     667               0 : {
     668                 :         php_sockaddr_storage sa;
     669               0 :         socklen_t sl = sizeof(sa);
     670               0 :         memset(&sa, 0, sizeof(sa));
     671                 :         
     672               0 :         if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
     673               0 :                 php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
     674                 :                                 textaddr, textaddrlen,
     675                 :                                 addr, addrlen
     676                 :                                 TSRMLS_CC);
     677               0 :                 return 0;
     678                 :         }
     679               0 :         return -1;
     680                 : 
     681                 : }
     682                 : 
     683                 : 
     684                 : /* Accept a client connection from a server socket,
     685                 :  * using an optional timeout.
     686                 :  * Returns the peer address in addr/addrlen (it will emalloc
     687                 :  * these, so be sure to efree the result).
     688                 :  * If you specify textaddr/textaddrlen, a text-printable
     689                 :  * version of the address will be emalloc'd and returned.
     690                 :  * */
     691                 : 
     692                 : /* {{{ php_network_accept_incoming */
     693                 : PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
     694                 :                 char **textaddr, long *textaddrlen,
     695                 :                 struct sockaddr **addr,
     696                 :                 socklen_t *addrlen,
     697                 :                 struct timeval *timeout,
     698                 :                 char **error_string,
     699                 :                 int *error_code
     700                 :                 TSRMLS_DC)
     701              41 : {
     702              41 :         php_socket_t clisock = -1;
     703              41 :         int error = 0, n;
     704                 :         php_sockaddr_storage sa;
     705                 :         socklen_t sl;
     706                 :                 
     707              41 :         n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout);
     708                 : 
     709              41 :         if (n == 0) {
     710               0 :                 error = PHP_TIMEOUT_ERROR_VALUE;
     711              41 :         } else if (n == -1) {
     712               0 :                 error = php_socket_errno();
     713                 :         } else {
     714              41 :                 sl = sizeof(sa);
     715                 : 
     716              41 :                 clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);
     717                 : 
     718              41 :                 if (clisock != SOCK_ERR) {
     719              41 :                         php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
     720                 :                                         textaddr, textaddrlen,
     721                 :                                         addr, addrlen
     722                 :                                         TSRMLS_CC);
     723                 :                 } else {
     724               0 :                         error = php_socket_errno();
     725                 :                 }
     726                 :         }
     727                 :         
     728              41 :         if (error_code) {
     729              41 :                 *error_code = error;
     730                 :         }
     731              41 :         if (error_string) {
     732              41 :                 *error_string = php_socket_strerror(error, NULL, 0);
     733                 :         }
     734                 :         
     735              41 :         return clisock;
     736                 : }
     737                 : /* }}} */
     738                 :         
     739                 : 
     740                 : 
     741                 : /* Connect to a remote host using an interruptible connect with optional timeout.
     742                 :  * Optionally, the connect can be made asynchronously, which will implicitly
     743                 :  * enable non-blocking mode on the socket.
     744                 :  * Returns the connected (or connecting) socket, or -1 on failure.
     745                 :  * */
     746                 : 
     747                 : /* {{{ php_network_connect_socket_to_host */
     748                 : php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
     749                 :                 int socktype, int asynchronous, struct timeval *timeout, char **error_string,
     750                 :                 int *error_code, char *bindto, unsigned short bindport 
     751                 :                 TSRMLS_DC)
     752              84 : {
     753              84 :         int num_addrs, n, fatal = 0;
     754                 :         php_socket_t sock;
     755                 :         struct sockaddr **sal, **psal, *sa;
     756                 :         struct timeval working_timeout;
     757                 :         socklen_t socklen;
     758                 : #if HAVE_GETTIMEOFDAY
     759                 :         struct timeval limit_time, time_now;
     760                 : #endif
     761                 : 
     762              84 :         num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
     763                 : 
     764              84 :         if (num_addrs == 0) {
     765                 :                 /* could not resolve address(es) */
     766              10 :                 return -1;
     767                 :         }
     768                 : 
     769              74 :         if (timeout) {
     770              74 :                 memcpy(&working_timeout, timeout, sizeof(working_timeout));
     771                 : #if HAVE_GETTIMEOFDAY
     772              74 :                 gettimeofday(&limit_time, NULL);
     773              74 :                 limit_time.tv_sec += working_timeout.tv_sec;
     774              74 :                 limit_time.tv_usec += working_timeout.tv_usec;
     775              74 :                 if (limit_time.tv_usec >= 1000000) {
     776               1 :                         limit_time.tv_usec -= 1000000;
     777               1 :                         limit_time.tv_sec++;
     778                 :                 }
     779                 : #endif
     780                 :         }
     781                 : 
     782              79 :         for (sal = psal; !fatal && *sal != NULL; sal++) {
     783              74 :                 sa = *sal;
     784                 : 
     785                 :                 /* create a socket for this address */
     786              74 :                 sock = socket(sa->sa_family, socktype, 0);
     787                 : 
     788              74 :                 if (sock == SOCK_ERR) {
     789               0 :                         continue;
     790                 :                 }
     791                 : 
     792              74 :                 switch (sa->sa_family) {
     793                 : #if HAVE_GETADDRINFO && HAVE_IPV6
     794                 :                         case AF_INET6:
     795              12 :                                 if (!bindto || strchr(bindto, ':')) {
     796               6 :                                         ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
     797               6 :                                         ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
     798               6 :                                         socklen = sizeof(struct sockaddr_in6);
     799                 :                                 } else {
     800               0 :                                         socklen = 0;
     801               0 :                                         sa = NULL;
     802                 :                                 }
     803               6 :                                 break;
     804                 : #endif
     805                 :                         case AF_INET:
     806              68 :                                 ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
     807              68 :                                 ((struct sockaddr_in *)sa)->sin_port = htons(port);
     808              68 :                                 socklen = sizeof(struct sockaddr_in);
     809              68 :                                 break;
     810                 :                         default:
     811                 :                                 /* Unknown family */
     812               0 :                                 socklen = 0;
     813               0 :                                 sa = NULL;
     814                 :                 }
     815                 : 
     816              74 :                 if (sa) {
     817                 :                         /* make a connection attempt */
     818                 : 
     819              74 :                         if (bindto) {
     820               0 :                                 struct sockaddr *local_address = NULL;
     821               0 :                                 int local_address_len = 0;
     822                 : 
     823               0 :                                 if (sa->sa_family == AF_INET) {
     824               0 :                                         struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));
     825                 : 
     826               0 :                                         local_address = (struct sockaddr*)in4;
     827               0 :                                         local_address_len = sizeof(struct sockaddr_in);
     828                 :                                 
     829               0 :                                         in4->sin_family = sa->sa_family;
     830               0 :                                         in4->sin_port = htons(bindport);
     831               0 :                                         if (!inet_aton(bindto, &in4->sin_addr)) {
     832               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
     833               0 :                                                 goto skip_bind;
     834                 :                                         }
     835               0 :                                         memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
     836                 :                                 }
     837                 : #if HAVE_IPV6 && HAVE_INET_PTON
     838                 :                                  else { /* IPV6 */
     839               0 :                                         struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));
     840                 : 
     841               0 :                                         local_address = (struct sockaddr*)in6;
     842               0 :                                         local_address_len = sizeof(struct sockaddr_in6);
     843                 :                                 
     844               0 :                                         in6->sin6_family = sa->sa_family;
     845               0 :                                         in6->sin6_port = htons(bindport);
     846               0 :                                         if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
     847               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
     848               0 :                                                 goto skip_bind;
     849                 :                                         }
     850                 :                                 }
     851                 : #endif
     852               0 :                                 if (!local_address || bind(sock, local_address, local_address_len)) {
     853               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
     854                 :                                 }
     855               0 : skip_bind:
     856               0 :                                 if (local_address) {
     857               0 :                                         efree(local_address);
     858                 :                                 }
     859                 :                         }
     860                 :                         /* free error string recieved during previous iteration (if any) */
     861              74 :                         if (error_string && *error_string) {
     862               0 :                                 efree(*error_string);
     863               0 :                                 *error_string = NULL;
     864                 :                         }
     865                 :                         
     866              74 :                         n = php_network_connect_socket(sock, sa, socklen, asynchronous,
     867                 :                                         timeout ? &working_timeout : NULL,
     868                 :                                         error_string, error_code);
     869                 : 
     870              74 :                         if (n != -1) {
     871              69 :                                 goto connected;
     872                 :                         }
     873                 : 
     874                 :                         /* adjust timeout for next attempt */
     875                 : #if HAVE_GETTIMEOFDAY
     876               5 :                         if (timeout) {
     877               5 :                                 gettimeofday(&time_now, NULL);
     878                 : 
     879               5 :                                 if (timercmp(&time_now, &limit_time, >=)) {
     880                 :                                         /* time limit expired; don't attempt any further connections */
     881               0 :                                         fatal = 1;
     882                 :                                 } else {
     883                 :                                         /* work out remaining time */
     884               5 :                                         sub_times(limit_time, time_now, &working_timeout);
     885                 :                                 }
     886                 :                         }
     887                 : #else
     888                 :                         if (error_code && *error_code == PHP_TIMEOUT_ERROR_VALUE) {
     889                 :                                 /* Don't even bother trying to connect to the next alternative;
     890                 :                                  * we have no way to determine how long we have already taken
     891                 :                                  * and it is quite likely that the next attempt will fail too. */
     892                 :                                 fatal = 1;
     893                 :                         } else {
     894                 :                                 /* re-use the same initial timeout.
     895                 :                                  * Not the best thing, but in practice it should be good-enough */
     896                 :                                 if (timeout) {
     897                 :                                         memcpy(&working_timeout, timeout, sizeof(working_timeout));
     898                 :                                 }
     899                 :                         }
     900                 : #endif
     901                 :                 }
     902                 : 
     903               5 :                 closesocket(sock);
     904                 :         }
     905               5 :         sock = -1;
     906                 : 
     907              74 : connected:
     908                 : 
     909              74 :         php_network_freeaddresses(psal);
     910                 :         
     911              74 :         return sock;
     912                 : }
     913                 : /* }}} */
     914                 : 
     915                 : /* {{{ php_any_addr
     916                 :  * Fills the any (wildcard) address into php_sockaddr_storage
     917                 :  */
     918                 : PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
     919              21 : {
     920              21 :         memset(addr, 0, sizeof(php_sockaddr_storage));
     921              21 :         switch (family) {
     922                 : #if HAVE_IPV6
     923                 :         case AF_INET6: {
     924               0 :                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
     925               0 :                 sin6->sin6_family = AF_INET6;
     926               0 :                 sin6->sin6_port = htons(port);
     927               0 :                 sin6->sin6_addr = in6addr_any;
     928               0 :                 break;
     929                 :         }
     930                 : #endif
     931                 :         case AF_INET: {
     932              21 :                 struct sockaddr_in *sin = (struct sockaddr_in *) addr;
     933              21 :                 sin->sin_family = AF_INET;
     934              21 :                 sin->sin_port = htons(port);
     935              21 :                 sin->sin_addr.s_addr = htonl(INADDR_ANY);
     936                 :                 break;
     937                 :         }
     938                 :         }
     939              21 : }
     940                 : /* }}} */
     941                 : 
     942                 : /* {{{ php_sockaddr_size
     943                 :  * Returns the size of struct sockaddr_xx for the family
     944                 :  */
     945                 : PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
     946              21 : {
     947              21 :         switch (((struct sockaddr *)addr)->sa_family) {
     948                 :         case AF_INET:
     949              21 :                 return sizeof(struct sockaddr_in);
     950                 : #if HAVE_IPV6
     951                 :         case AF_INET6:
     952               0 :                 return sizeof(struct sockaddr_in6);
     953                 : #endif
     954                 : #ifdef AF_UNIX
     955                 :         case AF_UNIX:
     956               0 :                 return sizeof(struct sockaddr_un);
     957                 : #endif
     958                 :         default:
     959               0 :                 return 0;
     960                 :         }
     961                 : }
     962                 : /* }}} */
     963                 : 
     964                 : /* Given a socket error code, if buf == NULL:
     965                 :  *   emallocs storage for the error message and returns
     966                 :  * else
     967                 :  *   sprintf message into provided buffer and returns buf
     968                 :  */
     969                 : /* {{{ php_socket_strerror */
     970                 : PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
     971              58 : {
     972                 : #ifndef PHP_WIN32
     973                 :         char *errstr;
     974                 : 
     975              58 :         errstr = strerror(err);
     976              58 :         if (buf == NULL) {
     977              58 :                 buf = estrdup(errstr);
     978                 :         } else {
     979               0 :                 strncpy(buf, errstr, bufsize);
     980                 :         }
     981              58 :         return buf;
     982                 : #else
     983                 :         char *sysbuf;
     984                 :         int free_it = 1;
     985                 : 
     986                 :         if (!FormatMessage(
     987                 :                                 FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     988                 :                                 FORMAT_MESSAGE_FROM_SYSTEM |
     989                 :                                 FORMAT_MESSAGE_IGNORE_INSERTS,
     990                 :                                 NULL,
     991                 :                                 err,
     992                 :                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     993                 :                                 (LPTSTR)&sysbuf,
     994                 :                                 0,
     995                 :                                 NULL)) {
     996                 :                 free_it = 0;
     997                 :                 sysbuf = "Unknown Error";
     998                 :         }
     999                 : 
    1000                 :         if (buf == NULL) {
    1001                 :                 buf = estrdup(sysbuf);
    1002                 :         } else {
    1003                 :                 strncpy(buf, sysbuf, bufsize);
    1004                 :         }
    1005                 : 
    1006                 :         if (free_it) {
    1007                 :                 LocalFree(sysbuf);
    1008                 :         }
    1009                 : 
    1010                 :         return buf;
    1011                 : #endif
    1012                 : }
    1013                 : /* }}} */
    1014                 : 
    1015                 : /* deprecated */
    1016                 : PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC TSRMLS_DC)
    1017              12 : {
    1018                 :         php_stream *stream;
    1019                 :         php_netstream_data_t *sock;
    1020                 : 
    1021              12 :         sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
    1022              12 :         memset(sock, 0, sizeof(php_netstream_data_t));
    1023                 : 
    1024              12 :         sock->is_blocked = 1;
    1025              12 :         sock->timeout.tv_sec = FG(default_socket_timeout);
    1026              12 :         sock->timeout.tv_usec = 0;
    1027              12 :         sock->socket = socket;
    1028                 : 
    1029              12 :         stream = php_stream_alloc_rel(&php_stream_generic_socket_ops, sock, persistent_id, "r+");
    1030                 : 
    1031              12 :         if (stream == NULL) {
    1032               0 :                 pefree(sock, persistent_id ? 1 : 0);
    1033                 :         } else {
    1034              12 :                 stream->flags |= PHP_STREAM_FLAG_AVOID_BLOCKING;
    1035                 :         }
    1036                 : 
    1037              12 :         return stream;
    1038                 : }
    1039                 : 
    1040                 : PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short port,
    1041                 :                 int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC TSRMLS_DC)
    1042               0 : {
    1043                 :         char *res;
    1044                 :         long reslen;
    1045                 :         php_stream *stream;
    1046                 : 
    1047               0 :         reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
    1048                 : 
    1049               0 :         stream = php_stream_xport_create(res, reslen, ENFORCE_SAFE_MODE | REPORT_ERRORS,
    1050                 :                         STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);
    1051                 : 
    1052               0 :         efree(res);
    1053                 : 
    1054               0 :         return stream;
    1055                 : }
    1056                 : 
    1057                 : PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC)
    1058              16 : {
    1059              16 :         int ret = SUCCESS;
    1060                 :         int flags;
    1061              16 :         int myflag = 0;
    1062                 : 
    1063                 : #ifdef PHP_WIN32
    1064                 :         /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
    1065                 :         flags = !block;
    1066                 :         if (ioctlsocket(socketd, FIONBIO, &flags) == SOCKET_ERROR) {
    1067                 :                 char *error_string;
    1068                 :                 
    1069                 :                 error_string = php_socket_strerror(WSAGetLastError(), NULL, 0);
    1070                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_string);
    1071                 :                 efree(error_string);
    1072                 :                 ret = FAILURE;
    1073                 :         }
    1074                 : #else
    1075              16 :         flags = fcntl(socketd, F_GETFL);
    1076                 : #ifdef O_NONBLOCK
    1077              16 :         myflag = O_NONBLOCK; /* POSIX version */
    1078                 : #elif defined(O_NDELAY)
    1079                 :         myflag = O_NDELAY;   /* old non-POSIX version */
    1080                 : #endif
    1081              16 :         if (!block) {
    1082              10 :                 flags |= myflag;
    1083                 :         } else {
    1084               6 :                 flags &= ~myflag;
    1085                 :         }
    1086              16 :         fcntl(socketd, F_SETFL, flags);
    1087                 : #endif
    1088              16 :         return ret;
    1089                 : }
    1090                 : 
    1091                 : PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
    1092               0 : {
    1093                 :         TSRMLS_FETCH();
    1094                 : 
    1095                 : #ifdef PHP_WIN32
    1096                 :         php_error_docref(NULL TSRMLS_CC, E_WARNING,
    1097                 :                 "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
    1098                 :                 "If this binary is from an official www.php.net package, file a bug report\n"
    1099                 :                 "at http://bugs.php.net, including the following information:\n"
    1100                 :                 "FD_SETSIZE=%d, but you are using %d.\n"
    1101                 :                 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
    1102                 :                 "to match to maximum number of sockets each script will work with at\n"
    1103                 :                 "one time, in order to avoid seeing this error again at a later date.",
    1104                 :                 FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
    1105                 : #else
    1106               0 :         php_error_docref(NULL TSRMLS_CC, E_WARNING,
    1107                 :                 "You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
    1108                 :                 "It is set to %d, but you have descriptors numbered at least as high as %d.\n"
    1109                 :                 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
    1110                 :                 "to equal the maximum number of open files supported by your system,\n"
    1111                 :                 "in order to avoid seeing this error again at a later date.",
    1112                 :                 FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
    1113                 : #endif
    1114               0 : }
    1115                 : 
    1116                 : #if defined(PHP_USE_POLL_2_EMULATION)
    1117                 : 
    1118                 : /* emulate poll(2) using select(2), safely. */
    1119                 : 
    1120                 : PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
    1121                 : {
    1122                 :         fd_set rset, wset, eset;
    1123                 :         php_socket_t max_fd = SOCK_ERR;
    1124                 :         unsigned int i, n;
    1125                 :         struct timeval tv;
    1126                 : 
    1127                 :         /* check the highest numbered descriptor */
    1128                 :         for (i = 0; i < nfds; i++) {
    1129                 :                 if (ufds[i].fd > max_fd)
    1130                 :                         max_fd = ufds[i].fd;
    1131                 :         }
    1132                 : 
    1133                 :         PHP_SAFE_MAX_FD(max_fd, nfds + 1);
    1134                 : 
    1135                 :         FD_ZERO(&rset);
    1136                 :         FD_ZERO(&wset);
    1137                 :         FD_ZERO(&eset);
    1138                 : 
    1139                 :         for (i = 0; i < nfds; i++) {
    1140                 :                 if (ufds[i].events & PHP_POLLREADABLE) {
    1141                 :                         PHP_SAFE_FD_SET(ufds[i].fd, &rset);
    1142                 :                 }
    1143                 :                 if (ufds[i].events & POLLOUT) {
    1144                 :                         PHP_SAFE_FD_SET(ufds[i].fd, &wset);
    1145                 :                 }
    1146                 :                 if (ufds[i].events & POLLPRI) {
    1147                 :                         PHP_SAFE_FD_SET(ufds[i].fd, &eset);
    1148                 :                 }
    1149                 :         }
    1150                 : 
    1151                 :         if (timeout >= 0) {
    1152                 :                 tv.tv_sec = timeout / 1000;
    1153                 :                 tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
    1154                 :         }
    1155                 : /* Reseting/initializing */
    1156                 : #ifdef PHP_WIN32
    1157                 :         WSASetLastError(0);
    1158                 : #else
    1159                 :         errno = 0;
    1160                 : #endif
    1161                 :         n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL);
    1162                 : 
    1163                 :         if (n >= 0) {
    1164                 :                 for (i = 0; i < nfds; i++) {
    1165                 :                         ufds[i].revents = 0;
    1166                 : 
    1167                 :                         if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) {
    1168                 :                                 /* could be POLLERR or POLLHUP but can't tell without probing */
    1169                 :                                 ufds[i].revents |= POLLIN;
    1170                 :                         }
    1171                 :                         if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) {
    1172                 :                                 ufds[i].revents |= POLLOUT;
    1173                 :                         }
    1174                 :                         if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) {
    1175                 :                                 ufds[i].revents |= POLLPRI;
    1176                 :                         }
    1177                 :                 }
    1178                 :         }
    1179                 :         return n;
    1180                 : }
    1181                 : 
    1182                 : #endif
    1183                 : 
    1184                 : 
    1185                 : /*
    1186                 :  * Local variables:
    1187                 :  * tab-width: 8
    1188                 :  * c-basic-offset: 8
    1189                 :  * End:
    1190                 :  * vim600: sw=4 ts=4 fdm=marker
    1191                 :  * vim<600: sw=4 ts=4
    1192                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:16 +0000 (3 days ago)

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