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

LTP GCOV extension - code coverage report
Current view: directory - sockets - sockets.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 755
Code covered: 74.6 % Executed lines: 563
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:19 +0000 (5 days ago)

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