Back to index

php5  5.3.10
Defines | Typedefs | Functions
network.c File Reference
#include "php.h"
#include <stddef.h>
#include <sys/param.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include "php_network.h"
#include "ext/standard/file.h"

Go to the source code of this file.

Defines

#define SOCK_ERR   -1
#define SOCK_CONN_ERR   -1
#define PHP_TIMEOUT_ERROR_VALUE   ETIMEDOUT
#define O_NONBLOCK   O_NDELAY
#define HAVE_NON_BLOCKING_CONNECT   1
#define SET_SOCKET_BLOCKING_MODE(sock, save)
#define RESTORE_SOCKET_BLOCKING_MODE(sock, save)   fcntl(sock, F_SETFL, save)

Typedefs

typedef int php_non_blocking_flags_t

Functions

int inet_aton (const char *, struct in_addr *)
static void php_network_freeaddresses (struct sockaddr **sal)
static int php_network_getaddresses (const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
PHPAPI int php_network_connect_socket (php_socket_t sockfd, const struct sockaddr *addr, socklen_t addrlen, int asynchronous, struct timeval *timeout, char **error_string, int *error_code)
static void sub_times (struct timeval a, struct timeval b, struct timeval *result)
php_socket_t php_network_bind_socket_to_local_addr (const char *host, unsigned port, int socktype, char **error_string, int *error_code TSRMLS_DC)
PHPAPI int php_network_parse_network_address_with_port (const char *addr, long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC)
PHPAPI void php_network_populate_name_from_sockaddr (struct sockaddr *sa, socklen_t sl, char **textaddr, long *textaddrlen, struct sockaddr **addr, socklen_t *addrlen TSRMLS_DC)
PHPAPI int php_network_get_peer_name (php_socket_t sock, char **textaddr, long *textaddrlen, struct sockaddr **addr, socklen_t *addrlen TSRMLS_DC)
PHPAPI int php_network_get_sock_name (php_socket_t sock, char **textaddr, long *textaddrlen, struct sockaddr **addr, socklen_t *addrlen TSRMLS_DC)
PHPAPI php_socket_t php_network_accept_incoming (php_socket_t srvsock, char **textaddr, long *textaddrlen, struct sockaddr **addr, socklen_t *addrlen, struct timeval *timeout, char **error_string, int *error_code TSRMLS_DC)
php_socket_t php_network_connect_socket_to_host (const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, char **error_string, int *error_code, char *bindto, unsigned short bindport TSRMLS_DC)
PHPAPI void php_any_addr (int family, php_sockaddr_storage *addr, unsigned short port)
PHPAPI int php_sockaddr_size (php_sockaddr_storage *addr)
PHPAPI char * php_socket_strerror (long err, char *buf, size_t bufsize)
PHPAPI php_stream * _php_stream_sock_open_from_socket (php_socket_t socket, const char *persistent_id STREAMS_DC TSRMLS_DC)
PHPAPI php_stream * _php_stream_sock_open_host (const char *host, unsigned short port, int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC TSRMLS_DC)
PHPAPI int php_set_sock_blocking (int socketd, int block TSRMLS_DC)
PHPAPI void _php_emit_fd_setsize_warning (int max_fd)
PHPAPI int php_poll2 (php_pollfd *ufds, unsigned int nfds, int timeout)

Define Documentation

#define HAVE_NON_BLOCKING_CONNECT   1

Definition at line 278 of file network.c.

#define O_NONBLOCK   O_NDELAY

Definition at line 274 of file network.c.

#define PHP_TIMEOUT_ERROR_VALUE   ETIMEDOUT

Definition at line 102 of file network.c.

#define RESTORE_SOCKET_BLOCKING_MODE (   sock,
  save 
)    fcntl(sock, F_SETFL, save)

Definition at line 290 of file network.c.

#define SET_SOCKET_BLOCKING_MODE (   sock,
  save 
)
Value:
save = fcntl(sock, F_GETFL, 0); \
        fcntl(sock, F_SETFL, save | O_NONBLOCK)

