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-21 Instrumented lines: 762
Code covered: 74.1 % Executed lines: 565
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:09 +0000 (3 days ago)

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