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

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: 
1.1.1.2 ! misho      20: /* $Id$ */
1.1       misho      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:  */
1.1.1.2 ! misho     151: PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
1.1       misho     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:  */
1.1.1.2 ! misho     166: PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
1.1       misho     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: 
1.1.1.2 ! misho    1061:        stream = php_stream_xport_create(res, reslen, REPORT_ERRORS,
1.1       misho    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>