Definition at line 287 of file network.c.

#define SOCK_CONN_ERR   -1

Definition at line 101 of file network.c.

#define SOCK_ERR   -1

Definition at line 100 of file network.c.


Typedef Documentation

Definition at line 286 of file network.c.


Function Documentation

Definition at line 1105 of file network.c.

{
       TSRMLS_FETCH();

#ifdef PHP_WIN32
       php_error_docref(NULL TSRMLS_CC, E_WARNING,
              "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
              "If this binary is from an official www.php.net package, file a bug report\n"
              "at http://bugs.php.net, including the following information:\n"
              "FD_SETSIZE=%d, but you are using %d.\n"
              " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
              "to match to maximum number of sockets each script will work with at\n"
              "one time, in order to avoid seeing this error again at a later date.",
              FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
#else
       php_error_docref(NULL TSRMLS_CC, E_WARNING,
              "You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
              "It is set to %d, but you have descriptors numbered at least as high as %d.\n"
              " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
              "to equal the maximum number of open files supported by your system,\n"
              "in order to avoid seeing this error again at a later date.",
              FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
#endif
}
PHPAPI php_stream* _php_stream_sock_open_from_socket ( php_socket_t  socket,
const char *persistent_id STREAMS_DC  TSRMLS_DC 
)

Definition at line 1028 of file network.c.

{
       php_stream *stream;
       php_netstream_data_t *sock;

       sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
       memset(sock, 0, sizeof(php_netstream_data_t));

       sock->is_blocked = 1;
       sock->timeout.tv_sec = FG(default_socket_timeout);
       sock->timeout.tv_usec = 0;
       sock->socket = socket;

       stream = php_stream_alloc_rel(&php_stream_generic_socket_ops, sock, persistent_id, "r+");

       if (stream == NULL) {
              pefree(sock, persistent_id ? 1 : 0);
       } else {
              stream->flags |= PHP_STREAM_FLAG_AVOID_BLOCKING;
       }

       return stream;
}
PHPAPI php_stream* _php_stream_sock_open_host ( const char *  host,
unsigned short  port,
int  socktype,
struct timeval *  timeout,
const char *persistent_id STREAMS_DC  TSRMLS_DC 
)

Definition at line 1052 of file network.c.

{
       char *res;
       long reslen;
       php_stream *stream;

       reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);

       stream = php_stream_xport_create(res, reslen, ENFORCE_SAFE_MODE | REPORT_ERRORS,
                     STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);

       efree(res);

       return stream;
}

Here is the call graph for this function:

int inet_aton ( const char *  ,
struct in_addr *   
)

Definition at line 175 of file flock_compat.c.

{
    int dots = 0;
    register unsigned long acc = 0, addr = 0;

    do {
        register char cc = *cp;

        switch (cc) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            acc = acc * 10 + (cc - '0');
            break;

        case '.':
            if (++dots > 3) {
                return 0;
            }
            /* Fall through */

        case '\0':
            if (acc > 255) {
                return 0;
            }
            addr = addr << 8 | acc;
            acc = 0;
            break;

        default:
            return 0;
        }
    } while (*cp++) ;

    /* Normalize the address */
    if (dots < 3) {
        addr <<= 8 * (3 - dots) ;
    }

    /* Store it if requested */
    if (ap) {
        ap->s_addr = htonl(addr);
    }

    return 1;    
}
PHPAPI void php_any_addr ( int  family,
php_sockaddr_storage addr,
unsigned short  port 
)

Definition at line 930 of file network.c.

{
       memset(addr, 0, sizeof(php_sockaddr_storage));
       switch (family) {
#if HAVE_IPV6
       case AF_INET6: {
              struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
              sin6->sin6_family = AF_INET6;
              sin6->sin6_port = htons(port);
              sin6->sin6_addr = in6addr_any;
              break;
       }
#endif
       case AF_INET: {
              struct sockaddr_in *sin = (struct sockaddr_in *) addr;
              sin->sin_family = AF_INET;
              sin->sin_port = htons(port);
              sin->sin_addr.s_addr = htonl(INADDR_ANY);
              break;
       }
       }
}
PHPAPI php_socket_t php_network_accept_incoming ( php_socket_t  srvsock,
char **  textaddr,
long *  textaddrlen,
struct sockaddr **  addr,
socklen_t addrlen,
struct timeval *  timeout,
char **  error_string,
int *error_code  TSRMLS_DC 
)

