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-23 Instrumented lines: 759
Code covered: 71.9 % Executed lines: 546
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:38 +0000 (34 hours ago)

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