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

LCOV - code coverage report
Current view: top level - ext/sockets - sockets.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 571 772 74.0 %
Date: 2014-07-27 Functions: 32 39 82.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2013 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             :    | Authors: Chris Vandomelen <chrisv@b0rked.dhs.org>                    |
      16             :    |          Sterling Hughes  <sterling@php.net>                         |
      17             :    |          Jason Greene     <jason@php.net>                            |
      18             :    | WinSock: Daniel Beulshausen <daniel@php4win.de>                      |
      19             :    +----------------------------------------------------------------------+
      20             :  */
      21             : 
      22             : /* $Id$ */
      23             : 
      24             : #ifdef HAVE_CONFIG_H
      25             : #include "config.h"
      26             : #endif
      27             : 
      28             : #include "php.h"
      29             : 
      30             : #if HAVE_SOCKETS
      31             : 
      32             : #include "php_network.h"
      33             : #include "ext/standard/file.h"
      34             : #include "ext/standard/info.h"
      35             : #include "php_ini.h"
      36             : #ifdef PHP_WIN32
      37             : # include "win32/inet.h"
      38             : # include <winsock2.h>
      39             : # include <windows.h>
      40             : # include <Ws2tcpip.h>
      41             : # include "php_sockets.h"
      42             : # include "win32/sockets.h"
      43             : # define IS_INVALID_SOCKET(a)   (a->bsd_socket == INVALID_SOCKET)
      44             : # ifdef EPROTONOSUPPORT
      45             : #  undef EPROTONOSUPPORT
      46             : # endif
      47             : # ifdef ECONNRESET
      48             : #  undef ECONNRESET
      49             : # endif
      50             : # define EPROTONOSUPPORT        WSAEPROTONOSUPPORT
      51             : # define ECONNRESET             WSAECONNRESET
      52             : # ifdef errno
      53             : #  undef errno
      54             : # endif
      55             : # define errno                  WSAGetLastError()
      56             : # define h_errno                WSAGetLastError()
      57             : # define set_errno(a)           WSASetLastError(a)
      58             : # define close(a)               closesocket(a)
      59             : #else
      60             : # include <sys/types.h>
      61             : # include <sys/socket.h>
      62             : # include <netdb.h>
      63             : # include <netinet/in.h>
      64             : # include <netinet/tcp.h>
      65             : # include <sys/un.h>
      66             : # include <arpa/inet.h>
      67             : # include <sys/time.h>
      68             : # include <unistd.h>
      69             : # include <errno.h>
      70             : # include <fcntl.h>
      71             : # include <signal.h>
      72             : # include <sys/uio.h>
      73             : # define IS_INVALID_SOCKET(a)   (a->bsd_socket < 0)
      74             : # define set_errno(a) (errno = a)
      75             : # include "php_sockets.h"
      76             : #endif
      77             : 
      78             : ZEND_DECLARE_MODULE_GLOBALS(sockets)
      79             : static PHP_GINIT_FUNCTION(sockets);
      80             : 
      81             : #ifndef MSG_WAITALL
      82             : #ifdef LINUX
      83             : #define MSG_WAITALL 0x00000100
      84             : #else
      85             : #define MSG_WAITALL 0x00000000
      86             : #endif
      87             : #endif
      88             : 
      89             : #ifndef MSG_EOF
      90             : #ifdef MSG_FIN
      91             : #define MSG_EOF MSG_FIN
      92             : #endif
      93             : #endif
      94             : 
      95             : #ifndef SUN_LEN
      96             : #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
      97             : #endif
      98             : 
      99             : #ifndef PF_INET
     100             : #define PF_INET AF_INET
     101             : #endif
     102             : 
     103             : static char *php_strerror(int error TSRMLS_DC);
     104             : 
     105             : #define PHP_NORMAL_READ 0x0001
     106             : #define PHP_BINARY_READ 0x0002
     107             : 
     108             : #define PHP_SOCKET_ERROR(socket,msg,errn)       socket->error = errn;        \
     109             :                                                 SOCKETS_G(last_error) = errn; \
     110             :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s [%d]: %s", msg, errn, php_strerror(errn TSRMLS_CC))
     111             : 
     112             : static int le_socket;
     113             : #define le_socket_name php_sockets_le_socket_name
     114             : 
     115             : /* {{{ arginfo */
     116             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_select, 0, 0, 4)
     117             :         ZEND_ARG_INFO(1, read_fds)
     118             :         ZEND_ARG_INFO(1, write_fds)
     119             :         ZEND_ARG_INFO(1, except_fds)
     120             :         ZEND_ARG_INFO(0, tv_sec)
     121             :         ZEND_ARG_INFO(0, tv_usec)
     122             : ZEND_END_ARG_INFO()
     123             : 
     124             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_listen, 0, 0, 1)
     125             :         ZEND_ARG_INFO(0, port)
     126             :         ZEND_ARG_INFO(0, backlog)
     127             : ZEND_END_ARG_INFO()
     128             : 
     129             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_accept, 0, 0, 1)
     130             :         ZEND_ARG_INFO(0, socket)
     131             : ZEND_END_ARG_INFO()
     132             : 
     133             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_nonblock, 0, 0, 1)
     134             :         ZEND_ARG_INFO(0, socket)
     135             : ZEND_END_ARG_INFO()
     136             : 
     137             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_block, 0, 0, 1)
     138             :         ZEND_ARG_INFO(0, socket)
     139             : ZEND_END_ARG_INFO()
     140             : 
     141             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_listen, 0, 0, 1)
     142             :         ZEND_ARG_INFO(0, socket)
     143             :         ZEND_ARG_INFO(0, backlog)
     144             : ZEND_END_ARG_INFO()
     145             : 
     146             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_close, 0, 0, 1)
     147             :         ZEND_ARG_INFO(0, socket)
     148             : ZEND_END_ARG_INFO()
     149             : 
     150             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_write, 0, 0, 2)
     151             :         ZEND_ARG_INFO(0, socket)
     152             :         ZEND_ARG_INFO(0, buf)
     153             :         ZEND_ARG_INFO(0, length)
     154             : ZEND_END_ARG_INFO()
     155             : 
     156             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_read, 0, 0, 2)
     157             :         ZEND_ARG_INFO(0, socket)
     158             :         ZEND_ARG_INFO(0, length)
     159             :         ZEND_ARG_INFO(0, type)
     160             : ZEND_END_ARG_INFO()
     161             : 
     162             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getsockname, 0, 0, 2)
     163             :         ZEND_ARG_INFO(0, socket)
     164             :         ZEND_ARG_INFO(1, addr)
     165             :         ZEND_ARG_INFO(1, port)
     166             : ZEND_END_ARG_INFO()
     167             : 
     168             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getpeername, 0, 0, 2)
     169             :         ZEND_ARG_INFO(0, socket)
     170             :         ZEND_ARG_INFO(1, addr)
     171             :         ZEND_ARG_INFO(1, port)
     172             : ZEND_END_ARG_INFO()
     173             : 
     174             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create, 0, 0, 3)
     175             :         ZEND_ARG_INFO(0, domain)
     176             :         ZEND_ARG_INFO(0, type)
     177             :         ZEND_ARG_INFO(0, protocol)
     178             : ZEND_END_ARG_INFO()
     179             : 
     180             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_connect, 0, 0, 2)
     181             :         ZEND_ARG_INFO(0, socket)
     182             :         ZEND_ARG_INFO(0, addr)
     183             :         ZEND_ARG_INFO(0, port)
     184             : ZEND_END_ARG_INFO()
     185             : 
     186             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_strerror, 0, 0, 1)
     187             :         ZEND_ARG_INFO(0, errno)
     188             : ZEND_END_ARG_INFO()
     189             : 
     190             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_bind, 0, 0, 2)
     191             :         ZEND_ARG_INFO(0, socket)
     192             :         ZEND_ARG_INFO(0, addr)
     193             :         ZEND_ARG_INFO(0, port)
     194             : ZEND_END_ARG_INFO()
     195             : 
     196             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recv, 0, 0, 4)
     197             :         ZEND_ARG_INFO(0, socket)
     198             :         ZEND_ARG_INFO(1, buf)
     199             :         ZEND_ARG_INFO(0, len)
     200             :         ZEND_ARG_INFO(0, flags)
     201             : ZEND_END_ARG_INFO()
     202             : 
     203             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_send, 0, 0, 4)
     204             :         ZEND_ARG_INFO(0, socket)
     205             :         ZEND_ARG_INFO(0, buf)
     206             :         ZEND_ARG_INFO(0, len)
     207             :         ZEND_ARG_INFO(0, flags)
     208             : ZEND_END_ARG_INFO()
     209             : 
     210             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvfrom, 0, 0, 5)
     211             :         ZEND_ARG_INFO(0, socket)
     212             :         ZEND_ARG_INFO(1, buf)
     213             :         ZEND_ARG_INFO(0, len)
     214             :         ZEND_ARG_INFO(0, flags)
     215             :         ZEND_ARG_INFO(1, name)
     216             :         ZEND_ARG_INFO(1, port)
     217             : ZEND_END_ARG_INFO()
     218             : 
     219             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendto, 0, 0, 5)
     220             :         ZEND_ARG_INFO(0, socket)
     221             :         ZEND_ARG_INFO(0, buf)
     222             :         ZEND_ARG_INFO(0, len)
     223             :         ZEND_ARG_INFO(0, flags)
     224             :         ZEND_ARG_INFO(0, addr)
     225             :         ZEND_ARG_INFO(0, port)
     226             : ZEND_END_ARG_INFO()
     227             : 
     228             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_get_option, 0, 0, 3)
     229             :         ZEND_ARG_INFO(0, socket)
     230             :         ZEND_ARG_INFO(0, level)
     231             :         ZEND_ARG_INFO(0, optname)
     232             : ZEND_END_ARG_INFO()
     233             : 
     234             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_option, 0, 0, 4)
     235             :         ZEND_ARG_INFO(0, socket)
     236             :         ZEND_ARG_INFO(0, level)
     237             :         ZEND_ARG_INFO(0, optname)
     238             :         ZEND_ARG_INFO(0, optval)
     239             : ZEND_END_ARG_INFO()
     240             : 
     241             : #ifdef HAVE_SOCKETPAIR
     242             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_pair, 0, 0, 4)
     243             :         ZEND_ARG_INFO(0, domain)
     244             :         ZEND_ARG_INFO(0, type)
     245             :         ZEND_ARG_INFO(0, protocol)
     246             :         ZEND_ARG_INFO(1, fd)
     247             : ZEND_END_ARG_INFO()
     248             : #endif
     249             : 
     250             : #ifdef HAVE_SHUTDOWN
     251             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_shutdown, 0, 0, 1)
     252             :         ZEND_ARG_INFO(0, socket)
     253             :         ZEND_ARG_INFO(0, how)
     254             : ZEND_END_ARG_INFO()
     255             : #endif
     256             : 
     257             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_last_error, 0, 0, 0)
     258             :         ZEND_ARG_INFO(0, socket)
     259             : ZEND_END_ARG_INFO()
     260             : 
     261             : ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_clear_error, 0, 0, 0)
     262             :         ZEND_ARG_INFO(0, socket)
     263             : ZEND_END_ARG_INFO()
     264             : /* }}} */
     265             : 
     266             : /* {{{ sockets_functions[]
     267             :  */
     268             : const zend_function_entry sockets_functions[] = {
     269             :         PHP_FE(socket_select,                   arginfo_socket_select)
     270             :         PHP_FE(socket_create,                   arginfo_socket_create)
     271             :         PHP_FE(socket_create_listen,    arginfo_socket_create_listen)
     272             : #ifdef HAVE_SOCKETPAIR
     273             :         PHP_FE(socket_create_pair,              arginfo_socket_create_pair)
     274             : #endif
     275             :         PHP_FE(socket_accept,                   arginfo_socket_accept)
     276             :         PHP_FE(socket_set_nonblock,             arginfo_socket_set_nonblock)
     277             :         PHP_FE(socket_set_block,                arginfo_socket_set_block)
     278             :         PHP_FE(socket_listen,                   arginfo_socket_listen)
     279             :         PHP_FE(socket_close,                    arginfo_socket_close)
     280             :         PHP_FE(socket_write,                    arginfo_socket_write)
     281             :         PHP_FE(socket_read,                             arginfo_socket_read)
     282             :         PHP_FE(socket_getsockname,              arginfo_socket_getsockname)
     283             :         PHP_FE(socket_getpeername,              arginfo_socket_getpeername)
     284             :         PHP_FE(socket_connect,                  arginfo_socket_connect)
     285             :         PHP_FE(socket_strerror,                 arginfo_socket_strerror)
     286             :         PHP_FE(socket_bind,                             arginfo_socket_bind)
     287             :         PHP_FE(socket_recv,                             arginfo_socket_recv)
     288             :         PHP_FE(socket_send,                             arginfo_socket_send)
     289             :         PHP_FE(socket_recvfrom,                 arginfo_socket_recvfrom)
     290             :         PHP_FE(socket_sendto,                   arginfo_socket_sendto)
     291             :         PHP_FE(socket_get_option,               arginfo_socket_get_option)
     292             :         PHP_FE(socket_set_option,               arginfo_socket_set_option)
     293             : #ifdef HAVE_SHUTDOWN
     294             :         PHP_FE(socket_shutdown,                 arginfo_socket_shutdown)
     295             : #endif
     296             :         PHP_FE(socket_last_error,               arginfo_socket_last_error)
     297             :         PHP_FE(socket_clear_error,              arginfo_socket_clear_error)
     298             : 
     299             :         /* for downwards compatability */
     300             :         PHP_FALIAS(socket_getopt, socket_get_option, arginfo_socket_get_option)
     301             :         PHP_FALIAS(socket_setopt, socket_set_option, arginfo_socket_set_option)
     302             : 
     303             :         PHP_FE_END
     304             : };
     305             : /* }}} */
     306             : 
     307             : zend_module_entry sockets_module_entry = {
     308             :         STANDARD_MODULE_HEADER,
     309             :         "sockets",
     310             :         sockets_functions,
     311             :         PHP_MINIT(sockets),
     312             :         NULL,
     313             :         NULL,
     314             :         PHP_RSHUTDOWN(sockets),
     315             :         PHP_MINFO(sockets),
     316             :         NO_VERSION_YET,
     317             :         PHP_MODULE_GLOBALS(sockets),
     318             :         PHP_GINIT(sockets),
     319             :         NULL,
     320             :         NULL,
     321             :         STANDARD_MODULE_PROPERTIES_EX
     322             : };
     323             : 
     324             : 
     325             : #ifdef COMPILE_DL_SOCKETS
     326             : ZEND_GET_MODULE(sockets)
     327             : #endif
     328             : 
     329             : /* inet_ntop should be used instead of inet_ntoa */
     330             : int inet_ntoa_lock = 0;
     331             : 
     332           0 : PHP_SOCKETS_API int php_sockets_le_socket(void) /* {{{ */
     333             : {
     334           0 :         return le_socket;
     335             : }
     336             : /* }}} */
     337             : 
     338          47 : static void php_destroy_socket(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
     339             : {
     340          47 :         php_socket *php_sock = (php_socket *) rsrc->ptr;
     341             : 
     342          47 :         close(php_sock->bsd_socket);
     343          47 :         efree(php_sock);
     344          47 : }
     345             : /* }}} */
     346             : 
     347          13 : static int php_open_listen_sock(php_socket **php_sock, int port, int backlog TSRMLS_DC) /* {{{ */
     348             : {
     349             :         struct sockaddr_in  la;
     350             :         struct hostent          *hp;
     351          13 :         php_socket                      *sock = (php_socket*)emalloc(sizeof(php_socket));
     352             : 
     353          13 :         *php_sock = sock;
     354             : 
     355             : #ifndef PHP_WIN32
     356          13 :         if ((hp = gethostbyname("0.0.0.0")) == NULL) {
     357             : #else
     358             :         if ((hp = gethostbyname("localhost")) == NULL) {
     359             : #endif
     360           0 :                 efree(sock);
     361           0 :                 return 0;
     362             :         }
     363             : 
     364          13 :         memcpy((char *) &la.sin_addr, hp->h_addr, hp->h_length);
     365          13 :         la.sin_family = hp->h_addrtype;
     366          13 :         la.sin_port = htons((unsigned short) port);
     367             : 
     368          13 :         sock->bsd_socket = socket(PF_INET, SOCK_STREAM, 0);
     369          13 :         sock->blocking = 1;
     370             : 
     371          13 :         if (IS_INVALID_SOCKET(sock)) {
     372           0 :                 PHP_SOCKET_ERROR(sock, "unable to create listening socket", errno);
     373           0 :                 efree(sock);
     374           0 :                 return 0;
     375             :         }
     376             : 
     377          13 :         sock->type = PF_INET;
     378             : 
     379          13 :         if (bind(sock->bsd_socket, (struct sockaddr *)&la, sizeof(la)) != 0) {
     380           2 :                 PHP_SOCKET_ERROR(sock, "unable to bind to given address", errno);
     381           2 :                 close(sock->bsd_socket);
     382           2 :                 efree(sock);
     383           2 :                 return 0;
     384             :         }
     385             : 
     386          11 :         if (listen(sock->bsd_socket, backlog) != 0) {
     387           0 :                 PHP_SOCKET_ERROR(sock, "unable to listen on socket", errno);
     388           0 :                 close(sock->bsd_socket);
     389           0 :                 efree(sock);
     390           0 :                 return 0;
     391             :         }
     392             : 
     393          11 :         return 1;
     394             : }
     395             : /* }}} */
     396             : 
     397           5 : static int php_accept_connect(php_socket *in_sock, php_socket **new_sock, struct sockaddr *la, socklen_t *la_len TSRMLS_DC) /* {{{ */
     398             : {
     399           5 :         php_socket      *out_sock = (php_socket*)emalloc(sizeof(php_socket));
     400             : 
     401           5 :         *new_sock = out_sock;
     402             : 
     403           5 :         out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len);
     404             : 
     405           5 :         if (IS_INVALID_SOCKET(out_sock)) {
     406           0 :                 PHP_SOCKET_ERROR(out_sock, "unable to accept incoming connection", errno);
     407           0 :                 efree(out_sock);
     408           0 :                 return 0;
     409             :         }
     410             : 
     411           5 :         out_sock->error = 0;
     412           5 :         out_sock->blocking = 1;
     413           5 :         out_sock->type = la->sa_family;
     414             : 
     415           5 :         return 1;
     416             : }
     417             : /* }}} */
     418             : 
     419             : /* {{{ php_read -- wrapper around read() so that it only reads to a \r or \n. */
     420           0 : static int php_read(php_socket *sock, void *buf, size_t maxlen, int flags)
     421             : {
     422           0 :         int m = 0;
     423           0 :         size_t n = 0;
     424           0 :         int no_read = 0;
     425           0 :         int nonblock = 0;
     426           0 :         char *t = (char *) buf;
     427             : 
     428             : #ifndef PHP_WIN32
     429           0 :         m = fcntl(sock->bsd_socket, F_GETFL);
     430           0 :         if (m < 0) {
     431           0 :                 return m;
     432             :         }
     433           0 :         nonblock = (m & O_NONBLOCK);
     434           0 :         m = 0;
     435             : #else
     436             :         nonblock = !sock->blocking;
     437             : #endif
     438           0 :         set_errno(0);
     439             : 
     440           0 :         *t = '\0';
     441           0 :         while (*t != '\n' && *t != '\r' && n < maxlen) {
     442           0 :                 if (m > 0) {
     443           0 :                         t++;
     444           0 :                         n++;
     445           0 :                 } else if (m == 0) {
     446           0 :                         no_read++;
     447           0 :                         if (nonblock && no_read >= 2) {
     448           0 :                                 return n;
     449             :                                 /* The first pass, m always is 0, so no_read becomes 1
     450             :                                  * in the first pass. no_read becomes 2 in the second pass,
     451             :                                  * and if this is nonblocking, we should return.. */
     452             :                         }
     453             : 
     454           0 :                         if (no_read > 200) {
     455           0 :                                 set_errno(ECONNRESET);
     456           0 :                                 return -1;
     457             :                         }
     458             :                 }
     459             : 
     460           0 :                 if (n < maxlen) {
     461           0 :                         m = recv(sock->bsd_socket, (void *) t, 1, flags);
     462             :                 }
     463             : 
     464           0 :                 if (errno != 0 && errno != ESPIPE && errno != EAGAIN) {
     465           0 :                         return -1;
     466             :                 }
     467             : 
     468           0 :                 set_errno(0);
     469             :         }
     470             : 
     471           0 :         if (n < maxlen) {
     472           0 :                 n++;
     473             :                 /* The only reasons it makes it to here is
     474             :                  * if '\n' or '\r' are encountered. So, increase
     475             :                  * the return by 1 to make up for the lack of the
     476             :                  * '\n' or '\r' in the count (since read() takes
     477             :                  * place at the end of the loop..) */
     478             :         }
     479             : 
     480           0 :         return n;
     481             : }
     482             : /* }}} */
     483             : 
     484         149 : static char *php_strerror(int error TSRMLS_DC) /* {{{ */
     485             : {
     486             :         const char *buf;
     487             : 
     488             : #ifndef PHP_WIN32
     489         149 :         if (error < -10000) {
     490           0 :                 error = -error - 10000;
     491             : 
     492             : #ifdef HAVE_HSTRERROR
     493           0 :                 buf = hstrerror(error);
     494             : #else
     495             :                 {
     496             :                         if (SOCKETS_G(strerror_buf)) {
     497             :                                 efree(SOCKETS_G(strerror_buf));
     498             :                         }
     499             : 
     500             :                         spprintf(&(SOCKETS_G(strerror_buf)), 0, "Host lookup error %d", error);
     501             :                         buf = SOCKETS_G(strerror_buf);
     502             :                 }
     503             : #endif
     504             :         } else {
     505         149 :                 buf = strerror(error);
     506             :         }
     507             : #else
     508             :         {
     509             :                 LPTSTR tmp = NULL;
     510             :                 buf = NULL;
     511             : 
     512             :                 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
     513             :                         NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &tmp, 0, NULL)
     514             :                 ) {
     515             :                         if (SOCKETS_G(strerror_buf)) {
     516             :                                 efree(SOCKETS_G(strerror_buf));
     517             :                         }
     518             : 
     519             :                         SOCKETS_G(strerror_buf) = estrdup(tmp);
     520             :                         LocalFree(tmp);
     521             : 
     522             :                         buf = SOCKETS_G(strerror_buf);
     523             :                 }
     524             :         }
     525             : #endif
     526             : 
     527         149 :         return (buf ? (char *) buf : "");
     528             : }
     529             : /* }}} */
     530             : 
     531             : #if HAVE_IPV6
     532             : /* Sets addr by hostname, or by ip in string form (AF_INET6) */
     533           6 : static int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */
     534             : {
     535             :         struct in6_addr tmp;
     536             : #if HAVE_GETADDRINFO
     537             :         struct addrinfo hints;
     538           6 :         struct addrinfo *addrinfo = NULL;
     539             : #endif
     540             : 
     541           6 :         if (inet_pton(AF_INET6, string, &tmp)) {
     542           6 :                 memcpy(&(sin6->sin6_addr.s6_addr), &(tmp.s6_addr), sizeof(struct in6_addr));
     543             :         } else {
     544             : #if HAVE_GETADDRINFO
     545             : 
     546           0 :                 memset(&hints, 0, sizeof(struct addrinfo));
     547           0 :                 hints.ai_family = PF_INET6;
     548           0 :                 getaddrinfo(string, NULL, &hints, &addrinfo);
     549           0 :                 if (!addrinfo) {
     550             : #ifdef PHP_WIN32
     551             :                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError());
     552             : #else
     553           0 :                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno));
     554             : #endif
     555           0 :                         return 0;
     556             :                 }
     557           0 :                 if (addrinfo->ai_family != PF_INET6 || addrinfo->ai_addrlen != sizeof(struct sockaddr_in6)) {
     558           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: Non AF_INET6 domain returned on AF_INET6 socket");
     559           0 :                         freeaddrinfo(addrinfo);
     560           0 :                         return 0;
     561             :                 }
     562             : 
     563           0 :                 memcpy(&(sin6->sin6_addr.s6_addr), ((struct sockaddr_in6*)(addrinfo->ai_addr))->sin6_addr.s6_addr, sizeof(struct in6_addr));
     564           0 :                 freeaddrinfo(addrinfo);
     565             : 
     566             : #else
     567             :                 /* No IPv6 specific hostname resolution is available on this system? */
     568             :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system");
     569             :                 return 0;
     570             : #endif
     571             : 
     572             :         }
     573             : 
     574           6 :         return 1;
     575             : }
     576             : /* }}} */
     577             : #endif
     578             : 
     579             : /* Sets addr by hostname, or by ip in string form (AF_INET)  */
     580          11 : static int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */
     581             : {
     582             :         struct in_addr tmp;
     583             :         struct hostent *host_entry;
     584             : 
     585          11 :         if (inet_aton(string, &tmp)) {
     586          10 :                 sin->sin_addr.s_addr = tmp.s_addr;
     587             :         } else {
     588           1 :                 if (! (host_entry = gethostbyname(string))) {
     589             :                         /* Note: < -10000 indicates a host lookup error */
     590             : #ifdef PHP_WIN32
     591             :                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError());
     592             : #else
     593           0 :                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno));
     594             : #endif
     595           0 :                         return 0;
     596             :                 }
     597           1 :                 if (host_entry->h_addrtype != AF_INET) {
     598           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: Non AF_INET domain returned on AF_INET socket");
     599           0 :                         return 0;
     600             :                 }
     601           1 :                 memcpy(&(sin->sin_addr.s_addr), host_entry->h_addr_list[0], host_entry->h_length);
     602             :         }
     603             : 
     604          11 :         return 1;
     605             : }
     606             : /* }}} */
     607             : 
     608             : /* {{{ PHP_GINIT_FUNCTION */
     609       19341 : static PHP_GINIT_FUNCTION(sockets)
     610             : {
     611       19341 :         sockets_globals->last_error = 0;
     612       19341 :         sockets_globals->strerror_buf = NULL;
     613       19341 : }
     614             : /* }}} */
     615             : 
     616             : /* {{{ PHP_MINIT_FUNCTION
     617             :  */
     618       19341 : PHP_MINIT_FUNCTION(sockets)
     619             : {
     620             :         struct protoent *pe;
     621             : 
     622       19341 :         le_socket = zend_register_list_destructors_ex(php_destroy_socket, NULL, le_socket_name, module_number);
     623             : 
     624       19341 :         REGISTER_LONG_CONSTANT("AF_UNIX",             AF_UNIX,                CONST_CS | CONST_PERSISTENT);
     625       19341 :         REGISTER_LONG_CONSTANT("AF_INET",             AF_INET,                CONST_CS | CONST_PERSISTENT);
     626             : #if HAVE_IPV6
     627       19341 :         REGISTER_LONG_CONSTANT("AF_INET6",            AF_INET6,               CONST_CS | CONST_PERSISTENT);
     628             : #endif
     629       19341 :         REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM,    CONST_CS | CONST_PERSISTENT);
     630       19341 :         REGISTER_LONG_CONSTANT("SOCK_DGRAM",  SOCK_DGRAM,             CONST_CS | CONST_PERSISTENT);
     631       19341 :         REGISTER_LONG_CONSTANT("SOCK_RAW",            SOCK_RAW,               CONST_CS | CONST_PERSISTENT);
     632       19341 :         REGISTER_LONG_CONSTANT("SOCK_SEQPACKET",SOCK_SEQPACKET, CONST_CS | CONST_PERSISTENT);
     633       19341 :         REGISTER_LONG_CONSTANT("SOCK_RDM",            SOCK_RDM,               CONST_CS | CONST_PERSISTENT);
     634       19341 :         REGISTER_LONG_CONSTANT("MSG_OOB",             MSG_OOB,                CONST_CS | CONST_PERSISTENT);
     635       19341 :         REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL,    CONST_CS | CONST_PERSISTENT);
     636             : #ifdef MSG_DONTWAIT
     637       19341 :         REGISTER_LONG_CONSTANT("MSG_DONTWAIT",        MSG_DONTWAIT,   CONST_CS | CONST_PERSISTENT);
     638             : #endif
     639       19341 :         REGISTER_LONG_CONSTANT("MSG_PEEK",            MSG_PEEK,               CONST_CS | CONST_PERSISTENT);
     640       19341 :         REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE,        CONST_CS | CONST_PERSISTENT);
     641             : #ifdef MSG_EOR
     642       19341 :         REGISTER_LONG_CONSTANT("MSG_EOR",             MSG_EOR,                CONST_CS | CONST_PERSISTENT);
     643             : #endif
     644             : #ifdef MSG_EOF
     645       19341 :         REGISTER_LONG_CONSTANT("MSG_EOF",             MSG_EOF,                CONST_CS | CONST_PERSISTENT);
     646             : #endif
     647       19341 :         REGISTER_LONG_CONSTANT("SO_DEBUG",            SO_DEBUG,               CONST_CS | CONST_PERSISTENT);
     648       19341 :         REGISTER_LONG_CONSTANT("SO_REUSEADDR",        SO_REUSEADDR,   CONST_CS | CONST_PERSISTENT);
     649       19341 :         REGISTER_LONG_CONSTANT("SO_KEEPALIVE",        SO_KEEPALIVE,   CONST_CS | CONST_PERSISTENT);
     650       19341 :         REGISTER_LONG_CONSTANT("SO_DONTROUTE",        SO_DONTROUTE,   CONST_CS | CONST_PERSISTENT);
     651       19341 :         REGISTER_LONG_CONSTANT("SO_LINGER",           SO_LINGER,              CONST_CS | CONST_PERSISTENT);
     652       19341 :         REGISTER_LONG_CONSTANT("SO_BROADCAST",        SO_BROADCAST,   CONST_CS | CONST_PERSISTENT);
     653       19341 :         REGISTER_LONG_CONSTANT("SO_OOBINLINE",        SO_OOBINLINE,   CONST_CS | CONST_PERSISTENT);
     654       19341 :         REGISTER_LONG_CONSTANT("SO_SNDBUF",           SO_SNDBUF,              CONST_CS | CONST_PERSISTENT);
     655       19341 :         REGISTER_LONG_CONSTANT("SO_RCVBUF",           SO_RCVBUF,              CONST_CS | CONST_PERSISTENT);
     656       19341 :         REGISTER_LONG_CONSTANT("SO_SNDLOWAT", SO_SNDLOWAT,    CONST_CS | CONST_PERSISTENT);
     657       19341 :         REGISTER_LONG_CONSTANT("SO_RCVLOWAT", SO_RCVLOWAT,    CONST_CS | CONST_PERSISTENT);
     658       19341 :         REGISTER_LONG_CONSTANT("SO_SNDTIMEO", SO_SNDTIMEO,    CONST_CS | CONST_PERSISTENT);
     659       19341 :         REGISTER_LONG_CONSTANT("SO_RCVTIMEO", SO_RCVTIMEO,    CONST_CS | CONST_PERSISTENT);
     660       19341 :         REGISTER_LONG_CONSTANT("SO_TYPE",             SO_TYPE,                CONST_CS | CONST_PERSISTENT);
     661       19341 :         REGISTER_LONG_CONSTANT("SO_ERROR",            SO_ERROR,               CONST_CS | CONST_PERSISTENT);
     662       19341 :         REGISTER_LONG_CONSTANT("SOL_SOCKET",  SOL_SOCKET,             CONST_CS | CONST_PERSISTENT);
     663       19341 :         REGISTER_LONG_CONSTANT("SOMAXCONN",           SOMAXCONN,              CONST_CS | CONST_PERSISTENT);
     664             : #ifdef TCP_NODELAY
     665       19341 :         REGISTER_LONG_CONSTANT("TCP_NODELAY",   TCP_NODELAY,    CONST_CS | CONST_PERSISTENT);
     666             : #endif
     667       19341 :         REGISTER_LONG_CONSTANT("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT);
     668       19341 :         REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT);
     669             : 
     670             : #ifndef WIN32
     671             : # include "unix_socket_constants.h"
     672             : #else
     673             : # include "win32_socket_constants.h"
     674             : #endif
     675             : 
     676       19341 :         if ((pe = getprotobyname("tcp"))) {
     677       19341 :                 REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
     678             :         }
     679             : 
     680       19341 :         if ((pe = getprotobyname("udp"))) {
     681       19341 :                 REGISTER_LONG_CONSTANT("SOL_UDP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
     682             :         }
     683             : 
     684       19341 :         return SUCCESS;
     685             : }
     686             : /* }}} */
     687             : 
     688             : /* {{{ PHP_MINFO_FUNCTION
     689             :  */
     690         148 : PHP_MINFO_FUNCTION(sockets)
     691             : {
     692         148 :         php_info_print_table_start();
     693         148 :         php_info_print_table_row(2, "Sockets Support", "enabled");
     694         148 :         php_info_print_table_end();
     695         148 : }
     696             : /* }}} */
     697             : 
     698             : /* {{{ PHP_RSHUTDOWN_FUNCTION */
     699       19362 : PHP_RSHUTDOWN_FUNCTION(sockets)
     700             : {
     701       19362 :         if (SOCKETS_G(strerror_buf)) {
     702           0 :                 efree(SOCKETS_G(strerror_buf));
     703           0 :                 SOCKETS_G(strerror_buf) = NULL;
     704             :         }
     705             : 
     706       19362 :         return SUCCESS;
     707             : }
     708             : /* }}} */
     709             : 
     710           4 : static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *max_fd TSRMLS_DC) /* {{{ */
     711             : {
     712             :         zval            **element;
     713             :         php_socket      *php_sock;
     714           4 :         int                     num = 0;
     715             : 
     716           4 :         if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
     717             : 
     718          16 :         for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));
     719          12 :                  zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;
     720           8 :                  zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {
     721             : 
     722           8 :                 php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
     723           8 :                 if (!php_sock) continue; /* If element is not a resource, skip it */
     724             : 
     725           8 :                 PHP_SAFE_FD_SET(php_sock->bsd_socket, fds);
     726           8 :                 if (php_sock->bsd_socket > *max_fd) {
     727           8 :                         *max_fd = php_sock->bsd_socket;
     728             :                 }
     729           8 :                 num++;
     730             :         }
     731             : 
     732           4 :         return num ? 1 : 0;
     733             : }
     734             : /* }}} */
     735             : 
     736           3 : static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds TSRMLS_DC) /* {{{ */
     737             : {
     738             :         zval            **element;
     739             :         zval            **dest_element;
     740             :         php_socket      *php_sock;
     741             :         HashTable       *new_hash;
     742             :         char            *key;
     743           3 :         int                     num = 0;
     744             :         ulong       num_key;
     745             :         uint            key_len;
     746             : 
     747           3 :         if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
     748             : 
     749           3 :         ALLOC_HASHTABLE(new_hash);
     750           3 :         zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(sock_array)), NULL, ZVAL_PTR_DTOR, 0);
     751          12 :         for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));
     752           9 :                  zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;
     753           6 :                  zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {
     754             : 
     755           6 :                 php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
     756           6 :                 if (!php_sock) continue; /* If element is not a resource, skip it */
     757             : 
     758           6 :                 if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) {
     759             :                         /* Add fd to new array */
     760           0 :                         switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(sock_array), &key, &key_len, &num_key, 0, NULL)) {
     761             :                                 case HASH_KEY_IS_STRING:
     762           0 :                                         zend_hash_add(new_hash, key, key_len, (void *)element, sizeof(zval *), (void **)&dest_element);
     763           0 :                                         break;
     764             :                                 case HASH_KEY_IS_LONG:
     765           0 :                                         zend_hash_index_update(new_hash, num_key, (void *)element, sizeof(zval *), (void **)&dest_element);
     766             :                                         break;
     767             :                         }
     768           0 :                         if (dest_element) zval_add_ref(dest_element);
     769             :                 }
     770           6 :                 num++;
     771             :         }
     772             : 
     773             :         /* Destroy old array, add new one */
     774           3 :         zend_hash_destroy(Z_ARRVAL_P(sock_array));
     775           3 :         efree(Z_ARRVAL_P(sock_array));
     776             : 
     777           3 :         zend_hash_internal_pointer_reset(new_hash);
     778           3 :         Z_ARRVAL_P(sock_array) = new_hash;
     779             : 
     780           3 :         return num ? 1 : 0;
     781             : }
     782             : /* }}} */
     783             : 
     784             : /* {{{ proto int socket_select(array &read_fds, array &write_fds, array &except_fds, int tv_sec[, int tv_usec]) U
     785             :    Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec */
     786           6 : PHP_FUNCTION(socket_select)
     787             : {
     788             :         zval                    *r_array, *w_array, *e_array, *sec;
     789             :         struct timeval  tv;
     790           6 :         struct timeval *tv_p = NULL;
     791             :         fd_set                  rfds, wfds, efds;
     792           6 :         PHP_SOCKET              max_fd = 0;
     793           6 :         int                             retval, sets = 0;
     794           6 :         long                    usec = 0;
     795             : 
     796           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE) {
     797           1 :                 return;
     798             :         }
     799             : 
     800           5 :         FD_ZERO(&rfds);
     801           5 :         FD_ZERO(&wfds);
     802           5 :         FD_ZERO(&efds);
     803             : 
     804           5 :         if (r_array != NULL) sets += php_sock_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
     805           5 :         if (w_array != NULL) sets += php_sock_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
     806           5 :         if (e_array != NULL) sets += php_sock_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
     807             : 
     808           5 :         if (!sets) {
     809           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no resource arrays were passed to select");
     810           1 :                 RETURN_FALSE;
     811             :         }
     812             : 
     813           4 :         PHP_SAFE_MAX_FD(max_fd, 0); /* someone needs to make this look more like stream_socket_select */
     814             : 
     815             :         /* If seconds is not set to null, build the timeval, else we wait indefinitely */
     816           4 :         if (sec != NULL) {
     817             :                 zval tmp;
     818             : 
     819           4 :                 if (Z_TYPE_P(sec) != IS_LONG) {
     820           1 :                         tmp = *sec;
     821           1 :                         zval_copy_ctor(&tmp);
     822           1 :                         convert_to_long(&tmp);
     823           1 :                         sec = &tmp;
     824             :                 }
     825             : 
     826             :                 /* Solaris + BSD do not like microsecond values which are >= 1 sec */
     827           4 :                 if (usec > 999999) {
     828           1 :                         tv.tv_sec = Z_LVAL_P(sec) + (usec / 1000000);
     829           1 :                         tv.tv_usec = usec % 1000000;
     830             :                 } else {
     831           3 :                         tv.tv_sec = Z_LVAL_P(sec);
     832           3 :                         tv.tv_usec = usec;
     833             :                 }
     834             : 
     835           4 :                 tv_p = &tv;
     836             : 
     837           4 :                 if (sec == &tmp) {
     838           1 :                         zval_dtor(&tmp);
     839             :                 }
     840             :         }
     841             : 
     842           4 :         retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
     843             : 
     844           4 :         if (retval == -1) {
     845           1 :                 SOCKETS_G(last_error) = errno;
     846           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s", errno, php_strerror(errno TSRMLS_CC));
     847           1 :                 RETURN_FALSE;
     848             :         }
     849             : 
     850           3 :         if (r_array != NULL) php_sock_array_from_fd_set(r_array, &rfds TSRMLS_CC);
     851           3 :         if (w_array != NULL) php_sock_array_from_fd_set(w_array, &wfds TSRMLS_CC);
     852           3 :         if (e_array != NULL) php_sock_array_from_fd_set(e_array, &efds TSRMLS_CC);
     853             : 
     854           3 :         RETURN_LONG(retval);
     855             : }
     856             : /* }}} */
     857             : 
     858             : /* {{{ proto resource socket_create_listen(int port[, int backlog]) U
     859             :    Opens a socket on port to accept connections */
     860          16 : PHP_FUNCTION(socket_create_listen)
     861             : {
     862             :         php_socket      *php_sock;
     863          16 :         long            port, backlog = 128;
     864             : 
     865          16 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &port, &backlog) == FAILURE) {
     866           3 :                 return;
     867             :         }
     868             : 
     869          13 :         if (!php_open_listen_sock(&php_sock, port, backlog TSRMLS_CC)) {
     870           2 :                 RETURN_FALSE;
     871             :         }
     872             : 
     873          11 :         php_sock->error = 0;
     874          11 :         php_sock->blocking = 1;
     875             : 
     876          11 :         ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
     877             : }
     878             : /* }}} */
     879             : 
     880             : /* {{{ proto resource socket_accept(resource socket) U
     881             :    Accepts a connection on the listening socket fd */
     882           6 : PHP_FUNCTION(socket_accept)
     883             : {
     884             :         zval                             *arg1;
     885             :         php_socket                       *php_sock, *new_sock;
     886             :         php_sockaddr_storage sa;
     887           6 :         socklen_t                        php_sa_len = sizeof(sa);
     888             : 
     889           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
     890           1 :                 return;
     891             :         }
     892             : 
     893           5 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
     894             : 
     895           5 :         if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr*)&sa, &php_sa_len TSRMLS_CC)) {
     896           0 :                 RETURN_FALSE;
     897             :         }
     898             : 
     899           5 :         ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);
     900             : }
     901             : /* }}} */
     902             : 
     903             : /* {{{ proto bool socket_set_nonblock(resource socket) U
     904             :    Sets nonblocking mode on a socket resource */
     905           7 : PHP_FUNCTION(socket_set_nonblock)
     906             : {
     907             :         zval            *arg1;
     908             :         php_socket      *php_sock;
     909             : 
     910           7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
     911           1 :                 return;
     912             :         }
     913             : 
     914           6 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
     915             : 
     916           5 :         if (php_set_sock_blocking(php_sock->bsd_socket, 0 TSRMLS_CC) == SUCCESS) {
     917           5 :                 php_sock->blocking = 0;
     918           5 :                 RETURN_TRUE;
     919             :         } else {
     920           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to set nonblocking mode", errno);
     921           0 :                 RETURN_FALSE;
     922             :         }
     923             : }
     924             : /* }}} */
     925             : 
     926             : /* {{{ proto bool socket_set_block(resource socket) U
     927             :    Sets blocking mode on a socket resource */
     928           5 : PHP_FUNCTION(socket_set_block)
     929             : {
     930             :         zval            *arg1;
     931             :         php_socket      *php_sock;
     932             : 
     933           5 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
     934           1 :                 return;
     935             :         }
     936             : 
     937           4 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
     938             : 
     939           3 :         if (php_set_sock_blocking(php_sock->bsd_socket, 1 TSRMLS_CC) == SUCCESS) {
     940           3 :                 php_sock->blocking = 1;
     941           3 :                 RETURN_TRUE;
     942             :         } else {
     943           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to set blocking mode", errno);
     944           0 :                 RETURN_FALSE;
     945             :         }
     946             : }
     947             : /* }}} */
     948             : 
     949             : /* {{{ proto bool socket_listen(resource socket[, int backlog]) U
     950             :    Sets the maximum number of connections allowed to be waited for on the socket specified by fd */
     951           8 : PHP_FUNCTION(socket_listen)
     952             : {
     953             :         zval            *arg1;
     954             :         php_socket      *php_sock;
     955           8 :         long            backlog = 0;
     956             : 
     957           8 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &backlog) == FAILURE) {
     958           2 :                 return;
     959             :         }
     960             : 
     961           6 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
     962             : 
     963           6 :         if (listen(php_sock->bsd_socket, backlog) != 0) {
     964           1 :                 PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno);
     965           1 :                 RETURN_FALSE;
     966             :         }
     967           5 :         RETURN_TRUE;
     968             : }
     969             : /* }}} */
     970             : 
     971             : /* {{{ proto void socket_close(resource socket) U
     972             :    Closes a file descriptor */
     973          38 : PHP_FUNCTION(socket_close)
     974             : {
     975             :         zval            *arg1;
     976             :         php_socket      *php_sock;
     977             : 
     978          38 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
     979           3 :                 return;
     980             :         }
     981             : 
     982          35 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
     983          35 :         zend_list_delete(Z_RESVAL_P(arg1));
     984             : }
     985             : /* }}} */
     986             : 
     987             : /* {{{ proto int socket_write(resource socket, string buf[, int length])
     988             :    Writes the buffer to the socket resource, length is optional */
     989           7 : PHP_FUNCTION(socket_write)
     990             : {
     991             :         zval            *arg1;
     992             :         php_socket      *php_sock;
     993             :         int                     retval, str_len;
     994           7 :         long            length = 0;
     995             :         char            *str;
     996             : 
     997           7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &str, &str_len, &length) == FAILURE) {
     998           2 :                 return;
     999             :         }
    1000             : 
    1001           5 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1002             : 
    1003           5 :         if (ZEND_NUM_ARGS() < 3) {
    1004           5 :                 length = str_len;
    1005             :         }
    1006             : 
    1007             : #ifndef PHP_WIN32
    1008           5 :         retval = write(php_sock->bsd_socket, str, MIN(length, str_len));
    1009             : #else
    1010             :         retval = send(php_sock->bsd_socket, str, min(length, str_len), 0);
    1011             : #endif
    1012             : 
    1013           5 :         if (retval < 0) {
    1014           1 :                 PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
    1015           1 :                 RETURN_FALSE;
    1016             :         }
    1017             : 
    1018           4 :         RETURN_LONG(retval);
    1019             : }
    1020             : /* }}} */
    1021             : 
    1022             : /* {{{ proto string socket_read(resource socket, int length [, int type]) U
    1023             :    Reads a maximum of length bytes from socket */
    1024           6 : PHP_FUNCTION(socket_read)
    1025             : {
    1026             :         zval            *arg1;
    1027             :         php_socket      *php_sock;
    1028             :         char            *tmpbuf;
    1029             :         int                     retval;
    1030           6 :         long            length, type = PHP_BINARY_READ;
    1031             : 
    1032           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &arg1, &length, &type) == FAILURE) {
    1033           2 :                 return;
    1034             :         }
    1035             : 
    1036             :         /* overflow check */
    1037           4 :         if ((length + 1) < 2) {
    1038           0 :                 RETURN_FALSE;
    1039             :         }
    1040             : 
    1041           4 :         tmpbuf = emalloc(length + 1);
    1042             : 
    1043           4 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1044             : 
    1045           4 :         if (type == PHP_NORMAL_READ) {
    1046           0 :                 retval = php_read(php_sock, tmpbuf, length, 0);
    1047             :         } else {
    1048           4 :                 retval = recv(php_sock->bsd_socket, tmpbuf, length, 0);
    1049             :         }
    1050             : 
    1051           4 :         if (retval == -1) {
    1052             :                 /* if the socket is in non-blocking mode and there's no data to read,
    1053             :                 don't output any error, as this is a normal situation, and not an error */
    1054           2 :                 if (errno == EAGAIN
    1055             : #ifdef EWOULDBLOCK
    1056           1 :                 || errno == EWOULDBLOCK
    1057             : #endif
    1058             :                 ) {
    1059           0 :                         php_sock->error = errno;
    1060           0 :                         SOCKETS_G(last_error) = errno;
    1061             :                 } else {
    1062           1 :                         PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
    1063             :                 }
    1064             : 
    1065           1 :                 efree(tmpbuf);
    1066           1 :                 RETURN_FALSE;
    1067           3 :         } else if (!retval) {
    1068           0 :                 efree(tmpbuf);
    1069           0 :                 RETURN_EMPTY_STRING();
    1070             :         }
    1071             : 
    1072           3 :         tmpbuf = erealloc(tmpbuf, retval + 1);
    1073           3 :         tmpbuf[retval] = '\0' ;
    1074             : 
    1075           3 :         RETURN_STRINGL(tmpbuf, retval, 0);
    1076             : }
    1077             : /* }}} */
    1078             : 
    1079             : /* {{{ proto bool socket_getsockname(resource socket, string &addr[, int &port])
    1080             :    Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */
    1081           2 : PHP_FUNCTION(socket_getsockname)
    1082             : {
    1083           2 :         zval                                    *arg1, *addr, *port = NULL;
    1084             :         php_sockaddr_storage    sa_storage;
    1085             :         php_socket                              *php_sock;
    1086             :         struct sockaddr                 *sa;
    1087             :         struct sockaddr_in              *sin;
    1088             : #if HAVE_IPV6
    1089             :         struct sockaddr_in6             *sin6;
    1090             :         char                                    addr6[INET6_ADDRSTRLEN+1];
    1091             : #endif
    1092             :         struct sockaddr_un              *s_un;
    1093             :         char                                    *addr_string;
    1094           2 :         socklen_t                               salen = sizeof(php_sockaddr_storage);
    1095             : 
    1096           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &addr, &port) == FAILURE) {
    1097           0 :                 return;
    1098             :         }
    1099             : 
    1100           2 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1101             : 
    1102           2 :         sa = (struct sockaddr *) &sa_storage;
    1103             : 
    1104           2 :         if (getsockname(php_sock->bsd_socket, sa, &salen) != 0) {
    1105           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket name", errno);
    1106           0 :                 RETURN_FALSE;
    1107             :         }
    1108             : 
    1109           2 :         switch (sa->sa_family) {
    1110             : #if HAVE_IPV6
    1111             :                 case AF_INET6:
    1112           0 :                         sin6 = (struct sockaddr_in6 *) sa;
    1113           0 :                         inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
    1114           0 :                         zval_dtor(addr);
    1115           0 :                         ZVAL_STRING(addr, addr6, 1);
    1116             : 
    1117           0 :                         if (port != NULL) {
    1118           0 :                                 zval_dtor(port);
    1119           0 :                                 ZVAL_LONG(port, htons(sin6->sin6_port));
    1120             :                         }
    1121           0 :                         RETURN_TRUE;
    1122             :                         break;
    1123             : #endif
    1124             :                 case AF_INET:
    1125           2 :                         sin = (struct sockaddr_in *) sa;
    1126           2 :                         while (inet_ntoa_lock == 1);
    1127           2 :                         inet_ntoa_lock = 1;
    1128           2 :                         addr_string = inet_ntoa(sin->sin_addr);
    1129           2 :                         inet_ntoa_lock = 0;
    1130             : 
    1131           2 :                         zval_dtor(addr);
    1132           2 :                         ZVAL_STRING(addr, addr_string, 1);
    1133             : 
    1134           2 :                         if (port != NULL) {
    1135           2 :                                 zval_dtor(port);
    1136           2 :                                 ZVAL_LONG(port, htons(sin->sin_port));
    1137             :                         }
    1138           2 :                         RETURN_TRUE;
    1139             :                         break;
    1140             : 
    1141             :                 case AF_UNIX:
    1142           0 :                         s_un = (struct sockaddr_un *) sa;
    1143             : 
    1144           0 :                         zval_dtor(addr);
    1145           0 :                         ZVAL_STRING(addr, s_un->sun_path, 1);
    1146           0 :                         RETURN_TRUE;
    1147             :                         break;
    1148             : 
    1149             :                 default:
    1150           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported address family %d", sa->sa_family);
    1151           0 :                         RETURN_FALSE;
    1152             :         }
    1153             : }
    1154             : /* }}} */
    1155             : 
    1156             : /* {{{ proto bool socket_getpeername(resource socket, string &addr[, int &port])
    1157             :    Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */
    1158           3 : PHP_FUNCTION(socket_getpeername)
    1159             : {
    1160           3 :         zval                                    *arg1, *arg2, *arg3 = NULL;
    1161             :         php_sockaddr_storage    sa_storage;
    1162             :         php_socket                              *php_sock;
    1163             :         struct sockaddr                 *sa;
    1164             :         struct sockaddr_in              *sin;
    1165             : #if HAVE_IPV6
    1166             :         struct sockaddr_in6             *sin6;
    1167             :         char                                    addr6[INET6_ADDRSTRLEN+1];
    1168             : #endif
    1169             :         struct sockaddr_un              *s_un;
    1170             :         char                                    *addr_string;
    1171           3 :         socklen_t                               salen = sizeof(php_sockaddr_storage);
    1172             : 
    1173           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &arg2, &arg3) == FAILURE) {
    1174           0 :                 return;
    1175             :         }
    1176             : 
    1177           3 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1178             : 
    1179           3 :         sa = (struct sockaddr *) &sa_storage;
    1180             : 
    1181           3 :         if (getpeername(php_sock->bsd_socket, sa, &salen) < 0) {
    1182           1 :                 PHP_SOCKET_ERROR(php_sock, "unable to retrieve peer name", errno);
    1183           1 :                 RETURN_FALSE;
    1184             :         }
    1185             : 
    1186           2 :         switch (sa->sa_family) {
    1187             : #if HAVE_IPV6
    1188             :                 case AF_INET6:
    1189           1 :                         sin6 = (struct sockaddr_in6 *) sa;
    1190           1 :                         inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
    1191           1 :                         zval_dtor(arg2);
    1192           1 :                         ZVAL_STRING(arg2, addr6, 1);
    1193             : 
    1194           1 :                         if (arg3 != NULL) {
    1195           1 :                                 zval_dtor(arg3);
    1196           1 :                                 ZVAL_LONG(arg3, htons(sin6->sin6_port));
    1197             :                         }
    1198             : 
    1199           1 :                         RETURN_TRUE;
    1200             :                         break;
    1201             : #endif
    1202             :                 case AF_INET:
    1203           1 :                         sin = (struct sockaddr_in *) sa;
    1204           1 :                         while (inet_ntoa_lock == 1);
    1205           1 :                         inet_ntoa_lock = 1;
    1206           1 :                         addr_string = inet_ntoa(sin->sin_addr);
    1207           1 :                         inet_ntoa_lock = 0;
    1208             : 
    1209           1 :                         zval_dtor(arg2);
    1210           1 :                         ZVAL_STRING(arg2, addr_string, 1);
    1211             : 
    1212           1 :                         if (arg3 != NULL) {
    1213           1 :                                 zval_dtor(arg3);
    1214           1 :                                 ZVAL_LONG(arg3, htons(sin->sin_port));
    1215             :                         }
    1216             : 
    1217           1 :                         RETURN_TRUE;
    1218             :                         break;
    1219             : 
    1220             :                 case AF_UNIX:
    1221           0 :                         s_un = (struct sockaddr_un *) sa;
    1222             : 
    1223           0 :                         zval_dtor(arg2);
    1224           0 :                         ZVAL_STRING(arg2, s_un->sun_path, 1);
    1225           0 :                         RETURN_TRUE;
    1226             :                         break;
    1227             : 
    1228             :                 default:
    1229           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported address family %d", sa->sa_family);
    1230           0 :                         RETURN_FALSE;
    1231             :         }
    1232             : }
    1233             : /* }}} */
    1234             : 
    1235             : /* {{{ proto resource socket_create(int domain, int type, int protocol) U
    1236             :    Creates an endpoint for communication in the domain specified by domain, of type specified by type */
    1237          28 : PHP_FUNCTION(socket_create)
    1238             : {
    1239             :         long            arg1, arg2, arg3;
    1240          28 :         php_socket      *php_sock = (php_socket*)emalloc(sizeof(php_socket));
    1241             : 
    1242          28 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) {
    1243           6 :                 efree(php_sock);
    1244           6 :                 return;
    1245             :         }
    1246             : 
    1247          51 :         if (arg1 != AF_UNIX
    1248             : #if HAVE_IPV6
    1249          22 :                 && arg1 != AF_INET6
    1250             : #endif
    1251          29 :                 && arg1 != AF_INET) {
    1252           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1);
    1253           0 :                 arg1 = AF_INET;
    1254             :         }
    1255             : 
    1256          22 :         if (arg2 > 10) {
    1257           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2);
    1258           0 :                 arg2 = SOCK_STREAM;
    1259             :         }
    1260             : 
    1261          22 :         php_sock->bsd_socket = socket(arg1, arg2, arg3);
    1262          22 :         php_sock->type = arg1;
    1263             : 
    1264          22 :         if (IS_INVALID_SOCKET(php_sock)) {
    1265           1 :                 SOCKETS_G(last_error) = errno;
    1266           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, php_strerror(errno TSRMLS_CC));
    1267           1 :                 efree(php_sock);
    1268           1 :                 RETURN_FALSE;
    1269             :         }
    1270             : 
    1271          21 :         php_sock->error = 0;
    1272          21 :         php_sock->blocking = 1;
    1273             : 
    1274          21 :         ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
    1275             : }
    1276             : /* }}} */
    1277             : 
    1278             : /* {{{ proto bool socket_connect(resource socket, string addr [, int port])
    1279             :    Opens a connection to addr:port on the socket specified by socket */
    1280          10 : PHP_FUNCTION(socket_connect)
    1281             : {
    1282             :         zval                            *arg1;
    1283             :         php_socket                      *php_sock;
    1284             :         struct sockaddr_in      sin;
    1285             : #if HAVE_IPV6
    1286             :         struct sockaddr_in6     sin6;
    1287             : #endif
    1288             :         struct sockaddr_un      s_un;
    1289             :         char                            *addr;
    1290             :         int                                     retval, addr_len;
    1291          10 :         long                            port = 0;
    1292          10 :         int                                     argc = ZEND_NUM_ARGS();
    1293             : 
    1294          10 :         if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
    1295           2 :                 return;
    1296             :         }
    1297             : 
    1298           8 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1299             : 
    1300           8 :         switch(php_sock->type) {
    1301             : #if HAVE_IPV6
    1302             :                 case AF_INET6:
    1303           2 :                         if (argc != 3) {
    1304           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET6 requires 3 arguments");
    1305           0 :                                 RETURN_FALSE;
    1306             :                         }
    1307             : 
    1308           2 :                         memset(&sin6, 0, sizeof(struct sockaddr_in6));
    1309             : 
    1310           2 :                         sin6.sin6_family = AF_INET6;
    1311           2 :                         sin6.sin6_port   = htons((unsigned short int)port);
    1312             : 
    1313           2 :                         if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) {
    1314           0 :                                 RETURN_FALSE;
    1315             :                         }
    1316             : 
    1317           2 :                         retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin6, sizeof(struct sockaddr_in6));
    1318           2 :                         break;
    1319             : #endif
    1320             :                 case AF_INET:
    1321           5 :                         if (argc != 3) {
    1322           1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET requires 3 arguments");
    1323           1 :                                 RETURN_FALSE;
    1324             :                         }
    1325             : 
    1326           4 :                         memset(&sin, 0, sizeof(struct sockaddr_in));
    1327             : 
    1328           4 :                         sin.sin_family = AF_INET;
    1329           4 :                         sin.sin_port   = htons((unsigned short int)port);
    1330             : 
    1331           4 :                         if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) {
    1332           0 :                                 RETURN_FALSE;
    1333             :                         }
    1334             : 
    1335           4 :                         retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
    1336           4 :                         break;
    1337             : 
    1338             :                 case AF_UNIX:
    1339           1 :                         if (addr_len >= sizeof(s_un.sun_path)) {
    1340           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Path too long");
    1341           0 :                                 RETURN_FALSE;
    1342             :                         }
    1343             :                                 
    1344           1 :                         memset(&s_un, 0, sizeof(struct sockaddr_un));
    1345             : 
    1346           1 :                         s_un.sun_family = AF_UNIX;
    1347           1 :                         memcpy(&s_un.sun_path, addr, addr_len);
    1348           1 :                         retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un, (socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + addr_len);
    1349           1 :                         break;
    1350             : 
    1351             :                 default:
    1352           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
    1353           0 :                         RETURN_FALSE;
    1354             :                 }
    1355             : 
    1356           7 :         if (retval != 0) {
    1357           1 :                 PHP_SOCKET_ERROR(php_sock, "unable to connect", errno);
    1358           1 :                 RETURN_FALSE;
    1359             :         }
    1360             : 
    1361           6 :         RETURN_TRUE;
    1362             : }
    1363             : /* }}} */
    1364             : 
    1365             : /* {{{ proto string socket_strerror(int errno)
    1366             :    Returns a string describing an error */
    1367         134 : PHP_FUNCTION(socket_strerror)
    1368             : {
    1369             :         long    arg1;
    1370             : 
    1371         134 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg1) == FAILURE) {
    1372           1 :                 return;
    1373             :         }
    1374             : 
    1375         133 :         RETURN_STRING(php_strerror(arg1 TSRMLS_CC), 1);
    1376             : }
    1377             : /* }}} */
    1378             : 
    1379             : /* {{{ proto bool socket_bind(resource socket, string addr [, int port])
    1380             :    Binds an open socket to a listening port, port is only specified in AF_INET family. */
    1381          13 : PHP_FUNCTION(socket_bind)
    1382             : {
    1383             :         zval                                    *arg1;
    1384             :         php_sockaddr_storage    sa_storage;
    1385          13 :         struct sockaddr                 *sock_type = (struct sockaddr*) &sa_storage;
    1386             :         php_socket                              *php_sock;
    1387             :         char                                    *addr;
    1388             :         int                                             addr_len;
    1389          13 :         long                                    port = 0;
    1390          13 :         long                                    retval = 0;
    1391             : 
    1392          13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
    1393           2 :                 return;
    1394             :         }
    1395             : 
    1396          11 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1397             : 
    1398          11 :         switch(php_sock->type) {
    1399             :                 case AF_UNIX:
    1400             :                         {
    1401           2 :                                 struct sockaddr_un *sa = (struct sockaddr_un *) sock_type;
    1402           2 :                                 memset(sa, 0, sizeof(sa_storage));
    1403           2 :                                 sa->sun_family = AF_UNIX;
    1404           2 :                                 snprintf(sa->sun_path, 108, "%s", addr);
    1405           2 :                                 retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, SUN_LEN(sa));
    1406           2 :                                 break;
    1407             :                         }
    1408             : 
    1409             :                 case AF_INET:
    1410             :                         {
    1411           6 :                                 struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
    1412             : 
    1413           6 :                                 memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
    1414             : 
    1415           6 :                                 sa->sin_family = AF_INET;
    1416           6 :                                 sa->sin_port = htons((unsigned short) port);
    1417             : 
    1418           6 :                                 if (! php_set_inet_addr(sa, addr, php_sock TSRMLS_CC)) {
    1419           0 :                                         RETURN_FALSE;
    1420             :                                 }
    1421             : 
    1422           6 :                                 retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in));
    1423           6 :                                 break;
    1424             :                         }
    1425             : #if HAVE_IPV6
    1426             :                 case AF_INET6:
    1427             :                         {
    1428           3 :                                 struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type;
    1429             : 
    1430           3 :                                 memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
    1431             : 
    1432           3 :                                 sa->sin6_family = AF_INET6;
    1433           3 :                                 sa->sin6_port = htons((unsigned short) port);
    1434             : 
    1435           3 :                                 if (! php_set_inet6_addr(sa, addr, php_sock TSRMLS_CC)) {
    1436           0 :                                         RETURN_FALSE;
    1437             :                                 }
    1438             : 
    1439           3 :                                 retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in6));
    1440           3 :                                 break;
    1441             :                         }
    1442             : #endif
    1443             :                 default:
    1444           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported socket type '%d', must be AF_UNIX, AF_INET, or AF_INET6", php_sock->type);
    1445           0 :                         RETURN_FALSE;
    1446             :         }
    1447             : 
    1448          11 :         if (retval != 0) {
    1449           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to bind address", errno);
    1450           0 :                 RETURN_FALSE;
    1451             :         }
    1452             : 
    1453          11 :         RETURN_TRUE;
    1454             : }
    1455             : /* }}} */
    1456             : 
    1457             : /* {{{ proto int socket_recv(resource socket, string &buf, int len, int flags)
    1458             :    Receives data from a connected socket */
    1459           0 : PHP_FUNCTION(socket_recv)
    1460             : {
    1461             :         zval            *php_sock_res, *buf;
    1462             :         char            *recv_buf;
    1463             :         php_socket      *php_sock;
    1464             :         int                     retval;
    1465             :         long            len, flags;
    1466             : 
    1467           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) {
    1468           0 :                 return;
    1469             :         }
    1470             : 
    1471           0 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &php_sock_res, -1, le_socket_name, le_socket);
    1472             : 
    1473             :         /* overflow check */
    1474           0 :         if ((len + 1) < 2) {
    1475           0 :                 RETURN_FALSE;
    1476             :         }
    1477             : 
    1478           0 :         recv_buf = emalloc(len + 1);
    1479           0 :         memset(recv_buf, 0, len + 1);
    1480             : 
    1481           0 :         if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {
    1482           0 :                 efree(recv_buf);
    1483             : 
    1484           0 :                 zval_dtor(buf);
    1485           0 :                 Z_TYPE_P(buf) = IS_NULL;
    1486             :         } else {
    1487           0 :                 recv_buf[retval] = '\0';
    1488             : 
    1489             :                 /* Rebuild buffer zval */
    1490           0 :                 zval_dtor(buf);
    1491             : 
    1492           0 :                 Z_STRVAL_P(buf) = recv_buf;
    1493           0 :                 Z_STRLEN_P(buf) = retval;
    1494           0 :                 Z_TYPE_P(buf) = IS_STRING;
    1495             :         }
    1496             : 
    1497           0 :         if (retval == -1) {
    1498           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
    1499           0 :                 RETURN_FALSE;
    1500             :         }
    1501             : 
    1502           0 :         RETURN_LONG(retval);
    1503             : }
    1504             : /* }}} */
    1505             : 
    1506             : /* {{{ proto int socket_send(resource socket, string buf, int len, int flags)
    1507             :    Sends data to a connected socket */
    1508           0 : PHP_FUNCTION(socket_send)
    1509             : {
    1510             :         zval            *arg1;
    1511             :         php_socket      *php_sock;
    1512             :         int                     buf_len, retval;
    1513             :         long            len, flags;
    1514             :         char            *buf;
    1515             : 
    1516           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsll", &arg1, &buf, &buf_len, &len, &flags) == FAILURE) {
    1517           0 :                 return;
    1518             :         }
    1519             : 
    1520           0 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1521             : 
    1522           0 :         retval = send(php_sock->bsd_socket, buf, (buf_len < len ? buf_len : len), flags);
    1523             : 
    1524           0 :         if (retval == -1) {
    1525           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
    1526           0 :                 RETURN_FALSE;
    1527             :         }
    1528             : 
    1529           0 :         RETURN_LONG(retval);
    1530             : }
    1531             : /* }}} */
    1532             : 
    1533             : /* {{{ proto int socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port])
    1534             :    Receives data from a socket, connected or not */
    1535          11 : PHP_FUNCTION(socket_recvfrom)
    1536             : {
    1537          11 :         zval                            *arg1, *arg2, *arg5, *arg6 = NULL;
    1538             :         php_socket                      *php_sock;
    1539             :         struct sockaddr_un      s_un;
    1540             :         struct sockaddr_in      sin;
    1541             : #if HAVE_IPV6
    1542             :         struct sockaddr_in6     sin6;
    1543             :         char                            addr6[INET6_ADDRSTRLEN];
    1544             : #endif
    1545             :         socklen_t                       slen;
    1546             :         int                                     retval;
    1547             :         long                            arg3, arg4;
    1548             :         char                            *recv_buf, *address;
    1549             : 
    1550          11 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
    1551           2 :                 return;
    1552             :         }
    1553             : 
    1554           9 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1555             : 
    1556             :         /* overflow check */
    1557           9 :         if ((arg3 + 2) < 3) {
    1558           1 :                 RETURN_FALSE;
    1559             :         }
    1560             : 
    1561           8 :         recv_buf = emalloc(arg3 + 2);
    1562           8 :         memset(recv_buf, 0, arg3 + 2);
    1563             : 
    1564           8 :         switch (php_sock->type) {
    1565             :                 case AF_UNIX:
    1566           2 :                         slen = sizeof(s_un);
    1567           2 :                         s_un.sun_family = AF_UNIX;
    1568           2 :                         retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&s_un, (socklen_t *)&slen);
    1569             : 
    1570           2 :                         if (retval < 0) {
    1571           1 :                                 efree(recv_buf);
    1572           1 :                                 PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
    1573           1 :                                 RETURN_FALSE;
    1574             :                         }
    1575             : 
    1576           1 :                         zval_dtor(arg2);
    1577           1 :                         zval_dtor(arg5);
    1578             : 
    1579           1 :                         ZVAL_STRINGL(arg2, recv_buf, retval, 0);
    1580           1 :                         ZVAL_STRING(arg5, s_un.sun_path, 1);
    1581           1 :                         break;
    1582             : 
    1583             :                 case AF_INET:
    1584           3 :                         slen = sizeof(sin);
    1585           3 :                         memset(&sin, 0, slen);
    1586           3 :                         sin.sin_family = AF_INET;
    1587             : 
    1588           3 :                         if (arg6 == NULL) {
    1589           1 :                                 efree(recv_buf);
    1590           1 :                                 WRONG_PARAM_COUNT;
    1591             :                         }
    1592             : 
    1593           2 :                         retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin, (socklen_t *)&slen);
    1594             : 
    1595           2 :                         if (retval < 0) {
    1596           1 :                                 efree(recv_buf);
    1597           1 :                                 PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
    1598           1 :                                 RETURN_FALSE;
    1599             :                         }
    1600             : 
    1601           1 :                         zval_dtor(arg2);
    1602           1 :                         zval_dtor(arg5);
    1603           1 :                         zval_dtor(arg6);
    1604             : 
    1605           1 :                         address = inet_ntoa(sin.sin_addr);
    1606             : 
    1607           1 :                         ZVAL_STRINGL(arg2, recv_buf, retval, 0);
    1608           1 :                         ZVAL_STRING(arg5, address ? address : "0.0.0.0", 1);
    1609           1 :                         ZVAL_LONG(arg6, ntohs(sin.sin_port));
    1610           1 :                         break;
    1611             : #if HAVE_IPV6
    1612             :                 case AF_INET6:
    1613           3 :                         slen = sizeof(sin6);
    1614           3 :                         memset(&sin6, 0, slen);
    1615           3 :                         sin6.sin6_family = AF_INET6;
    1616             : 
    1617           3 :                         if (arg6 == NULL) {
    1618           1 :                                 efree(recv_buf);
    1619           1 :                                 WRONG_PARAM_COUNT;
    1620             :                         }
    1621             : 
    1622           2 :                         retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin6, (socklen_t *)&slen);
    1623             : 
    1624           2 :                         if (retval < 0) {
    1625           1 :                                 efree(recv_buf);
    1626           1 :                                 PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
    1627           1 :                                 RETURN_FALSE;
    1628             :                         }
    1629             : 
    1630           1 :                         zval_dtor(arg2);
    1631           1 :                         zval_dtor(arg5);
    1632           1 :                         zval_dtor(arg6);
    1633             : 
    1634           1 :                         memset(addr6, 0, INET6_ADDRSTRLEN);
    1635           1 :                         inet_ntop(AF_INET6, &sin6.sin6_addr, addr6, INET6_ADDRSTRLEN);
    1636             : 
    1637           1 :                         ZVAL_STRINGL(arg2, recv_buf, retval, 0);
    1638           1 :                         ZVAL_STRING(arg5, addr6[0] ? addr6 : "::", 1);
    1639           1 :                         ZVAL_LONG(arg6, ntohs(sin6.sin6_port));
    1640           1 :                         break;
    1641             : #endif
    1642             :                 default:
    1643           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
    1644           0 :                         RETURN_FALSE;
    1645             :         }
    1646             : 
    1647           3 :         RETURN_LONG(retval);
    1648             : }
    1649             : /* }}} */
    1650             : 
    1651             : /* {{{ proto int socket_sendto(resource socket, string buf, int len, int flags, string addr [, int port])
    1652             :    Sends a message to a socket, whether it is connected or not */
    1653           6 : PHP_FUNCTION(socket_sendto)
    1654             : {
    1655             :         zval                            *arg1;
    1656             :         php_socket                      *php_sock;
    1657             :         struct sockaddr_un      s_un;
    1658             :         struct sockaddr_in      sin;
    1659             : #if HAVE_IPV6
    1660             :         struct sockaddr_in6     sin6;
    1661             : #endif
    1662             :         int                                     retval, buf_len, addr_len;
    1663           6 :         long                            len, flags, port = 0;
    1664             :         char                            *buf, *addr;
    1665           6 :         int                                     argc = ZEND_NUM_ARGS();
    1666             : 
    1667           6 :         if (zend_parse_parameters(argc TSRMLS_CC, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) {
    1668           1 :                 return;
    1669             :         }
    1670             : 
    1671           5 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1672             : 
    1673           5 :         switch (php_sock->type) {
    1674             :                 case AF_UNIX:
    1675           1 :                         memset(&s_un, 0, sizeof(s_un));
    1676           1 :                         s_un.sun_family = AF_UNIX;
    1677           1 :                         snprintf(s_un.sun_path, 108, "%s", addr);
    1678             : 
    1679           1 :                         retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len,       flags, (struct sockaddr *) &s_un, SUN_LEN(&s_un));
    1680           1 :                         break;
    1681             : 
    1682             :                 case AF_INET:
    1683           2 :                         if (argc != 6) {
    1684           1 :                                 WRONG_PARAM_COUNT;
    1685             :                         }
    1686             : 
    1687           1 :                         memset(&sin, 0, sizeof(sin));
    1688           1 :                         sin.sin_family = AF_INET;
    1689           1 :                         sin.sin_port = htons((unsigned short) port);
    1690             : 
    1691           1 :                         if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) {
    1692           0 :                                 RETURN_FALSE;
    1693             :                         }
    1694             : 
    1695           1 :                         retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin, sizeof(sin));
    1696           1 :                         break;
    1697             : #if HAVE_IPV6
    1698             :                 case AF_INET6:
    1699           2 :                         if (argc != 6) {
    1700           1 :                                 WRONG_PARAM_COUNT;
    1701             :                         }
    1702             : 
    1703           1 :                         memset(&sin6, 0, sizeof(sin6));
    1704           1 :                         sin6.sin6_family = AF_INET6;
    1705           1 :                         sin6.sin6_port = htons((unsigned short) port);
    1706             : 
    1707           1 :                         if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) {
    1708           0 :                                 RETURN_FALSE;
    1709             :                         }
    1710             : 
    1711           1 :                         retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin6, sizeof(sin6));
    1712           1 :                         break;
    1713             : #endif
    1714             :                 default:
    1715           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
    1716           0 :                         RETURN_FALSE;
    1717             :         }
    1718             : 
    1719           3 :         if (retval == -1) {
    1720           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);
    1721           0 :                 RETURN_FALSE;
    1722             :         }
    1723             : 
    1724           3 :         RETURN_LONG(retval);
    1725             : }
    1726             : /* }}} */
    1727             : 
    1728             : /* {{{ proto mixed socket_get_option(resource socket, int level, int optname) U
    1729             :    Gets socket options for the socket */
    1730           3 : PHP_FUNCTION(socket_get_option)
    1731             : {
    1732             :         zval                    *arg1;
    1733             :         struct linger   linger_val;
    1734             :         struct timeval  tv;
    1735             : #ifdef PHP_WIN32
    1736             :         int                             timeout = 0;
    1737             : #endif
    1738             :         socklen_t               optlen;
    1739             :         php_socket              *php_sock;
    1740             :         int                             other_val;
    1741             :         long                    level, optname;
    1742             : 
    1743           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &arg1, &level, &optname) == FAILURE) {
    1744           0 :                 return;
    1745             :         }
    1746             : 
    1747           3 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1748             : 
    1749           3 :         switch(optname) {
    1750             :                 case SO_LINGER:
    1751           1 :                         optlen = sizeof(linger_val);
    1752             : 
    1753           1 :                         if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&linger_val, &optlen) != 0) {
    1754           0 :                                 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
    1755           0 :                                 RETURN_FALSE;
    1756             :                         }
    1757             : 
    1758           1 :                         array_init(return_value);
    1759           1 :                         add_assoc_long(return_value, "l_onoff", linger_val.l_onoff);
    1760           1 :                         add_assoc_long(return_value, "l_linger", linger_val.l_linger);
    1761           1 :                         break;
    1762             : 
    1763             :                 case SO_RCVTIMEO:
    1764             :                 case SO_SNDTIMEO:
    1765             : #ifndef PHP_WIN32
    1766           2 :                         optlen = sizeof(tv);
    1767             : 
    1768           2 :                         if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&tv, &optlen) != 0) {
    1769           0 :                                 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
    1770           0 :                                 RETURN_FALSE;
    1771             :                         }
    1772             : #else
    1773             :                         optlen = sizeof(int);
    1774             : 
    1775             :                         if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&timeout, &optlen) != 0) {
    1776             :                                 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
    1777             :                                 RETURN_FALSE;
    1778             :                         }
    1779             : 
    1780             :                         tv.tv_sec = timeout ? timeout / 1000 : 0;
    1781             :                         tv.tv_usec = timeout ? (timeout * 1000) % 1000000 : 0;
    1782             : #endif
    1783             : 
    1784           2 :                         array_init(return_value);
    1785             : 
    1786           2 :                         add_assoc_long(return_value, "sec", tv.tv_sec);
    1787           2 :                         add_assoc_long(return_value, "usec", tv.tv_usec);
    1788           2 :                         break;
    1789             : 
    1790             :                 default:
    1791           0 :                         optlen = sizeof(other_val);
    1792             : 
    1793           0 :                         if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&other_val, &optlen) != 0) {
    1794           0 :                                 PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
    1795           0 :                                 RETURN_FALSE;
    1796             :                         }
    1797             : 
    1798           0 :                         RETURN_LONG(other_val);
    1799             :                         break;
    1800             :         }
    1801             : }
    1802             : /* }}} */
    1803             : 
    1804             : /* {{{ proto bool socket_set_option(resource socket, int level, int optname, int|array optval)
    1805             :    Sets socket options for the socket */
    1806           8 : PHP_FUNCTION(socket_set_option)
    1807             : {
    1808             :         zval                    *arg1, **arg4;
    1809             :         struct linger   lv;
    1810             :         php_socket              *php_sock;
    1811             :         int                             ov, optlen, retval;
    1812             : #ifdef PHP_WIN32
    1813             :         int                             timeout;
    1814             : #else
    1815             :         struct                  timeval tv;
    1816             : #endif
    1817             :         long                    level, optname;
    1818             :         void                    *opt_ptr;
    1819             :         HashTable               *opt_ht;
    1820             :         zval                    **l_onoff, **l_linger;
    1821             :         zval                    **sec, **usec;
    1822             :         /* key name constants */
    1823           8 :         char                    *l_onoff_key = "l_onoff";
    1824           8 :         char                    *l_linger_key = "l_linger";
    1825           8 :         char                    *sec_key = "sec";
    1826           8 :         char                    *usec_key = "usec";
    1827             : 
    1828           8 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllZ", &arg1, &level, &optname, &arg4) == FAILURE) {
    1829           0 :                 return;
    1830             :         }
    1831             : 
    1832           8 :         ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
    1833             : 
    1834           8 :         set_errno(0);
    1835             : 
    1836           8 :         switch (optname) {
    1837             :                 case SO_LINGER:
    1838           3 :                         convert_to_array_ex(arg4);
    1839           3 :                         opt_ht = HASH_OF(*arg4);
    1840             : 
    1841           3 :                         if (zend_hash_find(opt_ht, l_onoff_key, strlen(l_onoff_key) + 1, (void **)&l_onoff) == FAILURE) {
    1842           1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_onoff_key);
    1843           1 :                                 RETURN_FALSE;
    1844             :                         }
    1845           2 :                         if (zend_hash_find(opt_ht, l_linger_key, strlen(l_linger_key) + 1, (void **)&l_linger) == FAILURE) {
    1846           1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_linger_key);
    1847           1 :                                 RETURN_FALSE;
    1848             :                         }
    1849             : 
    1850           1 :                         convert_to_long_ex(l_onoff);
    1851           1 :                         convert_to_long_ex(l_linger);
    1852             : 
    1853           1 :                         lv.l_onoff = (unsigned short)Z_LVAL_PP(l_onoff);
    1854           1 :                         lv.l_linger = (unsigned short)Z_LVAL_PP(l_linger);
    1855             : 
    1856           1 :                         optlen = sizeof(lv);
    1857           1 :                         opt_ptr = &lv;
    1858           1 :                         break;
    1859             : 
    1860             :                 case SO_RCVTIMEO:
    1861             :                 case SO_SNDTIMEO:
    1862           4 :                         convert_to_array_ex(arg4);
    1863           4 :                         opt_ht = HASH_OF(*arg4);
    1864             : 
    1865           4 :                         if (zend_hash_find(opt_ht, sec_key, strlen(sec_key) + 1, (void **)&sec) == FAILURE) {
    1866           2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", sec_key);
    1867           2 :                                 RETURN_FALSE;
    1868             :                         }
    1869           2 :                         if (zend_hash_find(opt_ht, usec_key, strlen(usec_key) + 1, (void **)&usec) == FAILURE) {
    1870           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", usec_key);
    1871           0 :                                 RETURN_FALSE;
    1872             :                         }
    1873             : 
    1874           2 :                         convert_to_long_ex(sec);
    1875           2 :                         convert_to_long_ex(usec);
    1876             : #ifndef PHP_WIN32
    1877           2 :                         tv.tv_sec = Z_LVAL_PP(sec);
    1878           2 :                         tv.tv_usec = Z_LVAL_PP(usec);
    1879           2 :                         optlen = sizeof(tv);
    1880           2 :                         opt_ptr = &tv;
    1881             : #else
    1882             :                         timeout = Z_LVAL_PP(sec) * 1000 + Z_LVAL_PP(usec) / 1000;
    1883             :                         optlen = sizeof(int);
    1884             :                         opt_ptr = &timeout;
    1885             : #endif
    1886           2 :                         break;
    1887             : 
    1888             :                 default:
    1889           1 :                         convert_to_long_ex(arg4);
    1890           1 :                         ov = Z_LVAL_PP(arg4);
    1891             : 
    1892           1 :                         optlen = sizeof(ov);
    1893           1 :                         opt_ptr = &ov;
    1894             :                         break;
    1895             :         }
    1896             : 
    1897           4 :         retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
    1898             : 
    1899           4 :         if (retval != 0) {
    1900           1 :                 PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
    1901           1 :                 RETURN_FALSE;
    1902             :         }
    1903             : 
    1904           3 :         RETURN_TRUE;
    1905             : }
    1906             : /* }}} */
    1907             : 
    1908             : #ifdef HAVE_SOCKETPAIR
    1909             : /* {{{ proto bool socket_create_pair(int domain, int type, int protocol, array &fd) U
    1910             :    Creates a pair of indistinguishable sockets and stores them in fds. */
    1911          10 : PHP_FUNCTION(socket_create_pair)
    1912             : {
    1913             :         zval            *retval[2], *fds_array_zval;
    1914             :         php_socket      *php_sock[2];
    1915             :         PHP_SOCKET      fds_array[2];
    1916             :         long            domain, type, protocol;
    1917             : 
    1918          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lllz", &domain, &type, &protocol, &fds_array_zval) == FAILURE) {
    1919           2 :                 return;
    1920             :         }
    1921             : 
    1922           8 :         php_sock[0] = (php_socket*)emalloc(sizeof(php_socket));
    1923           8 :         php_sock[1] = (php_socket*)emalloc(sizeof(php_socket));
    1924             : 
    1925          20 :         if (domain != AF_INET
    1926             : #if HAVE_IPV6
    1927           8 :                 && domain != AF_INET6
    1928             : #endif
    1929          12 :                 && domain != AF_UNIX) {
    1930           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", domain);
    1931           1 :                 domain = AF_INET;
    1932             :         }
    1933             : 
    1934           8 :         if (type > 10) {
    1935           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", type);
    1936           1 :                 type = SOCK_STREAM;
    1937             :         }
    1938             : 
    1939           8 :         if (socketpair(domain, type, protocol, fds_array) != 0) {
    1940           3 :                 SOCKETS_G(last_error) = errno;
    1941           3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to create socket pair [%d]: %s", errno, php_strerror(errno TSRMLS_CC));
    1942           3 :                 efree(php_sock[0]);
    1943           3 :                 efree(php_sock[1]);
    1944           3 :                 RETURN_FALSE;
    1945             :         }
    1946             : 
    1947           5 :         zval_dtor(fds_array_zval);
    1948           5 :         array_init(fds_array_zval);
    1949             : 
    1950           5 :         MAKE_STD_ZVAL(retval[0]);
    1951           5 :         MAKE_STD_ZVAL(retval[1]);
    1952             : 
    1953           5 :         php_sock[0]->bsd_socket = fds_array[0];
    1954           5 :         php_sock[1]->bsd_socket = fds_array[1];
    1955           5 :         php_sock[0]->type            = domain;
    1956           5 :         php_sock[1]->type            = domain;
    1957           5 :         php_sock[0]->error           = 0;
    1958           5 :         php_sock[1]->error           = 0;
    1959           5 :         php_sock[0]->blocking        = 1;
    1960           5 :         php_sock[1]->blocking        = 1;
    1961             : 
    1962           5 :         ZEND_REGISTER_RESOURCE(retval[0], php_sock[0], le_socket);
    1963           5 :         ZEND_REGISTER_RESOURCE(retval[1], php_sock[1], le_socket);
    1964             : 
    1965           5 :         add_index_zval(fds_array_zval, 0, retval[0]);
    1966           5 :         add_index_zval(fds_array_zval, 1, retval[1]);
    1967             : 
    1968           5 :         RETURN_TRUE;
    1969             : }
    1970             : /* }}} */
    1971             : #endif
    1972             : 
    1973             : #ifdef HAVE_SHUTDOWN
    1974             : /* {{{ proto bool socket_shutdown(resource socket[, int how]) U
    1975             :    Shuts down a socket for receiving, sending, or both. */
    1976           0 : PHP_FUNCTION(socket_shutdown)
    1977             : {
    1978             :         zval            *arg1;
    1979           0 :         long            how_shutdown = 2;
    1980             :         php_socket      *php_sock;
    1981             : 
    1982           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &how_shutdown) == FAILURE) {
    1983           0 :                 return;
    1984             :         }
    1985             : 
    1986           0 :         ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket);
    1987             : 
    1988           0 :         if (shutdown(php_sock->bsd_socket, how_shutdown) != 0) {
    1989           0 :                 PHP_SOCKET_ERROR(php_sock, "unable to shutdown socket", errno);
    1990           0 :                 RETURN_FALSE;
    1991             :         }
    1992             : 
    1993           0 :         RETURN_TRUE;
    1994             : }
    1995             : /* }}} */
    1996             : #endif
    1997             : 
    1998             : /* {{{ proto int socket_last_error([resource socket]) U
    1999             :    Returns the last socket error (either the last used or the provided socket resource) */
    2000           0 : PHP_FUNCTION(socket_last_error)
    2001             : {
    2002           0 :         zval            *arg1 = NULL;
    2003             :         php_socket      *php_sock;
    2004             : 
    2005           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg1) == FAILURE) {
    2006           0 :                 return;
    2007             :         }
    2008             : 
    2009           0 :         if (arg1) {
    2010           0 :                 ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket);
    2011           0 :                 RETVAL_LONG(php_sock->error);
    2012             :         } else {
    2013           0 :                 RETVAL_LONG(SOCKETS_G(last_error));
    2014             :         }
    2015             : }
    2016             : /* }}} */
    2017             : 
    2018             : /* {{{ proto void socket_clear_error([resource socket]) U
    2019             :    Clears the error on the socket or the last error code. */
    2020           0 : PHP_FUNCTION(socket_clear_error)
    2021             : {
    2022           0 :         zval            *arg1 = NULL;
    2023             :         php_socket      *php_sock;
    2024             : 
    2025           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg1) == FAILURE) {
    2026           0 :                 return;
    2027             :         }
    2028             : 
    2029           0 :         if (arg1) {
    2030           0 :                 ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket);
    2031           0 :                 php_sock->error = 0;
    2032             :         } else {
    2033           0 :                 SOCKETS_G(last_error) = 0;
    2034             :         }
    2035             : 
    2036           0 :         return;
    2037             : }
    2038             : /* }}} */
    2039             : 
    2040             : #endif
    2041             : 
    2042             : /*
    2043             :  * Local variables:
    2044             :  * tab-width: 4
    2045             :  * c-basic-offset: 4
    2046             :  * End:
    2047             :  * vim600: fdm=marker
    2048             :  * vim: noet sw=4 ts=4
    2049             :  */

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:35 +0000 (15 hours ago)

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