Definition at line 705 of file network.c.

{
       php_socket_t clisock = -1;
       int error = 0, n;
       php_sockaddr_storage sa;
       socklen_t sl;

       n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout);

       if (n == 0) {
              error = PHP_TIMEOUT_ERROR_VALUE;
       } else if (n == -1) {
              error = php_socket_errno();
       } else {
              sl = sizeof(sa);

              clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);

              if (clisock != SOCK_ERR) {
                     php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
                                   textaddr, textaddrlen,
                                   addr, addrlen
                                   TSRMLS_CC);
              } else {
                     error = php_socket_errno();
              }
       }

       if (error_code) {
              *error_code = error;
       }
       if (error_string) {
              *error_string = php_socket_strerror(error, NULL, 0);
       }

       return clisock;
}

Here is the call graph for this function:

Here is the caller graph for this function:

php_socket_t php_network_bind_socket_to_local_addr ( const char *  host,
unsigned  port,
int  socktype,
char **  error_string,
int *error_code  TSRMLS_DC 
)

Definition at line 415 of file network.c.

{
       int num_addrs, n, err = 0;
       php_socket_t sock;
       struct sockaddr **sal, **psal, *sa;
       socklen_t socklen;

       num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);

       if (num_addrs == 0) {
              /* could not resolve address(es) */
              return -1;
       }

       for (sal = psal; *sal != NULL; sal++) {
              sa = *sal;

              /* create a socket for this address */
              sock = socket(sa->sa_family, socktype, 0);

              if (sock == SOCK_ERR) {
                     continue;
              }

              switch (sa->sa_family) {
#if HAVE_GETADDRINFO && HAVE_IPV6
                     case AF_INET6:
                            ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
                            ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
                            socklen = sizeof(struct sockaddr_in6);
                            break;
#endif
                     case AF_INET:
                            ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
                            ((struct sockaddr_in *)sa)->sin_port = htons(port);
                            socklen = sizeof(struct sockaddr_in);
                            break;
                     default:
                            /* Unknown family */
                            socklen = 0;
                            sa = NULL;
              }

              if (sa) {
                     /* attempt to bind */

#ifdef SO_REUSEADDR
                     {
                            int val = 1;
                            setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
                     }
#endif

                     n = bind(sock, sa, socklen);

                     if (n != SOCK_CONN_ERR) {
                            goto bound;
                     }

                     err = php_socket_errno();
              }

              closesocket(sock);
       }
       sock = -1;

       if (error_code) {
              *error_code = err;
       }
       if (error_string) {
              *error_string = php_socket_strerror(err, NULL, 0);
       }

bound:

       php_network_freeaddresses(psal);

       return sock;

}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI int php_network_connect_socket ( php_socket_t  sockfd,
const struct sockaddr *  addr,
socklen_t  addrlen,
int  asynchronous,
struct timeval *  timeout,
char **  error_string,
int error_code 
)

Definition at line 300 of file network.c.

{
#if HAVE_NON_BLOCKING_CONNECT
       php_non_blocking_flags_t orig_flags;
       int n;
       int error = 0;
       socklen_t len;
       int ret = 0;

       SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags);

       if ((n = connect(sockfd, addr, addrlen)) != 0) {
              error = php_socket_errno();

              if (error_code) {
                     *error_code = error;
              }

              if (error != EINPROGRESS) {
                     if (error_string) {
                            *error_string = php_socket_strerror(error, NULL, 0);
                     }

                     return -1;
              }
              if (asynchronous && error == EINPROGRESS) {
                     /* this is fine by us */
                     return 0;
              }
       }

       if (n == 0) {
              goto ok;
       }
