Annotation of embedaddon/php/main/network.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>