# ifdef PHP_WIN32
       /* The documentation for connect() says in case of non-blocking connections
        * the select function reports success in the writefds set and failure in
        * the exceptfds set. Indeed, using PHP_POLLREADABLE results in select
        * failing only due to the timeout and not immediately as would be
        * expected when a connection is actively refused. This way,
        * php_pollfd_for will return a mask with POLLOUT if the connection
        * is successful and with POLLPRI otherwise. */
       if ((n = php_pollfd_for(sockfd, POLLOUT|POLLPRI, timeout)) == 0) {
#else
       if ((n = php_pollfd_for(sockfd, PHP_POLLREADABLE|POLLOUT, timeout)) == 0) {
#endif
              error = PHP_TIMEOUT_ERROR_VALUE;
       }

       if (n > 0) {
              len = sizeof(error);
              /*
                 BSD-derived systems set errno correctly
                 Solaris returns -1 from getsockopt in case of error
                 */
              if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
                     ret = -1;
              }
       } else {
              /* whoops: sockfd has disappeared */
              ret = -1;
       }

ok:
       if (!asynchronous) {
              /* back to blocking mode */
              RESTORE_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
       }

       if (error_code) {
              *error_code = error;
       }

       if (error) {
              ret = -1;
              if (error_string) {
                     *error_string = php_socket_strerror(error, NULL, 0);
              }
       }
       return ret;
#else
       if (asynchronous) {
              php_error_docref(NULL TSRMLS_CC, E_WARNING, "Asynchronous connect() not supported on this platform");
       }
       return (connect(sockfd, addr, addrlen) == 0) ? 0 : -1;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

php_socket_t php_network_connect_socket_to_host ( const char *  host,
unsigned short  port,
int  socktype,
int  asynchronous,
struct timeval *  timeout,
char **  error_string,
int error_code,
char *  bindto,
unsigned short bindport  TSRMLS_DC 
)

Definition at line 760 of file network.c.

{
       int num_addrs, n, fatal = 0;
       php_socket_t sock;
       struct sockaddr **sal, **psal, *sa;
       struct timeval working_timeout;
       socklen_t socklen;
#if HAVE_GETTIMEOFDAY
       struct timeval limit_time, time_now;
#endif

       num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);

       if (num_addrs == 0) {
              /* could not resolve address(es) */
              return -1;
       }

       if (timeout) {
              memcpy(&working_timeout, timeout, sizeof(working_timeout));
#if HAVE_GETTIMEOFDAY
              gettimeofday(&limit_time, NULL);
              limit_time.tv_sec += working_timeout.tv_sec;
              limit_time.tv_usec += working_timeout.tv_usec;
              if (limit_time.tv_usec >= 1000000) {
                     limit_time.tv_usec -= 1000000;
                     limit_time.tv_sec++;
              }
#endif
       }

       for (sal = psal; !fatal && *sal != NULL; sal++) {
              sa = *sal;

              /* create a socket for this address */
              sock = socket(sa->sa_family, socktype, 0);

              if (sock == SOCK_ERR) {
                     continue;
              }

              switch (sa->sa_family) {
#if HAVE_GETADDRINFO && HAVE_IPV6
                     case AF_INET6:
                            if (!bindto || strchr(bindto, ':')) {
                                   ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
                                   ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
                                   socklen = sizeof(struct sockaddr_in6);
                            } else {
                                   socklen = 0;
                                   sa = NULL;
                            }
                            break;
#endif
                     case AF_INET:
                            ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
                            ((struct sockaddr_in *)sa)->sin_port = htons(port);
                            socklen = sizeof(struct sockaddr_in);
                            break;
                     default:
                            /* Unknown family */
                            socklen = 0;
                            sa = NULL;
              }

              if (sa) {
                     /* make a connection attempt */

                     if (bindto) {
                            struct sockaddr *local_address = NULL;
                            int local_address_len = 0;

                            if (sa->sa_family == AF_INET) {
                                   struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));

                                   local_address = (struct sockaddr*)in4;
                                   local_address_len = sizeof(struct sockaddr_in);

                                   in4->sin_family = sa->sa_family;
                                   in4->sin_port = htons(bindport);
                                   if (!inet_aton(bindto, &in4->sin_addr)) {
                                          php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
                                          goto skip_bind;
                                   }
                                   memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
                            }
#if HAVE_IPV6 && HAVE_INET_PTON
                             else { /* IPV6 */
                                   struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));

                                   local_address = (struct sockaddr*)in6;
                                   local_address_len = sizeof(struct sockaddr_in6);

                                   in6->sin6_family = sa->sa_family;
                                   in6->sin6_port = htons(bindport);
                                   if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
                                          php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
                                          goto skip_bind;
                                   }
                            }
#endif
                            if (!local_address || bind(sock, local_address, local_address_len)) {
                                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
                            }
skip_bind:
                            if (local_address) {
                                   efree(local_address);
                            }
                     }
                     /* free error string recieved during previous iteration (if any) */
                     if (error_string && *error_string) {
                            efree(*error_string);
                            *error_string = NULL;
                     }

                     n = php_network_connect_socket(sock, sa, socklen, asynchronous,
                                   timeout ? &working_timeout : NULL,
                                   error_string, error_code);

                     if (n != -1) {
                            goto connected;
                     }

                     /* adjust timeout for next attempt */
#if HAVE_GETTIMEOFDAY
                     if (timeout) {
                            gettimeofday(&time_now, NULL);

                            if (timercmp(&time_now, &limit_time, >=)) {
                                   /* time limit expired; don't attempt any further connections */
                                   fatal = 1;
                            } else {
                                   /* work out remaining time */
                                   sub_times(limit_time, time_now, &working_timeout);
                            }
                     }
#else
                     if (error_code && *error_code == PHP_TIMEOUT_ERROR_VALUE) {
                            /* Don't even bother trying to connect to the next alternative;
                             * we have no way to determine how long we have already taken
                             * and it is quite likely that the next attempt will fail too. */
                            fatal = 1;
                     } else {
                            /* re-use the same initial timeout.
                             * Not the best thing, but in practice it should be good-enough */
                            if (timeout) {
                                   memcpy(&working_timeout, timeout, sizeof(working_timeout));
                            }
                     }
#endif
              }

              closesocket(sock);
       }
       sock = -1;

connected:

       php_network_freeaddresses(psal);

       return sock;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void php_network_freeaddresses ( struct sockaddr **  sal) [static]

Definition at line 151 of file network.c.

{
       struct sockaddr **sap;

       if (sal == NULL)
              return;
       for (sap = sal; *sap != NULL; sap++)
              efree(*sap);
       efree(sal);
}

Here is the caller graph for this function:

PHPAPI int php_network_get_peer_name ( php_socket_t  sock,
char **  textaddr,
long *  textaddrlen,
struct sockaddr **  addr,
socklen_t *addrlen  TSRMLS_DC 
)

Definition at line 654 of file network.c.

{
       php_sockaddr_storage sa;
       socklen_t sl = sizeof(sa);
       memset(&sa, 0, sizeof(sa));

       if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
              php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
                            textaddr, textaddrlen,
                            addr, addrlen
                            TSRMLS_CC);
              return 0;
       }
       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI int php_network_get_sock_name ( php_socket_t  sock,
char **  textaddr,
long *  textaddrlen,
struct sockaddr **  addr,
socklen_t *addrlen  TSRMLS_DC 
)

Definition at line 674 of file network.c.

{
       php_sockaddr_storage sa;
       socklen_t sl = sizeof(sa);
       memset(&sa, 0, sizeof(sa));

       if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
              php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
                            textaddr, textaddrlen,
                            addr, addrlen
                            TSRMLS_CC);
              return 0;
       }
       return -1;

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int php_network_getaddresses ( const char *  host,
int  socktype,
struct sockaddr ***  sal,
char **error_string  TSRMLS_DC 
) [static]

Definition at line 166 of file network.c.

{
       struct sockaddr **sap;
       int n;
#if HAVE_GETADDRINFO
# if HAVE_IPV6
       static int ipv6_borked = -1; /* the way this is used *is* thread safe */
# endif
       struct addrinfo hints, *res, *sai;
#else
       struct hostent *host_info;
       struct in_addr in;
#endif

       if (host == NULL) {
              return 0;
       }
#if HAVE_GETADDRINFO
       memset(&hints, '\0', sizeof(hints));

       hints.ai_family = AF_INET; /* default to regular inet (see below) */
       hints.ai_socktype = socktype;

# if HAVE_IPV6
       /* probe for a working IPv6 stack; even if detected as having v6 at compile
        * time, at runtime some stacks are slow to resolve or have other issues
        * if they are not correctly configured.
        * static variable use is safe here since simple store or fetch operations
        * are atomic and because the actual probe process is not in danger of
        * collisions or race conditions. */
       if (ipv6_borked == -1) {
              int s;

              s = socket(PF_INET6, SOCK_DGRAM, 0);
              if (s == SOCK_ERR) {
                     ipv6_borked = 1;
              } else {
                     ipv6_borked = 0;
                     closesocket(s);
              }
       }
       hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC;
# endif

       if ((n = getaddrinfo(host, NULL, &hints, &res))) {
              if (error_string) {
                     spprintf(error_string, 0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
              } else {
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
              }
              return 0;
       } else if (res == NULL) {
              if (error_string) {
                     spprintf(error_string, 0, "php_network_getaddresses: getaddrinfo failed (null result pointer) errno=%d", errno);
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
              } else {
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)");
              }
              return 0;
       }

       sai = res;
       for (n = 1; (sai = sai->ai_next) != NULL; n++)
              ;

       *sal = safe_emalloc((n + 1), sizeof(*sal), 0);
       sai = res;
       sap = *sal;

       do {
              *sap = emalloc(sai->ai_addrlen);
              memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
              sap++;
       } while ((sai = sai->ai_next) != NULL);

       freeaddrinfo(res);
#else
       if (!inet_aton(host, &in)) {
              /* XXX NOT THREAD SAFE (is safe under win32) */
              host_info = gethostbyname(host);
              if (host_info == NULL) {
                     if (error_string) {
                            spprintf(error_string, 0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
                            php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
                     } else {
                            php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: gethostbyname failed");
                     }
                     return 0;
              }
              in = *((struct in_addr *) host_info->h_addr);
       }

       *sal = safe_emalloc(2, sizeof(*sal), 0);
       sap = *sal;
       *sap = emalloc(sizeof(struct sockaddr_in));
       (*sap)->sa_family = AF_INET;
       ((struct sockaddr_in *)*sap)->sin_addr = in;
       sap++;
       n = 1;
#endif

       *sap = NULL;
       return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI int php_network_parse_network_address_with_port ( const char *  addr,
long  addrlen,
struct sockaddr *  sa,
socklen_t *sl  TSRMLS_DC 
)

Definition at line 499 of file network.c.

{
       char *colon;
       char *tmp;
       int ret = FAILURE;
       short port;
       struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
       struct sockaddr **psal;
       int n;
       char *errstr = NULL;
#if HAVE_IPV6
       struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
#endif

       if (*addr == '[') {
              colon = memchr(addr + 1, ']', addrlen-1);
              if (!colon || colon[1] != ':') {
                     return FAILURE;
              }
              port = atoi(colon + 2);
              addr++;
       } else {
              colon = memchr(addr, ':', addrlen);
              if (!colon) {
                     return FAILURE;
              }
              port = atoi(colon + 1);
       }

       tmp = estrndup(addr, colon - addr);

       /* first, try interpreting the address as a numeric address */

#if HAVE_IPV6 && HAVE_INET_PTON
       if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) {
              in6->sin6_port = htons(port);
              in6->sin6_family = AF_INET6;
              *sl = sizeof(struct sockaddr_in6);
              ret = SUCCESS;
              goto out;
       }
#endif
       if (inet_aton(tmp, &in4->sin_addr) > 0) {
              in4->sin_port = htons(port);
              in4->sin_family = AF_INET;
              *sl = sizeof(struct sockaddr_in);
              ret = SUCCESS;
              goto out;
       }

       /* looks like we'll need to resolve it */
       n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr TSRMLS_CC);

       if (n == 0) {
              if (errstr) {
                     php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr);
                     STR_FREE(errstr);
              }
              goto out;
       }

       /* copy the details from the first item */
       switch ((*psal)->sa_family) {
#if HAVE_GETADDRINFO && HAVE_IPV6
              case AF_INET6:
                     *in6 = **(struct sockaddr_in6**)psal;
                     in6->sin6_port = htons(port);
                     *sl = sizeof(struct sockaddr_in6);
                     ret = SUCCESS;
                     break;
#endif
              case AF_INET:
                     *in4 = **(struct sockaddr_in**)psal;
                     in4->sin_port = htons(port);
                     *sl = sizeof(struct sockaddr_in);
                     ret = SUCCESS;
                     break;
       }

       php_network_freeaddresses(psal);

out:
       STR_FREE(tmp);
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI void php_network_populate_name_from_sockaddr ( struct sockaddr *  sa,
socklen_t  sl,
char **  textaddr,
long *  textaddrlen,
struct sockaddr **  addr,
socklen_t *addrlen  TSRMLS_DC 
)

Definition at line 586 of file network.c.

{
       if (addr) {
              *addr = emalloc(sl);
              memcpy(*addr, sa, sl);
              *addrlen = sl;
       }

       if (textaddr) {
#if HAVE_IPV6 && HAVE_INET_NTOP
              char abuf[256];
#endif
              char *buf = NULL;

              switch (sa->sa_family) {
                     case AF_INET:
                            /* generally not thread safe, but it *is* thread safe under win32 */
                            buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
                            if (buf) {
                                   *textaddrlen = spprintf(textaddr, 0, "%s:%d",
                                          buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
                            }

                            break;

#if HAVE_IPV6 && HAVE_INET_NTOP
                     case AF_INET6:
                            buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
                            if (buf) {
                                   *textaddrlen = spprintf(textaddr, 0, "%s:%d",
                                          buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
                            }

                            break;
#endif
#ifdef AF_UNIX
                     case AF_UNIX:
                            {
                                   struct sockaddr_un *ua = (struct sockaddr_un*)sa;

                                   if (ua->sun_path[0] == '\0') {
                                          /* abstract name */
                                          int len = strlen(ua->sun_path + 1) + 1;
                                          *textaddrlen = len;
                                          *textaddr = emalloc(len + 1);
                                          memcpy(*textaddr, ua->sun_path, len);
                                          (*textaddr)[len] = '\0';
                                   } else {
                                          *textaddrlen = strlen(ua->sun_path);
                                          *textaddr = estrndup(ua->sun_path, *textaddrlen);
                                   }
                            }
                            break;
#endif

              }

       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI int php_poll2 ( php_pollfd ufds,
unsigned int  nfds,
int  timeout 
)

Definition at line 1134 of file network.c.

{
       fd_set rset, wset, eset;
       php_socket_t max_fd = SOCK_ERR;
       unsigned int i;
       int n;
       struct timeval tv;

       /* check the highest numbered descriptor */
       for (i = 0; i < nfds; i++) {
              if (ufds[i].fd > max_fd)
                     max_fd = ufds[i].fd;
       }

       PHP_SAFE_MAX_FD(max_fd, nfds + 1);

       FD_ZERO(&rset);
       FD_ZERO(&wset);
       FD_ZERO(&eset);

       for (i = 0; i < nfds; i++) {
              if (ufds[i].events & PHP_POLLREADABLE) {
                     PHP_SAFE_FD_SET(ufds[i].fd, &rset);
              }
              if (ufds[i].events & POLLOUT) {
                     PHP_SAFE_FD_SET(ufds[i].fd, &wset);
              }
              if (ufds[i].events & POLLPRI) {
                     PHP_SAFE_FD_SET(ufds[i].fd, &eset);
              }
       }

       if (timeout >= 0) {
              tv.tv_sec = timeout / 1000;
              tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
       }
/* Reseting/initializing */
#ifdef PHP_WIN32
       WSASetLastError(0);
#else
       errno = 0;
#endif
       n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL);

       if (n >= 0) {
              for (i = 0; i < nfds; i++) {
                     ufds[i].revents = 0;

                     if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) {
                            /* could be POLLERR or POLLHUP but can't tell without probing */
                            ufds[i].revents |= POLLIN;
                     }
                     if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) {
                            ufds[i].revents |= POLLOUT;
                     }
                     if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) {
                            ufds[i].revents |= POLLPRI;
                     }
              }
       }
       return n;
}

Here is the caller graph for this function:

PHPAPI int php_set_sock_blocking ( int  socketd,
int block  TSRMLS_DC 
)

Definition at line 1069 of file network.c.

{
       int ret = SUCCESS;
       int flags;
       int myflag = 0;

#ifdef PHP_WIN32
       /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
       flags = !block;
       if (ioctlsocket(socketd, FIONBIO, &flags) == SOCKET_ERROR) {
              char *error_string;

              error_string = php_socket_strerror(WSAGetLastError(), NULL, 0);
              php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_string);
              efree(error_string);
              ret = FAILURE;
       }
#else
       flags = fcntl(socketd, F_GETFL);
#ifdef O_NONBLOCK
       myflag = O_NONBLOCK; /* POSIX version */
#elif defined(O_NDELAY)
       myflag = O_NDELAY;   /* old non-POSIX version */
#endif
       if (!block) {
              flags |= myflag;
       } else {
              flags &= ~myflag;
       }
       if (fcntl(socketd, F_SETFL, flags) == -1) {
              ret = FAILURE;
       }
#endif
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 957 of file network.c.

{
       switch (((struct sockaddr *)addr)->sa_family) {
       case AF_INET:
              return sizeof(struct sockaddr_in);
#if HAVE_IPV6
       case AF_INET6:
              return sizeof(struct sockaddr_in6);
#endif
#ifdef AF_UNIX
       case AF_UNIX:
              return sizeof(struct sockaddr_un);
#endif
       default:
              return 0;
       }
}
PHPAPI char* php_socket_strerror ( long  err,
char *  buf,
size_t  bufsize 
)

Definition at line 982 of file network.c.

{
#ifndef PHP_WIN32
       char *errstr;

       errstr = strerror(err);
       if (buf == NULL) {
              buf = estrdup(errstr);
       } else {
              strncpy(buf, errstr, bufsize);
       }
       return buf;
#else
       char *sysbuf;
       int free_it = 1;

       if (!FormatMessage(
                            FORMAT_MESSAGE_ALLOCATE_BUFFER |
                            FORMAT_MESSAGE_FROM_SYSTEM |
                            FORMAT_MESSAGE_IGNORE_INSERTS,
                            NULL,
                            err,
                            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                            (LPTSTR)&sysbuf,
                            0,
                            NULL)) {
              free_it = 0;
              sysbuf = "Unknown Error";
       }

       if (buf == NULL) {
              buf = estrdup(sysbuf);
       } else {
              strncpy(buf, sysbuf, bufsize);
       }

       if (free_it) {
              LocalFree(sysbuf);
       }

       return buf;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void sub_times ( struct timeval  a,
struct timeval  b,
struct timeval *  result 
) [inline, static]

Definition at line 396 of file network.c.

{
       result->tv_usec = a.tv_usec - b.tv_usec;
       if (result->tv_usec < 0L) {
              a.tv_sec--;
              result->tv_usec += 1000000L;
       }
       result->tv_sec = a.tv_sec - b.tv_sec;
       if (result->tv_sec < 0L) {
              result->tv_sec++;
              result->tv_usec -= 1000000L;
       }
}

Here is the caller graph for this function: