diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-03-14 05:42:27 +0000 |
---|---|---|
committer | <> | 2013-04-03 16:25:08 +0000 |
commit | c4dd7a1a684490673e25aaf4fabec5df138854c4 (patch) | |
tree | 4d57c44caae4480efff02b90b9be86f44bf25409 /ext/sockets | |
download | php2-master.tar.gz |
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/sockets')
76 files changed, 6990 insertions, 0 deletions
diff --git a/ext/sockets/CREDITS b/ext/sockets/CREDITS new file mode 100644 index 0000000..2be7552 --- /dev/null +++ b/ext/sockets/CREDITS @@ -0,0 +1,2 @@ +Sockets +Chris Vandomelen, Sterling Hughes, Daniel Beulshausen, Jason Greene diff --git a/ext/sockets/config.m4 b/ext/sockets/config.m4 new file mode 100644 index 0000000..4032621 --- /dev/null +++ b/ext/sockets/config.m4 @@ -0,0 +1,48 @@ +dnl +dnl $Id$ +dnl + +PHP_ARG_ENABLE(sockets, whether to enable sockets support, +[ --enable-sockets Enable sockets support]) + +if test "$PHP_SOCKETS" != "no"; then + dnl Check for struct cmsghdr + AC_CACHE_CHECK([for struct cmsghdr], ac_cv_cmsghdr, + [ + AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/socket.h>], [struct cmsghdr s; s], ac_cv_cmsghdr=yes, ac_cv_cmsghdr=no) + ]) + + if test "$ac_cv_cmsghdr" = yes; then + AC_DEFINE(HAVE_CMSGHDR,1,[Whether you have struct cmsghdr]) + fi + + AC_CHECK_FUNCS([hstrerror socketpair if_nametoindex if_indextoname]) + AC_CHECK_HEADERS([netdb.h netinet/tcp.h sys/un.h sys/sockio.h errno.h]) + AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/socket.h> + ], [static struct msghdr tp; int n = (int) tp.msg_flags; return n],[], + [AC_DEFINE(MISSING_MSGHDR_MSGFLAGS, 1, [ ])] + ) + AC_DEFINE([HAVE_SOCKETS], 1, [ ]) + + dnl Check for fied ss_family in sockaddr_storage (missing in AIX until 5.3) + AC_CACHE_CHECK([for field ss_family in struct sockaddr_storage], ac_cv_ss_family, + [ + AC_TRY_COMPILE([ +#include <sys/socket.h> +#include <sys/types.h> +#include <netdb.h> + ], [struct sockaddr_storage sa_store; sa_store.ss_family = AF_INET6;], + ac_cv_ss_family=yes, ac_cv_ss_family=no) + ]) + + if test "$ac_cv_ss_family" = yes; then + AC_DEFINE(HAVE_SA_SS_FAMILY,1,[Whether you have sockaddr_storage.ss_family]) + fi + + PHP_NEW_EXTENSION([sockets], [sockets.c multicast.c], [$ext_shared]) + PHP_INSTALL_HEADERS([ext/sockets/], [php_sockets.h]) +fi diff --git a/ext/sockets/config.w32 b/ext/sockets/config.w32 new file mode 100644 index 0000000..9c234db --- /dev/null +++ b/ext/sockets/config.w32 @@ -0,0 +1,17 @@ +// $Id$ +// vim:ft=javascript + +ARG_ENABLE("sockets", "SOCKETS support", "no"); + +if (PHP_SOCKETS != "no") { + if (CHECK_LIB("ws2_32.lib", "sockets", PHP_SOCKETS) + && CHECK_LIB("Iphlpapi.lib", "sockets", PHP_SOCKETS) + && CHECK_HEADER_ADD_INCLUDE("winsock.h", "CFLAGS_SOCKETS")) { + EXTENSION('sockets', 'sockets.c multicast.c'); + AC_DEFINE('HAVE_SOCKETS', 1); + PHP_INSTALL_HEADERS("ext/sockets", "php_sockets.h"); + } else { + WARNING("sockets not enabled; libraries and headers not found"); + } +} + diff --git a/ext/sockets/multicast.c b/ext/sockets/multicast.c new file mode 100644 index 0000000..43b6f7d --- /dev/null +++ b/ext/sockets/multicast.c @@ -0,0 +1,545 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Gustavo Lopes <cataphract@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#if HAVE_SOCKETS + +#include "php_network.h" +#ifdef PHP_WIN32 +# include "win32/inet.h" +# include <winsock2.h> +# include <windows.h> +# include <Ws2tcpip.h> +# include <Ws2ipdef.h> +# include "php_sockets.h" +# include "win32/sockets.h" +# define NTDDI_XP NTDDI_WINXP /* bug in SDK */ +# include <IPHlpApi.h> +# undef NTDDI_XP +#else +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif +#include <netinet/in.h> +#include <arpa/inet.h> +#endif + +#include "php_sockets.h" +#include "multicast.h" +#include "main/php_network.h" + + +enum source_op { + JOIN_SOURCE, + LEAVE_SOURCE, + BLOCK_SOURCE, + UNBLOCK_SOURCE +}; + +static int _php_mcast_join_leave(php_socket *sock, int level, struct sockaddr *group, socklen_t group_len, unsigned int if_index, int join TSRMLS_DC); +#ifdef HAS_MCAST_EXT +static int _php_mcast_source_op(php_socket *sock, int level, struct sockaddr *group, socklen_t group_len, struct sockaddr *source, socklen_t source_len, unsigned int if_index, enum source_op sop TSRMLS_DC); +#endif + +#ifdef RFC3678_API +static int _php_source_op_to_rfc3678_op(enum source_op sop); +#elif HAS_MCAST_EXT +static const char *_php_source_op_to_string(enum source_op sop); +static int _php_source_op_to_ipv4_op(enum source_op sop); +#endif + +int php_mcast_join( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + unsigned int if_index TSRMLS_DC) +{ + return _php_mcast_join_leave(sock, level, group, group_len, if_index, 1 TSRMLS_CC); +} + +int php_mcast_leave( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + unsigned int if_index TSRMLS_DC) +{ + return _php_mcast_join_leave(sock, level, group, group_len, if_index, 0 TSRMLS_CC); +} + +#ifdef HAS_MCAST_EXT +int php_mcast_join_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC) +{ + return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, JOIN_SOURCE TSRMLS_CC); +} + +int php_mcast_leave_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC) +{ + return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, LEAVE_SOURCE TSRMLS_CC); +} + +int php_mcast_block_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC) +{ + return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, BLOCK_SOURCE TSRMLS_CC); +} + +int php_mcast_unblock_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC) +{ + return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, UNBLOCK_SOURCE TSRMLS_CC); +} +#endif /* HAS_MCAST_EXT */ + + +static int _php_mcast_join_leave( + php_socket *sock, + int level, + struct sockaddr *group, /* struct sockaddr_in/sockaddr_in6 */ + socklen_t group_len, + unsigned int if_index, + int join TSRMLS_DC) +{ +#ifdef RFC3678_API + struct group_req greq = {0}; + + memcpy(&greq.gr_group, group, group_len); + assert(greq.gr_group.ss_family != 0); /* the caller has set this */ + greq.gr_interface = if_index; + + return setsockopt(sock->bsd_socket, level, + join ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (char*)&greq, + sizeof(greq)); +#else + if (sock->type == AF_INET) { + struct ip_mreq mreq = {0}; + struct in_addr addr; + + assert(group_len == sizeof(struct sockaddr_in)); + + if (if_index != 0) { + if (php_if_index_to_addr4(if_index, sock, &addr TSRMLS_CC) == + FAILURE) + return -2; /* failure, but notice already emitted */ + mreq.imr_interface = addr; + } else { + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } + mreq.imr_multiaddr = ((struct sockaddr_in*)group)->sin_addr; + return setsockopt(sock->bsd_socket, level, + join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, (char*)&mreq, + sizeof(mreq)); + } +#if HAVE_IPV6 + else if (sock->type == AF_INET6) { + struct ipv6_mreq mreq = {0}; + + assert(group_len == sizeof(struct sockaddr_in6)); + + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6*)group)->sin6_addr; + mreq.ipv6mr_interface = if_index; + + return setsockopt(sock->bsd_socket, level, + join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, (char*)&mreq, + sizeof(mreq)); + } +#endif + else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Option %s is inapplicable to this socket type", + join ? "MCAST_JOIN_GROUP" : "MCAST_LEAVE_GROUP"); + return -2; + } +#endif +} + +#ifdef HAS_MCAST_EXT +static int _php_mcast_source_op( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index, + enum source_op sop TSRMLS_DC) +{ +#ifdef RFC3678_API + struct group_source_req gsreq = {0}; + + memcpy(&gsreq.gsr_group, group, group_len); + assert(gsreq.gsr_group.ss_family != 0); + memcpy(&gsreq.gsr_source, source, source_len); + assert(gsreq.gsr_source.ss_family != 0); + gsreq.gsr_interface = if_index; + + return setsockopt(sock->bsd_socket, level, + _php_source_op_to_rfc3678_op(sop), (char*)&gsreq, sizeof(gsreq)); +#else + if (sock->type == AF_INET) { + struct ip_mreq_source mreqs = {0}; + struct in_addr addr; + + mreqs.imr_multiaddr = ((struct sockaddr_in*)group)->sin_addr; + mreqs.imr_sourceaddr = ((struct sockaddr_in*)source)->sin_addr; + + assert(group_len == sizeof(struct sockaddr_in)); + assert(source_len == sizeof(struct sockaddr_in)); + + if (if_index != 0) { + if (php_if_index_to_addr4(if_index, sock, &addr TSRMLS_CC) == + FAILURE) + return -2; /* failure, but notice already emitted */ + mreqs.imr_interface = addr; + } else { + mreqs.imr_interface.s_addr = htonl(INADDR_ANY); + } + + return setsockopt(sock->bsd_socket, level, + _php_source_op_to_ipv4_op(sop), (char*)&mreqs, sizeof(mreqs)); + } +#if HAVE_IPV6 + else if (sock->type == AF_INET6) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "This platform does not support %s for IPv6 sockets", + _php_source_op_to_string(sop)); + return -2; + } +#endif + else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Option %s is inapplicable to this socket type", + _php_source_op_to_string(sop)); + return -2; + } +#endif +} + +#if RFC3678_API +static int _php_source_op_to_rfc3678_op(enum source_op sop) +{ + switch (sop) { + case JOIN_SOURCE: + return MCAST_JOIN_SOURCE_GROUP; + case LEAVE_SOURCE: + return MCAST_LEAVE_SOURCE_GROUP; + case BLOCK_SOURCE: + return MCAST_BLOCK_SOURCE; + case UNBLOCK_SOURCE: + return MCAST_UNBLOCK_SOURCE; + } + + assert(0); + return 0; +} +#else +static const char *_php_source_op_to_string(enum source_op sop) +{ + switch (sop) { + case JOIN_SOURCE: + return "MCAST_JOIN_SOURCE_GROUP"; + case LEAVE_SOURCE: + return "MCAST_LEAVE_SOURCE_GROUP"; + case BLOCK_SOURCE: + return "MCAST_BLOCK_SOURCE"; + case UNBLOCK_SOURCE: + return "MCAST_UNBLOCK_SOURCE"; + } + + assert(0); + return ""; +} + +static int _php_source_op_to_ipv4_op(enum source_op sop) +{ + switch (sop) { + case JOIN_SOURCE: + return IP_ADD_SOURCE_MEMBERSHIP; + case LEAVE_SOURCE: + return IP_DROP_SOURCE_MEMBERSHIP; + case BLOCK_SOURCE: + return IP_BLOCK_SOURCE; + case UNBLOCK_SOURCE: + return IP_UNBLOCK_SOURCE; + } + + assert(0); + return 0; +} +#endif + +#endif /* HAS_MCAST_EXT */ + +#if PHP_WIN32 +int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_addr *out_addr TSRMLS_DC) +{ + MIB_IPADDRTABLE *addr_table; + ULONG size; + DWORD retval; + DWORD i; + + (void) php_sock; /* not necessary */ + + if (if_index == 0) { + out_addr->s_addr = INADDR_ANY; + return SUCCESS; + } + + size = 4 * (sizeof *addr_table); + addr_table = emalloc(size); +retry: + retval = GetIpAddrTable(addr_table, &size, 0); + if (retval == ERROR_INSUFFICIENT_BUFFER) { + efree(addr_table); + addr_table = emalloc(size); + goto retry; + } + if (retval != NO_ERROR) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "GetIpAddrTable failed with error %lu", retval); + return FAILURE; + } + for (i = 0; i < addr_table->dwNumEntries; i++) { + MIB_IPADDRROW r = addr_table->table[i]; + if (r.dwIndex == if_index) { + out_addr->s_addr = r.dwAddr; + return SUCCESS; + } + } + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "No interface with index %u was found", if_index); + return FAILURE; +} + +int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *if_index TSRMLS_DC) +{ + MIB_IPADDRTABLE *addr_table; + ULONG size; + DWORD retval; + DWORD i; + + (void) php_sock; /* not necessary */ + + if (addr->s_addr == INADDR_ANY) { + *if_index = 0; + return SUCCESS; + } + + size = 4 * (sizeof *addr_table); + addr_table = emalloc(size); +retry: + retval = GetIpAddrTable(addr_table, &size, 0); + if (retval == ERROR_INSUFFICIENT_BUFFER) { + efree(addr_table); + addr_table = emalloc(size); + goto retry; + } + if (retval != NO_ERROR) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "GetIpAddrTable failed with error %lu", retval); + return FAILURE; + } + for (i = 0; i < addr_table->dwNumEntries; i++) { + MIB_IPADDRROW r = addr_table->table[i]; + if (r.dwAddr == addr->s_addr) { + *if_index = r.dwIndex; + return SUCCESS; + } + } + + { + char addr_str[17] = {0}; + inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "The interface with IP address %s was not found", addr_str); + } + return FAILURE; +} + +#else + +int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_addr *out_addr TSRMLS_DC) +{ + struct ifreq if_req; + + if (if_index == 0) { + out_addr->s_addr = INADDR_ANY; + return SUCCESS; + } + +#if !defined(ifr_ifindex) && defined(ifr_index) +#define ifr_ifindex ifr_index +#endif + +#if defined(SIOCGIFNAME) + if_req.ifr_ifindex = if_index; + if (ioctl(php_sock->bsd_socket, SIOCGIFNAME, &if_req) == -1) { +#elif defined(HAVE_IF_INDEXTONAME) + if (if_indextoname(if_index, if_req.ifr_name) == NULL) { +#else +#error Neither SIOCGIFNAME nor if_indextoname are available +#endif + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed obtaining address for interface %u: error %d", if_index, errno); + return FAILURE; + } + + if (ioctl(php_sock->bsd_socket, SIOCGIFADDR, &if_req) == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed obtaining address for interface %u: error %d", if_index, errno); + return FAILURE; + } + + memcpy(out_addr, &((struct sockaddr_in *) &if_req.ifr_addr)->sin_addr, + sizeof *out_addr); + return SUCCESS; +} + +int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *if_index TSRMLS_DC) +{ + struct ifconf if_conf = {0}; + char *buf = NULL, + *p; + int size = 0, + lastsize = 0; + size_t entry_len; + + if (addr->s_addr == INADDR_ANY) { + *if_index = 0; + return SUCCESS; + } + + for(;;) { + size += 5 * sizeof(struct ifreq); + buf = ecalloc(size, 1); + if_conf.ifc_len = size; + if_conf.ifc_buf = buf; + + if (ioctl(php_sock->bsd_socket, SIOCGIFCONF, (char*)&if_conf) == -1 && + (errno != EINVAL || lastsize != 0)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed obtaining interfaces list: error %d", errno); + goto err; + } + + if (if_conf.ifc_len == lastsize) + /* not increasing anymore */ + break; + else { + lastsize = if_conf.ifc_len; + efree(buf); + buf = NULL; + } + } + + for (p = if_conf.ifc_buf; + p < if_conf.ifc_buf + if_conf.ifc_len; + p += entry_len) { + struct ifreq *cur_req; + + /* let's hope the pointer is aligned */ + cur_req = (struct ifreq*) p; + +#ifdef HAVE_SOCKADDR_SA_LEN + entry_len = cur_req->ifr_addr.sa_len + sizeof(cur_req->ifr_name); +#else + /* if there's no sa_len, assume the ifr_addr field is a sockaddr */ + entry_len = sizeof(struct sockaddr) + sizeof(cur_req->ifr_name); +#endif + entry_len = MAX(entry_len, sizeof(*cur_req)); + + if ((((struct sockaddr*)&cur_req->ifr_addr)->sa_family == AF_INET) && + (((struct sockaddr_in*)&cur_req->ifr_addr)->sin_addr.s_addr == + addr->s_addr)) { +#if defined(SIOCGIFINDEX) + if (ioctl(php_sock->bsd_socket, SIOCGIFINDEX, (char*)cur_req) + == -1) { +#elif defined(HAVE_IF_NAMETOINDEX) + unsigned index_tmp; + if ((index_tmp = if_nametoindex(cur_req->ifr_name)) == 0) { +#else +#error Neither SIOCGIFINDEX nor if_nametoindex are available +#endif + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Error converting interface name to index: error %d", + errno); + goto err; + } else { +#if defined(SIOCGIFINDEX) + *if_index = cur_req->ifr_ifindex; +#else + *if_index = index_tmp; +#endif + efree(buf); + return SUCCESS; + } + } + } + + { + char addr_str[17] = {0}; + inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "The interface with IP address %s was not found", addr_str); + } + +err: + if (buf != NULL) + efree(buf); + return FAILURE; +} +#endif + +#endif /* HAVE_SOCKETS */ diff --git a/ext/sockets/multicast.h b/ext/sockets/multicast.h new file mode 100644 index 0000000..f46a6a8 --- /dev/null +++ b/ext/sockets/multicast.h @@ -0,0 +1,92 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Gustavo Lopes <cataphract@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#if defined(MCAST_JOIN_GROUP) && \ + (!defined(PHP_WIN32) || (_WIN32_WINNT >= 0x600 && SOCKETS_ENABLE_VISTA_API)) && \ + !defined(__APPLE__) +#define RFC3678_API 1 +/* has block/unblock and source membership, in this case for both IPv4 and IPv6 */ +#define HAS_MCAST_EXT 1 +#elif defined(IP_ADD_SOURCE_MEMBERSHIP) && !defined(__APPLE__) +/* has block/unblock and source membership, but only for IPv4 */ +#define HAS_MCAST_EXT 1 +#endif + +int php_if_index_to_addr4( + unsigned if_index, + php_socket *php_sock, + struct in_addr *out_addr TSRMLS_DC); + +int php_add4_to_if_index( + struct in_addr *addr, + php_socket *php_sock, + unsigned *if_index TSRMLS_DC); + +int php_mcast_join( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + unsigned int if_index TSRMLS_DC); + +int php_mcast_leave( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + unsigned int if_index TSRMLS_DC); + +#ifdef HAS_MCAST_EXT +int php_mcast_join_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC); + +int php_mcast_leave_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC); + +int php_mcast_block_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC); + +int php_mcast_unblock_source( + php_socket *sock, + int level, + struct sockaddr *group, + socklen_t group_len, + struct sockaddr *source, + socklen_t source_len, + unsigned int if_index TSRMLS_DC); +#endif diff --git a/ext/sockets/package.xml b/ext/sockets/package.xml new file mode 100644 index 0000000..2799fff --- /dev/null +++ b/ext/sockets/package.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "../pear/package.dtd"> +<package> + <name>sockets</name> + <summary>Socket functions</summary> + <maintainers> + <maintainer> + <user>???</user> + <name>Chris Vandomelen</name> + <email>chrisv@b0rked.dhs.org</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>sterling</user> + <name>Sterling Hughes</name> + <email>sterling@php.net</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>jason</user> + <name>Jason Greene</name> + <email>jason@php.net</email> + <role>lead</role> + </maintainer> + <maintainer> + <user>???</user> + <name>Daniel Beulshausen</name> + <email>daniel@php4win.de</email> + <role>lead</role> + </maintainer> + </maintainers> + <description> +The socket extension implements a low-level interface to the socket +communication functions based on the popular BSD sockets, providing +the possibility to act as a socket server as well as a client. + </description> + <license>PHP</license> + <release> + <state>beta</state> + <version>5.0.0rc1</version> + <date>2004-03-19</date> + <notes> +package.xml added to support installation using pear installer + </notes> + <filelist> + <file role="doc" name="CREDITS"/> + <file role="src" name="config.m4"/> + <file role="src" name="config.w32"/> + <file role="src" name="php_sockets.h"/> + <file role="src" name="php_sockets_win.c"/> + <file role="src" name="php_sockets_win.h"/> + <file role="src" name="sockets.c"/> + <file role="src" name="sockets.dsp"/> + <file role="src" name="unix_socket_constants.h"/> + <file role="src" name="win32_socket_constants.h"/> + <file role="test" name="tests/ipv4loop.phpt"/> + <file role="test" name="tests/ipv6loop.phpt"/> + </filelist> + <deps> + <dep type="php" rel="ge" version="5" /> + </deps> + </release> +</package> +<!-- +vim:et:ts=1:sw=1 +--> diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h new file mode 100644 index 0000000..fabc9c4 --- /dev/null +++ b/ext/sockets/php_sockets.h @@ -0,0 +1,90 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Chris Vandomelen <chrisv@b0rked.dhs.org> | + | Sterling Hughes <sterling@php.net> | + | | + | WinSock: Daniel Beulshausen <daniel@php4win.de> | + +----------------------------------------------------------------------+ + */ + +#ifndef PHP_SOCKETS_H +#define PHP_SOCKETS_H + +/* $Id$ */ + +#if HAVE_SOCKETS + +extern zend_module_entry sockets_module_entry; +#define phpext_sockets_ptr &sockets_module_entry + +#ifdef PHP_WIN32 +#include <winsock.h> +#else +#if HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#endif + +#ifndef PHP_WIN32 +typedef int PHP_SOCKET; +# define PHP_SOCKETS_API PHPAPI +#else +# define PHP_SOCKETS_API __declspec(dllexport) +typedef SOCKET PHP_SOCKET; +#endif + +typedef struct { + PHP_SOCKET bsd_socket; + int type; + int error; + int blocking; + zval *zstream; +} php_socket; + +#ifdef PHP_WIN32 +struct sockaddr_un { + short sun_family; + char sun_path[108]; +}; +#endif + +PHP_SOCKETS_API int php_sockets_le_socket(void); + +#define php_sockets_le_socket_name "Socket" + +ZEND_BEGIN_MODULE_GLOBALS(sockets) + int last_error; + char *strerror_buf; +ZEND_END_MODULE_GLOBALS(sockets) + +#ifdef ZTS +#define SOCKETS_G(v) TSRMG(sockets_globals_id, zend_sockets_globals *, v) +#else +#define SOCKETS_G(v) (sockets_globals.v) +#endif + +#else +#define phpext_sockets_ptr NULL +#endif + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c new file mode 100644 index 0000000..06bd0ec --- /dev/null +++ b/ext/sockets/sockets.c @@ -0,0 +1,2599 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Chris Vandomelen <chrisv@b0rked.dhs.org> | + | Sterling Hughes <sterling@php.net> | + | Jason Greene <jason@php.net> | + | Gustavo Lopes <cataphract@php.net> | + | WinSock: Daniel Beulshausen <daniel@php4win.de> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#if HAVE_SOCKETS + +#include "php_network.h" +#include "ext/standard/file.h" +#include "ext/standard/info.h" +#include "php_ini.h" +#ifdef PHP_WIN32 +# include "win32/inet.h" +# include <winsock2.h> +# include <windows.h> +# include <Ws2tcpip.h> +# include "php_sockets.h" +# include "win32/sockets.h" +# define IS_INVALID_SOCKET(a) (a->bsd_socket == INVALID_SOCKET) +# ifdef EPROTONOSUPPORT +# undef EPROTONOSUPPORT +# endif +# ifdef ECONNRESET +# undef ECONNRESET +# endif +# define EPROTONOSUPPORT WSAEPROTONOSUPPORT +# define ECONNRESET WSAECONNRESET +# ifdef errno +# undef errno +# endif +# define errno WSAGetLastError() +# define h_errno WSAGetLastError() +# define set_errno(a) WSASetLastError(a) +# define close(a) closesocket(a) +# if _WIN32_WINNT >= 0x0600 && SOCKETS_ENABLE_VISTA_API +# define HAVE_IF_NAMETOINDEX 1 +# endif +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netdb.h> +# include <netinet/in.h> +# include <netinet/tcp.h> +# include <sys/un.h> +# include <arpa/inet.h> +# include <sys/time.h> +# include <unistd.h> +# include <errno.h> +# include <fcntl.h> +# include <signal.h> +# include <sys/uio.h> +# define IS_INVALID_SOCKET(a) (a->bsd_socket < 0) +# define set_errno(a) (errno = a) +# include "php_sockets.h" +# if defined(_AIX) && !defined(HAVE_SA_SS_FAMILY) +# define ss_family __ss_family +# endif +# if HAVE_IF_NAMETOINDEX +# include <net/if.h> +# endif +#endif + +#include "multicast.h" + +ZEND_DECLARE_MODULE_GLOBALS(sockets) +static PHP_GINIT_FUNCTION(sockets); + +#ifndef MSG_WAITALL +#ifdef LINUX +#define MSG_WAITALL 0x00000100 +#else +#define MSG_WAITALL 0x00000000 +#endif +#endif + +#ifndef MSG_EOF +#ifdef MSG_FIN +#define MSG_EOF MSG_FIN +#endif +#endif + +#ifndef SUN_LEN +#define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) +#endif + +#ifndef PF_INET +#define PF_INET AF_INET +#endif + +static char *php_strerror(int error TSRMLS_DC); + +#define PHP_SOCKET_ERROR(socket, msg, errn) \ + do { \ + int _err = (errn); /* save value to avoid repeated calls to WSAGetLastError() on Windows */ \ + (socket)->error = _err; \ + SOCKETS_G(last_error) = _err; \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s [%d]: %s", msg, _err, php_strerror(_err TSRMLS_CC)); \ + } while (0) + +#define PHP_NORMAL_READ 0x0001 +#define PHP_BINARY_READ 0x0002 + +static int le_socket; +#define le_socket_name php_sockets_le_socket_name + +/* {{{ arginfo */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_select, 0, 0, 4) + ZEND_ARG_INFO(1, read_fds) + ZEND_ARG_INFO(1, write_fds) + ZEND_ARG_INFO(1, except_fds) + ZEND_ARG_INFO(0, tv_sec) + ZEND_ARG_INFO(0, tv_usec) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_listen, 0, 0, 1) + ZEND_ARG_INFO(0, port) + ZEND_ARG_INFO(0, backlog) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_accept, 0, 0, 1) + ZEND_ARG_INFO(0, socket) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_nonblock, 0, 0, 1) + ZEND_ARG_INFO(0, socket) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_block, 0, 0, 1) + ZEND_ARG_INFO(0, socket) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_listen, 0, 0, 1) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, backlog) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_close, 0, 0, 1) + ZEND_ARG_INFO(0, socket) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_write, 0, 0, 2) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, buf) + ZEND_ARG_INFO(0, length) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_read, 0, 0, 2) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, length) + ZEND_ARG_INFO(0, type) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getsockname, 0, 0, 2) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(1, addr) + ZEND_ARG_INFO(1, port) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_getpeername, 0, 0, 2) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(1, addr) + ZEND_ARG_INFO(1, port) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create, 0, 0, 3) + ZEND_ARG_INFO(0, domain) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, protocol) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_connect, 0, 0, 2) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, addr) + ZEND_ARG_INFO(0, port) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_strerror, 0, 0, 1) + ZEND_ARG_INFO(0, errno) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_bind, 0, 0, 2) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, addr) + ZEND_ARG_INFO(0, port) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recv, 0, 0, 4) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(1, buf) + ZEND_ARG_INFO(0, len) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_send, 0, 0, 4) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, buf) + ZEND_ARG_INFO(0, len) + ZEND_ARG_INFO(0, flags) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvfrom, 0, 0, 5) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(1, buf) + ZEND_ARG_INFO(0, len) + ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(1, name) + ZEND_ARG_INFO(1, port) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendto, 0, 0, 5) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, buf) + ZEND_ARG_INFO(0, len) + ZEND_ARG_INFO(0, flags) + ZEND_ARG_INFO(0, addr) + ZEND_ARG_INFO(0, port) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_get_option, 0, 0, 3) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, level) + ZEND_ARG_INFO(0, optname) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_set_option, 0, 0, 4) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, level) + ZEND_ARG_INFO(0, optname) + ZEND_ARG_INFO(0, optval) +ZEND_END_ARG_INFO() + +#ifdef HAVE_SOCKETPAIR +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_pair, 0, 0, 4) + ZEND_ARG_INFO(0, domain) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, protocol) + ZEND_ARG_INFO(1, fd) +ZEND_END_ARG_INFO() +#endif + +#ifdef HAVE_SHUTDOWN +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_shutdown, 0, 0, 1) + ZEND_ARG_INFO(0, socket) + ZEND_ARG_INFO(0, how) +ZEND_END_ARG_INFO() +#endif + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_last_error, 0, 0, 0) + ZEND_ARG_INFO(0, socket) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_clear_error, 0, 0, 0) + ZEND_ARG_INFO(0, socket) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_import_stream, 0, 0, 1) + ZEND_ARG_INFO(0, stream) +ZEND_END_ARG_INFO() +/* }}} */ + +PHP_MINIT_FUNCTION(sockets); +PHP_MINFO_FUNCTION(sockets); +PHP_RSHUTDOWN_FUNCTION(sockets); + +PHP_FUNCTION(socket_select); +PHP_FUNCTION(socket_create_listen); +#ifdef HAVE_SOCKETPAIR +PHP_FUNCTION(socket_create_pair); +#endif +PHP_FUNCTION(socket_accept); +PHP_FUNCTION(socket_set_nonblock); +PHP_FUNCTION(socket_set_block); +PHP_FUNCTION(socket_listen); +PHP_FUNCTION(socket_close); +PHP_FUNCTION(socket_write); +PHP_FUNCTION(socket_read); +PHP_FUNCTION(socket_getsockname); +PHP_FUNCTION(socket_getpeername); +PHP_FUNCTION(socket_create); +PHP_FUNCTION(socket_connect); +PHP_FUNCTION(socket_strerror); +PHP_FUNCTION(socket_bind); +PHP_FUNCTION(socket_recv); +PHP_FUNCTION(socket_send); +PHP_FUNCTION(socket_recvfrom); +PHP_FUNCTION(socket_sendto); +PHP_FUNCTION(socket_get_option); +PHP_FUNCTION(socket_set_option); +#ifdef HAVE_SHUTDOWN +PHP_FUNCTION(socket_shutdown); +#endif +PHP_FUNCTION(socket_last_error); +PHP_FUNCTION(socket_clear_error); +PHP_FUNCTION(socket_import_stream); + +/* {{{ sockets_functions[] + */ +const zend_function_entry sockets_functions[] = { + PHP_FE(socket_select, arginfo_socket_select) + PHP_FE(socket_create, arginfo_socket_create) + PHP_FE(socket_create_listen, arginfo_socket_create_listen) +#ifdef HAVE_SOCKETPAIR + PHP_FE(socket_create_pair, arginfo_socket_create_pair) +#endif + PHP_FE(socket_accept, arginfo_socket_accept) + PHP_FE(socket_set_nonblock, arginfo_socket_set_nonblock) + PHP_FE(socket_set_block, arginfo_socket_set_block) + PHP_FE(socket_listen, arginfo_socket_listen) + PHP_FE(socket_close, arginfo_socket_close) + PHP_FE(socket_write, arginfo_socket_write) + PHP_FE(socket_read, arginfo_socket_read) + PHP_FE(socket_getsockname, arginfo_socket_getsockname) + PHP_FE(socket_getpeername, arginfo_socket_getpeername) + PHP_FE(socket_connect, arginfo_socket_connect) + PHP_FE(socket_strerror, arginfo_socket_strerror) + PHP_FE(socket_bind, arginfo_socket_bind) + PHP_FE(socket_recv, arginfo_socket_recv) + PHP_FE(socket_send, arginfo_socket_send) + PHP_FE(socket_recvfrom, arginfo_socket_recvfrom) + PHP_FE(socket_sendto, arginfo_socket_sendto) + PHP_FE(socket_get_option, arginfo_socket_get_option) + PHP_FE(socket_set_option, arginfo_socket_set_option) +#ifdef HAVE_SHUTDOWN + PHP_FE(socket_shutdown, arginfo_socket_shutdown) +#endif + PHP_FE(socket_last_error, arginfo_socket_last_error) + PHP_FE(socket_clear_error, arginfo_socket_clear_error) + PHP_FE(socket_import_stream, arginfo_socket_import_stream) + + /* for downwards compatability */ + PHP_FALIAS(socket_getopt, socket_get_option, arginfo_socket_get_option) + PHP_FALIAS(socket_setopt, socket_set_option, arginfo_socket_set_option) + + PHP_FE_END +}; +/* }}} */ + +zend_module_entry sockets_module_entry = { + STANDARD_MODULE_HEADER, + "sockets", + sockets_functions, + PHP_MINIT(sockets), + NULL, + NULL, + PHP_RSHUTDOWN(sockets), + PHP_MINFO(sockets), + NO_VERSION_YET, + PHP_MODULE_GLOBALS(sockets), + PHP_GINIT(sockets), + NULL, + NULL, + STANDARD_MODULE_PROPERTIES_EX +}; + + +#ifdef COMPILE_DL_SOCKETS +ZEND_GET_MODULE(sockets) +#endif + +/* inet_ntop should be used instead of inet_ntoa */ +int inet_ntoa_lock = 0; + +PHP_SOCKETS_API int php_sockets_le_socket(void) /* {{{ */ +{ + return le_socket; +} +/* }}} */ + +/* allocating function to make programming errors due to uninitialized fields + * less likely */ +static php_socket *php_create_socket(void) /* {{{ */ +{ + php_socket *php_sock = emalloc(sizeof *php_sock); + + php_sock->bsd_socket = -1; /* invalid socket */ + php_sock->type = PF_UNSPEC; + php_sock->error = 0; + php_sock->blocking = 1; + php_sock->zstream = NULL; + + return php_sock; +} +/* }}} */ + +static void php_destroy_socket(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ +{ + php_socket *php_sock = rsrc->ptr; + + if (php_sock->zstream == NULL) { + if (!IS_INVALID_SOCKET(php_sock)) { + close(php_sock->bsd_socket); + } + } else { + zval_ptr_dtor(&php_sock->zstream); + } + efree(php_sock); +} +/* }}} */ + +static int php_open_listen_sock(php_socket **php_sock, int port, int backlog TSRMLS_DC) /* {{{ */ +{ + struct sockaddr_in la; + struct hostent *hp; + php_socket *sock = php_create_socket(); + + *php_sock = sock; + +#ifndef PHP_WIN32 + if ((hp = gethostbyname("0.0.0.0")) == NULL) { +#else + if ((hp = gethostbyname("localhost")) == NULL) { +#endif + efree(sock); + return 0; + } + + memcpy((char *) &la.sin_addr, hp->h_addr, hp->h_length); + la.sin_family = hp->h_addrtype; + la.sin_port = htons((unsigned short) port); + + sock->bsd_socket = socket(PF_INET, SOCK_STREAM, 0); + sock->blocking = 1; + + if (IS_INVALID_SOCKET(sock)) { + PHP_SOCKET_ERROR(sock, "unable to create listening socket", errno); + efree(sock); + return 0; + } + + sock->type = PF_INET; + + if (bind(sock->bsd_socket, (struct sockaddr *)&la, sizeof(la)) != 0) { + PHP_SOCKET_ERROR(sock, "unable to bind to given address", errno); + close(sock->bsd_socket); + efree(sock); + return 0; + } + + if (listen(sock->bsd_socket, backlog) != 0) { + PHP_SOCKET_ERROR(sock, "unable to listen on socket", errno); + close(sock->bsd_socket); + efree(sock); + return 0; + } + + return 1; +} +/* }}} */ + +static int php_accept_connect(php_socket *in_sock, php_socket **new_sock, struct sockaddr *la, socklen_t *la_len TSRMLS_DC) /* {{{ */ +{ + php_socket *out_sock = php_create_socket(); + + *new_sock = out_sock; + + out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len); + + if (IS_INVALID_SOCKET(out_sock)) { + PHP_SOCKET_ERROR(out_sock, "unable to accept incoming connection", errno); + efree(out_sock); + return 0; + } + + out_sock->error = 0; + out_sock->blocking = 1; + out_sock->type = la->sa_family; + + return 1; +} +/* }}} */ + +/* {{{ php_read -- wrapper around read() so that it only reads to a \r or \n. */ +static int php_read(php_socket *sock, void *buf, size_t maxlen, int flags) +{ + int m = 0; + size_t n = 0; + int no_read = 0; + int nonblock = 0; + char *t = (char *) buf; + +#ifndef PHP_WIN32 + m = fcntl(sock->bsd_socket, F_GETFL); + if (m < 0) { + return m; + } + nonblock = (m & O_NONBLOCK); + m = 0; +#else + nonblock = !sock->blocking; +#endif + set_errno(0); + + *t = '\0'; + while (*t != '\n' && *t != '\r' && n < maxlen) { + if (m > 0) { + t++; + n++; + } else if (m == 0) { + no_read++; + if (nonblock && no_read >= 2) { + return n; + /* The first pass, m always is 0, so no_read becomes 1 + * in the first pass. no_read becomes 2 in the second pass, + * and if this is nonblocking, we should return.. */ + } + + if (no_read > 200) { + set_errno(ECONNRESET); + return -1; + } + } + + if (n < maxlen) { + m = recv(sock->bsd_socket, (void *) t, 1, flags); + } + + if (errno != 0 && errno != ESPIPE && errno != EAGAIN) { + return -1; + } + + set_errno(0); + } + + if (n < maxlen) { + n++; + /* The only reasons it makes it to here is + * if '\n' or '\r' are encountered. So, increase + * the return by 1 to make up for the lack of the + * '\n' or '\r' in the count (since read() takes + * place at the end of the loop..) */ + } + + return n; +} +/* }}} */ + +static char *php_strerror(int error TSRMLS_DC) /* {{{ */ +{ + const char *buf; + +#ifndef PHP_WIN32 + if (error < -10000) { + error = -error - 10000; + +#ifdef HAVE_HSTRERROR + buf = hstrerror(error); +#else + { + if (SOCKETS_G(strerror_buf)) { + efree(SOCKETS_G(strerror_buf)); + } + + spprintf(&(SOCKETS_G(strerror_buf)), 0, "Host lookup error %d", error); + buf = SOCKETS_G(strerror_buf); + } +#endif + } else { + buf = strerror(error); + } +#else + { + LPTSTR tmp = NULL; + buf = NULL; + + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &tmp, 0, NULL) + ) { + if (SOCKETS_G(strerror_buf)) { + efree(SOCKETS_G(strerror_buf)); + } + + SOCKETS_G(strerror_buf) = estrdup(tmp); + LocalFree(tmp); + + buf = SOCKETS_G(strerror_buf); + } + } +#endif + + return (buf ? (char *) buf : ""); +} +/* }}} */ + +#if HAVE_IPV6 +/* Sets addr by hostname, or by ip in string form (AF_INET6) */ +static int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */ +{ + struct in6_addr tmp; +#if HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo *addrinfo = NULL; +#endif + + if (inet_pton(AF_INET6, string, &tmp)) { + memcpy(&(sin6->sin6_addr.s6_addr), &(tmp.s6_addr), sizeof(struct in6_addr)); + } else { +#if HAVE_GETADDRINFO + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = PF_INET6; + getaddrinfo(string, NULL, &hints, &addrinfo); + if (!addrinfo) { +#ifdef PHP_WIN32 + PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError()); +#else + PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno)); +#endif + return 0; + } + if (addrinfo->ai_family != PF_INET6 || addrinfo->ai_addrlen != sizeof(struct sockaddr_in6)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: Non AF_INET6 domain returned on AF_INET6 socket"); + freeaddrinfo(addrinfo); + return 0; + } + + memcpy(&(sin6->sin6_addr.s6_addr), ((struct sockaddr_in6*)(addrinfo->ai_addr))->sin6_addr.s6_addr, sizeof(struct in6_addr)); + freeaddrinfo(addrinfo); + +#else + /* No IPv6 specific hostname resolution is available on this system? */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system"); + return 0; +#endif + + } + + return 1; +} +/* }}} */ +#endif + +/* Sets addr by hostname, or by ip in string form (AF_INET) */ +static int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */ +{ + struct in_addr tmp; + struct hostent *host_entry; + + if (inet_aton(string, &tmp)) { + sin->sin_addr.s_addr = tmp.s_addr; + } else { + if (! (host_entry = gethostbyname(string))) { + /* Note: < -10000 indicates a host lookup error */ +#ifdef PHP_WIN32 + PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError()); +#else + PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno)); +#endif + return 0; + } + if (host_entry->h_addrtype != AF_INET) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: Non AF_INET domain returned on AF_INET socket"); + return 0; + } + memcpy(&(sin->sin_addr.s_addr), host_entry->h_addr_list[0], host_entry->h_length); + } + + return 1; +} +/* }}} */ + +/* Sets addr by hostname or by ip in string form (AF_INET or AF_INET6, + * depending on the socket) */ +static int php_set_inet46_addr(php_sockaddr_storage *ss, socklen_t *ss_len, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */ +{ + if (php_sock->type == AF_INET) { + struct sockaddr_in t = {0}; + if (php_set_inet_addr(&t, string, php_sock TSRMLS_CC)) { + memcpy(ss, &t, sizeof t); + ss->ss_family = AF_INET; + *ss_len = sizeof(t); + return 1; + } + } +#if HAVE_IPV6 + else if (php_sock->type == AF_INET6) { + struct sockaddr_in6 t = {0}; + if (php_set_inet6_addr(&t, string, php_sock TSRMLS_CC)) { + memcpy(ss, &t, sizeof t); + ss->ss_family = AF_INET6; + *ss_len = sizeof(t); + return 1; + } + } +#endif + else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "IP address used in the context of an unexpected type of socket"); + } + return 0; +} + +static int php_get_if_index_from_zval(zval *val, unsigned *out TSRMLS_DC) +{ + int ret; + + if (Z_TYPE_P(val) == IS_LONG) { + if (Z_LVAL_P(val) < 0 || Z_LVAL_P(val) > UINT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "the interface index cannot be negative or larger than %u;" + " given %ld", UINT_MAX, Z_LVAL_P(val)); + ret = FAILURE; + } else { + *out = Z_LVAL_P(val); + ret = SUCCESS; + } + } else { +#if HAVE_IF_NAMETOINDEX + unsigned int ind; + zval_add_ref(&val); + convert_to_string_ex(&val); + ind = if_nametoindex(Z_STRVAL_P(val)); + if (ind == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "no interface with name \"%s\" could be found", Z_STRVAL_P(val)); + ret = FAILURE; + } else { + *out = ind; + ret = SUCCESS; + } + zval_ptr_dtor(&val); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "this platform does not support looking up an interface by " + "name, an integer interface index must be supplied instead"); + ret = FAILURE; +#endif + } + + return ret; +} + +static int php_get_if_index_from_array(const HashTable *ht, const char *key, + php_socket *sock, unsigned int *if_index TSRMLS_DC) +{ + zval **val; + + if (zend_hash_find(ht, key, strlen(key) + 1, (void **)&val) == FAILURE) { + *if_index = 0; /* default: 0 */ + return SUCCESS; + } + + return php_get_if_index_from_zval(*val, if_index TSRMLS_CC); +} + +static int php_get_address_from_array(const HashTable *ht, const char *key, + php_socket *sock, php_sockaddr_storage *ss, socklen_t *ss_len TSRMLS_DC) +{ + zval **val, + *valcp; + + if (zend_hash_find(ht, key, strlen(key) + 1, (void **)&val) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", key); + return FAILURE; + } + valcp = *val; + zval_add_ref(&valcp); + convert_to_string_ex(val); + if (!php_set_inet46_addr(ss, ss_len, Z_STRVAL_P(valcp), sock TSRMLS_CC)) { + zval_ptr_dtor(&valcp); + return FAILURE; + } + zval_ptr_dtor(&valcp); + return SUCCESS; +} + +/* {{{ PHP_GINIT_FUNCTION */ +static PHP_GINIT_FUNCTION(sockets) +{ + sockets_globals->last_error = 0; + sockets_globals->strerror_buf = NULL; +} +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(sockets) +{ + le_socket = zend_register_list_destructors_ex(php_destroy_socket, NULL, le_socket_name, module_number); + + REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT); +#if HAVE_IPV6 + REGISTER_LONG_CONSTANT("AF_INET6", AF_INET6, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_RAW", SOCK_RAW, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_SEQPACKET",SOCK_SEQPACKET, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_RDM", SOCK_RDM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_OOB", MSG_OOB, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL, CONST_CS | CONST_PERSISTENT); +#ifdef MSG_DONTWAIT + REGISTER_LONG_CONSTANT("MSG_DONTWAIT", MSG_DONTWAIT, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("MSG_PEEK", MSG_PEEK, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE, CONST_CS | CONST_PERSISTENT); +#ifdef MSG_EOR + REGISTER_LONG_CONSTANT("MSG_EOR", MSG_EOR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef MSG_EOF + REGISTER_LONG_CONSTANT("MSG_EOF", MSG_EOF, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("SO_DEBUG", SO_DEBUG, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_REUSEADDR", SO_REUSEADDR, CONST_CS | CONST_PERSISTENT); +#ifdef SO_REUSEPORT + REGISTER_LONG_CONSTANT("SO_REUSEPORT", SO_REUSEPORT, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("SO_KEEPALIVE", SO_KEEPALIVE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_DONTROUTE", SO_DONTROUTE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_LINGER", SO_LINGER, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_BROADCAST", SO_BROADCAST, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_OOBINLINE", SO_OOBINLINE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_SNDBUF", SO_SNDBUF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_RCVBUF", SO_RCVBUF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_SNDLOWAT", SO_SNDLOWAT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_RCVLOWAT", SO_RCVLOWAT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_SNDTIMEO", SO_SNDTIMEO, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_RCVTIMEO", SO_RCVTIMEO, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_TYPE", SO_TYPE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_ERROR", SO_ERROR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOL_SOCKET", SOL_SOCKET, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOMAXCONN", SOMAXCONN, CONST_CS | CONST_PERSISTENT); +#ifdef TCP_NODELAY + REGISTER_LONG_CONSTANT("TCP_NODELAY", TCP_NODELAY, CONST_CS | CONST_PERSISTENT); +#endif + REGISTER_LONG_CONSTANT("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT); + +#ifndef RFC3678_API +#define MCAST_JOIN_GROUP IP_ADD_MEMBERSHIP +#define MCAST_LEAVE_GROUP IP_DROP_MEMBERSHIP +#ifdef HAS_MCAST_EXT +#define MCAST_BLOCK_SOURCE IP_BLOCK_SOURCE +#define MCAST_UNBLOCK_SOURCE IP_UNBLOCK_SOURCE +#define MCAST_JOIN_SOURCE_GROUP IP_ADD_SOURCE_MEMBERSHIP +#define MCAST_LEAVE_SOURCE_GROUP IP_DROP_SOURCE_MEMBERSHIP +#endif +#endif + + REGISTER_LONG_CONSTANT("MCAST_JOIN_GROUP", MCAST_JOIN_GROUP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MCAST_LEAVE_GROUP", MCAST_LEAVE_GROUP, CONST_CS | CONST_PERSISTENT); +#ifdef HAS_MCAST_EXT + REGISTER_LONG_CONSTANT("MCAST_BLOCK_SOURCE", MCAST_BLOCK_SOURCE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MCAST_UNBLOCK_SOURCE", MCAST_UNBLOCK_SOURCE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MCAST_JOIN_SOURCE_GROUP", MCAST_JOIN_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MCAST_LEAVE_SOURCE_GROUP", MCAST_LEAVE_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT); +#endif + + REGISTER_LONG_CONSTANT("IP_MULTICAST_IF", IP_MULTICAST_IF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_MULTICAST_TTL", IP_MULTICAST_TTL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT); +#if HAVE_IPV6 + REGISTER_LONG_CONSTANT("IPV6_MULTICAST_IF", IPV6_MULTICAST_IF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IPV6_MULTICAST_HOPS", IPV6_MULTICAST_HOPS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IPV6_MULTICAST_LOOP", IPV6_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT); +#endif + +#ifndef WIN32 +# include "unix_socket_constants.h" +#else +# include "win32_socket_constants.h" +#endif + + REGISTER_LONG_CONSTANT("IPPROTO_IP", IPPROTO_IP, CONST_CS | CONST_PERSISTENT); +#if HAVE_IPV6 + REGISTER_LONG_CONSTANT("IPPROTO_IPV6", IPPROTO_IPV6, CONST_CS | CONST_PERSISTENT); +#endif + + REGISTER_LONG_CONSTANT("SOL_TCP", IPPROTO_TCP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOL_UDP", IPPROTO_UDP, CONST_CS | CONST_PERSISTENT); + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(sockets) +{ + php_info_print_table_start(); + php_info_print_table_row(2, "Sockets Support", "enabled"); + php_info_print_table_end(); +} +/* }}} */ + +/* {{{ PHP_RSHUTDOWN_FUNCTION */ +PHP_RSHUTDOWN_FUNCTION(sockets) +{ + if (SOCKETS_G(strerror_buf)) { + efree(SOCKETS_G(strerror_buf)); + SOCKETS_G(strerror_buf) = NULL; + } + + return SUCCESS; +} +/* }}} */ + +static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *max_fd TSRMLS_DC) /* {{{ */ +{ + zval **element; + php_socket *php_sock; + int num = 0; + + if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0; + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array)); + zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(sock_array))) { + + php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket); + if (!php_sock) continue; /* If element is not a resource, skip it */ + + PHP_SAFE_FD_SET(php_sock->bsd_socket, fds); + if (php_sock->bsd_socket > *max_fd) { + *max_fd = php_sock->bsd_socket; + } + num++; + } + + return num ? 1 : 0; +} +/* }}} */ + +static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds TSRMLS_DC) /* {{{ */ +{ + zval **element; + zval **dest_element; + php_socket *php_sock; + HashTable *new_hash; + char *key; + int num = 0; + ulong num_key; + uint key_len; + + if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0; + + ALLOC_HASHTABLE(new_hash); + zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(sock_array)), NULL, ZVAL_PTR_DTOR, 0); + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array)); + zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(sock_array))) { + + php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket); + if (!php_sock) continue; /* If element is not a resource, skip it */ + + if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) { + /* Add fd to new array */ + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(sock_array), &key, &key_len, &num_key, 0, NULL)) { + case HASH_KEY_IS_STRING: + zend_hash_add(new_hash, key, key_len, (void *)element, sizeof(zval *), (void **)&dest_element); + break; + case HASH_KEY_IS_LONG: + zend_hash_index_update(new_hash, num_key, (void *)element, sizeof(zval *), (void **)&dest_element); + break; + } + if (dest_element) zval_add_ref(dest_element); + } + num++; + } + + /* Destroy old array, add new one */ + zend_hash_destroy(Z_ARRVAL_P(sock_array)); + efree(Z_ARRVAL_P(sock_array)); + + zend_hash_internal_pointer_reset(new_hash); + Z_ARRVAL_P(sock_array) = new_hash; + + return num ? 1 : 0; +} +/* }}} */ + +/* {{{ proto int socket_select(array &read_fds, array &write_fds, array &except_fds, int tv_sec[, int tv_usec]) U + Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec */ +PHP_FUNCTION(socket_select) +{ + zval *r_array, *w_array, *e_array, *sec; + struct timeval tv; + struct timeval *tv_p = NULL; + fd_set rfds, wfds, efds; + PHP_SOCKET max_fd = 0; + int retval, sets = 0; + long usec = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE) { + return; + } + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + if (r_array != NULL) sets += php_sock_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC); + if (w_array != NULL) sets += php_sock_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC); + if (e_array != NULL) sets += php_sock_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC); + + if (!sets) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no resource arrays were passed to select"); + RETURN_FALSE; + } + + PHP_SAFE_MAX_FD(max_fd, 0); /* someone needs to make this look more like stream_socket_select */ + + /* If seconds is not set to null, build the timeval, else we wait indefinitely */ + if (sec != NULL) { + zval tmp; + + if (Z_TYPE_P(sec) != IS_LONG) { + tmp = *sec; + zval_copy_ctor(&tmp); + convert_to_long(&tmp); + sec = &tmp; + } + + /* Solaris + BSD do not like microsecond values which are >= 1 sec */ + if (usec > 999999) { + tv.tv_sec = Z_LVAL_P(sec) + (usec / 1000000); + tv.tv_usec = usec % 1000000; + } else { + tv.tv_sec = Z_LVAL_P(sec); + tv.tv_usec = usec; + } + + tv_p = &tv; + + if (sec == &tmp) { + zval_dtor(&tmp); + } + } + + retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p); + + if (retval == -1) { + SOCKETS_G(last_error) = errno; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s", errno, php_strerror(errno TSRMLS_CC)); + RETURN_FALSE; + } + + if (r_array != NULL) php_sock_array_from_fd_set(r_array, &rfds TSRMLS_CC); + if (w_array != NULL) php_sock_array_from_fd_set(w_array, &wfds TSRMLS_CC); + if (e_array != NULL) php_sock_array_from_fd_set(e_array, &efds TSRMLS_CC); + + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto resource socket_create_listen(int port[, int backlog]) U + Opens a socket on port to accept connections */ +PHP_FUNCTION(socket_create_listen) +{ + php_socket *php_sock; + long port, backlog = 128; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &port, &backlog) == FAILURE) { + return; + } + + if (!php_open_listen_sock(&php_sock, port, backlog TSRMLS_CC)) { + RETURN_FALSE; + } + + php_sock->error = 0; + php_sock->blocking = 1; + + ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket); +} +/* }}} */ + +/* {{{ proto resource socket_accept(resource socket) U + Accepts a connection on the listening socket fd */ +PHP_FUNCTION(socket_accept) +{ + zval *arg1; + php_socket *php_sock, *new_sock; + php_sockaddr_storage sa; + socklen_t php_sa_len = sizeof(sa); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr*)&sa, &php_sa_len TSRMLS_CC)) { + RETURN_FALSE; + } + + ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket); +} +/* }}} */ + +/* {{{ proto bool socket_set_nonblock(resource socket) U + Sets nonblocking mode on a socket resource */ +PHP_FUNCTION(socket_set_nonblock) +{ + zval *arg1; + php_socket *php_sock; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + if (php_sock->zstream != NULL) { + php_stream *stream; + /* omit notice if resource doesn't exist anymore */ + stream = zend_fetch_resource(&php_sock->zstream TSRMLS_CC, -1, + NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); + if (stream != NULL) { + if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 0, + NULL) != -1) { + php_sock->blocking = 0; + RETURN_TRUE; + } + } + } + + if (php_set_sock_blocking(php_sock->bsd_socket, 0 TSRMLS_CC) == SUCCESS) { + php_sock->blocking = 0; + RETURN_TRUE; + } else { + PHP_SOCKET_ERROR(php_sock, "unable to set nonblocking mode", errno); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool socket_set_block(resource socket) U + Sets blocking mode on a socket resource */ +PHP_FUNCTION(socket_set_block) +{ + zval *arg1; + php_socket *php_sock; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + /* if socket was created from a stream, give the stream a chance to take + * care of the operation itself, thereby allowing it to update its internal + * state */ + if (php_sock->zstream != NULL) { + php_stream *stream; + stream = zend_fetch_resource(&php_sock->zstream TSRMLS_CC, -1, + NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream()); + if (stream != NULL) { + if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 1, + NULL) != -1) { + php_sock->blocking = 1; + RETURN_TRUE; + } + } + } + + if (php_set_sock_blocking(php_sock->bsd_socket, 1 TSRMLS_CC) == SUCCESS) { + php_sock->blocking = 1; + RETURN_TRUE; + } else { + PHP_SOCKET_ERROR(php_sock, "unable to set blocking mode", errno); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool socket_listen(resource socket[, int backlog]) U + Sets the maximum number of connections allowed to be waited for on the socket specified by fd */ +PHP_FUNCTION(socket_listen) +{ + zval *arg1; + php_socket *php_sock; + long backlog = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &backlog) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + if (listen(php_sock->bsd_socket, backlog) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno); + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto void socket_close(resource socket) U + Closes a file descriptor */ +PHP_FUNCTION(socket_close) +{ + zval *arg1; + php_socket *php_sock; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + if (php_sock->zstream != NULL) { + php_stream *stream = NULL; + php_stream_from_zval_no_verify(stream, &php_sock->zstream); + if (stream != NULL) { + /* close & destroy stream, incl. removing it from the rsrc list; + * resource stored in php_sock->zstream will become invalid */ + php_stream_free(stream, PHP_STREAM_FREE_CLOSE | + (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0)); + } + } + zend_list_delete(Z_RESVAL_P(arg1)); +} +/* }}} */ + +/* {{{ proto int socket_write(resource socket, string buf[, int length]) + Writes the buffer to the socket resource, length is optional */ +PHP_FUNCTION(socket_write) +{ + zval *arg1; + php_socket *php_sock; + int retval, str_len; + long length = 0; + char *str; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &str, &str_len, &length) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + if (ZEND_NUM_ARGS() < 3) { + length = str_len; + } + +#ifndef PHP_WIN32 + retval = write(php_sock->bsd_socket, str, MIN(length, str_len)); +#else + retval = send(php_sock->bsd_socket, str, min(length, str_len), 0); +#endif + + if (retval < 0) { + PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno); + RETURN_FALSE; + } + + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto string socket_read(resource socket, int length [, int type]) U + Reads a maximum of length bytes from socket */ +PHP_FUNCTION(socket_read) +{ + zval *arg1; + php_socket *php_sock; + char *tmpbuf; + int retval; + long length, type = PHP_BINARY_READ; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &arg1, &length, &type) == FAILURE) { + return; + } + + /* overflow check */ + if ((length + 1) < 2) { + RETURN_FALSE; + } + + tmpbuf = emalloc(length + 1); + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + if (type == PHP_NORMAL_READ) { + retval = php_read(php_sock, tmpbuf, length, 0); + } else { + retval = recv(php_sock->bsd_socket, tmpbuf, length, 0); + } + + if (retval == -1) { + /* if the socket is in non-blocking mode and there's no data to read, + don't output any error, as this is a normal situation, and not an error */ + if (errno == EAGAIN +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif + ) { + php_sock->error = errno; + SOCKETS_G(last_error) = errno; + } else { + PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno); + } + + efree(tmpbuf); + RETURN_FALSE; + } else if (!retval) { + efree(tmpbuf); + RETURN_EMPTY_STRING(); + } + + tmpbuf = erealloc(tmpbuf, retval + 1); + tmpbuf[retval] = '\0' ; + + RETURN_STRINGL(tmpbuf, retval, 0); +} +/* }}} */ + +/* {{{ proto bool socket_getsockname(resource socket, string &addr[, int &port]) + 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. */ +PHP_FUNCTION(socket_getsockname) +{ + zval *arg1, *addr, *port = NULL; + php_sockaddr_storage sa_storage; + php_socket *php_sock; + struct sockaddr *sa; + struct sockaddr_in *sin; +#if HAVE_IPV6 + struct sockaddr_in6 *sin6; + char addr6[INET6_ADDRSTRLEN+1]; +#endif + struct sockaddr_un *s_un; + char *addr_string; + socklen_t salen = sizeof(php_sockaddr_storage); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &addr, &port) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + sa = (struct sockaddr *) &sa_storage; + + if (getsockname(php_sock->bsd_socket, sa, &salen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket name", errno); + RETURN_FALSE; + } + + switch (sa->sa_family) { +#if HAVE_IPV6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN); + zval_dtor(addr); + ZVAL_STRING(addr, addr6, 1); + + if (port != NULL) { + zval_dtor(port); + ZVAL_LONG(port, htons(sin6->sin6_port)); + } + RETURN_TRUE; + break; +#endif + case AF_INET: + sin = (struct sockaddr_in *) sa; + while (inet_ntoa_lock == 1); + inet_ntoa_lock = 1; + addr_string = inet_ntoa(sin->sin_addr); + inet_ntoa_lock = 0; + + zval_dtor(addr); + ZVAL_STRING(addr, addr_string, 1); + + if (port != NULL) { + zval_dtor(port); + ZVAL_LONG(port, htons(sin->sin_port)); + } + RETURN_TRUE; + break; + + case AF_UNIX: + s_un = (struct sockaddr_un *) sa; + + zval_dtor(addr); + ZVAL_STRING(addr, s_un->sun_path, 1); + RETURN_TRUE; + break; + + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported address family %d", sa->sa_family); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool socket_getpeername(resource socket, string &addr[, int &port]) + 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. */ +PHP_FUNCTION(socket_getpeername) +{ + zval *arg1, *arg2, *arg3 = NULL; + php_sockaddr_storage sa_storage; + php_socket *php_sock; + struct sockaddr *sa; + struct sockaddr_in *sin; +#if HAVE_IPV6 + struct sockaddr_in6 *sin6; + char addr6[INET6_ADDRSTRLEN+1]; +#endif + struct sockaddr_un *s_un; + char *addr_string; + socklen_t salen = sizeof(php_sockaddr_storage); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &arg2, &arg3) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + sa = (struct sockaddr *) &sa_storage; + + if (getpeername(php_sock->bsd_socket, sa, &salen) < 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve peer name", errno); + RETURN_FALSE; + } + + switch (sa->sa_family) { +#if HAVE_IPV6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN); + zval_dtor(arg2); + ZVAL_STRING(arg2, addr6, 1); + + if (arg3 != NULL) { + zval_dtor(arg3); + ZVAL_LONG(arg3, htons(sin6->sin6_port)); + } + + RETURN_TRUE; + break; +#endif + case AF_INET: + sin = (struct sockaddr_in *) sa; + while (inet_ntoa_lock == 1); + inet_ntoa_lock = 1; + addr_string = inet_ntoa(sin->sin_addr); + inet_ntoa_lock = 0; + + zval_dtor(arg2); + ZVAL_STRING(arg2, addr_string, 1); + + if (arg3 != NULL) { + zval_dtor(arg3); + ZVAL_LONG(arg3, htons(sin->sin_port)); + } + + RETURN_TRUE; + break; + + case AF_UNIX: + s_un = (struct sockaddr_un *) sa; + + zval_dtor(arg2); + ZVAL_STRING(arg2, s_un->sun_path, 1); + RETURN_TRUE; + break; + + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported address family %d", sa->sa_family); + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto resource socket_create(int domain, int type, int protocol) U + Creates an endpoint for communication in the domain specified by domain, of type specified by type */ +PHP_FUNCTION(socket_create) +{ + long arg1, arg2, arg3; + php_socket *php_sock = php_create_socket(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) { + efree(php_sock); + return; + } + + if (arg1 != AF_UNIX +#if HAVE_IPV6 + && arg1 != AF_INET6 +#endif + && arg1 != AF_INET) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1); + arg1 = AF_INET; + } + + if (arg2 > 10) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2); + arg2 = SOCK_STREAM; + } + + php_sock->bsd_socket = socket(arg1, arg2, arg3); + php_sock->type = arg1; + + if (IS_INVALID_SOCKET(php_sock)) { + SOCKETS_G(last_error) = errno; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, php_strerror(errno TSRMLS_CC)); + efree(php_sock); + RETURN_FALSE; + } + + php_sock->error = 0; + php_sock->blocking = 1; + + ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket); +} +/* }}} */ + +/* {{{ proto bool socket_connect(resource socket, string addr [, int port]) + Opens a connection to addr:port on the socket specified by socket */ +PHP_FUNCTION(socket_connect) +{ + zval *arg1; + php_socket *php_sock; + char *addr; + int retval, addr_len; + long port = 0; + int argc = ZEND_NUM_ARGS(); + + if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + switch(php_sock->type) { +#if HAVE_IPV6 + case AF_INET6: { + struct sockaddr_in6 sin6 = {0}; + + if (argc != 3) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET6 requires 3 arguments"); + RETURN_FALSE; + } + + memset(&sin6, 0, sizeof(struct sockaddr_in6)); + + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons((unsigned short int)port); + + if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) { + RETURN_FALSE; + } + + retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin6, sizeof(struct sockaddr_in6)); + break; + } +#endif + case AF_INET: { + struct sockaddr_in sin = {0}; + + if (argc != 3) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET requires 3 arguments"); + RETURN_FALSE; + } + + sin.sin_family = AF_INET; + sin.sin_port = htons((unsigned short int)port); + + if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) { + RETURN_FALSE; + } + + retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)); + break; + } + + case AF_UNIX: { + struct sockaddr_un s_un = {0}; + + if (addr_len >= sizeof(s_un.sun_path)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Path too long"); + RETURN_FALSE; + } + + s_un.sun_family = AF_UNIX; + memcpy(&s_un.sun_path, addr, addr_len); + retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un, + (socklen_t)(XtOffsetOf(struct sockaddr_un, sun_path) + addr_len)); + break; + } + + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type); + RETURN_FALSE; + } + + if (retval != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to connect", errno); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string socket_strerror(int errno) + Returns a string describing an error */ +PHP_FUNCTION(socket_strerror) +{ + long arg1; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &arg1) == FAILURE) { + return; + } + + RETURN_STRING(php_strerror(arg1 TSRMLS_CC), 1); +} +/* }}} */ + +/* {{{ proto bool socket_bind(resource socket, string addr [, int port]) + Binds an open socket to a listening port, port is only specified in AF_INET family. */ +PHP_FUNCTION(socket_bind) +{ + zval *arg1; + php_sockaddr_storage sa_storage; + struct sockaddr *sock_type = (struct sockaddr*) &sa_storage; + php_socket *php_sock; + char *addr; + int addr_len; + long port = 0; + long retval = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + switch(php_sock->type) { + case AF_UNIX: + { + struct sockaddr_un *sa = (struct sockaddr_un *) sock_type; + memset(sa, 0, sizeof(sa_storage)); + sa->sun_family = AF_UNIX; + snprintf(sa->sun_path, 108, "%s", addr); + retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, SUN_LEN(sa)); + break; + } + + case AF_INET: + { + struct sockaddr_in *sa = (struct sockaddr_in *) sock_type; + + memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */ + + sa->sin_family = AF_INET; + sa->sin_port = htons((unsigned short) port); + + if (! php_set_inet_addr(sa, addr, php_sock TSRMLS_CC)) { + RETURN_FALSE; + } + + retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in)); + break; + } +#if HAVE_IPV6 + case AF_INET6: + { + struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type; + + memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */ + + sa->sin6_family = AF_INET6; + sa->sin6_port = htons((unsigned short) port); + + if (! php_set_inet6_addr(sa, addr, php_sock TSRMLS_CC)) { + RETURN_FALSE; + } + + retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in6)); + break; + } +#endif + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported socket type '%d', must be AF_UNIX, AF_INET, or AF_INET6", php_sock->type); + RETURN_FALSE; + } + + if (retval != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to bind address", errno); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int socket_recv(resource socket, string &buf, int len, int flags) + Receives data from a connected socket */ +PHP_FUNCTION(socket_recv) +{ + zval *php_sock_res, *buf; + char *recv_buf; + php_socket *php_sock; + int retval; + long len, flags; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &php_sock_res, -1, le_socket_name, le_socket); + + /* overflow check */ + if ((len + 1) < 2) { + RETURN_FALSE; + } + + recv_buf = emalloc(len + 1); + memset(recv_buf, 0, len + 1); + + if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) { + efree(recv_buf); + + zval_dtor(buf); + Z_TYPE_P(buf) = IS_NULL; + } else { + recv_buf[retval] = '\0'; + + /* Rebuild buffer zval */ + zval_dtor(buf); + + Z_STRVAL_P(buf) = recv_buf; + Z_STRLEN_P(buf) = retval; + Z_TYPE_P(buf) = IS_STRING; + } + + if (retval == -1) { + PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno); + RETURN_FALSE; + } + + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto int socket_send(resource socket, string buf, int len, int flags) + Sends data to a connected socket */ +PHP_FUNCTION(socket_send) +{ + zval *arg1; + php_socket *php_sock; + int buf_len, retval; + long len, flags; + char *buf; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsll", &arg1, &buf, &buf_len, &len, &flags) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + retval = send(php_sock->bsd_socket, buf, (buf_len < len ? buf_len : len), flags); + + if (retval == -1) { + PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno); + RETURN_FALSE; + } + + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto int socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port]) + Receives data from a socket, connected or not */ +PHP_FUNCTION(socket_recvfrom) +{ + zval *arg1, *arg2, *arg5, *arg6 = NULL; + php_socket *php_sock; + struct sockaddr_un s_un; + struct sockaddr_in sin; +#if HAVE_IPV6 + struct sockaddr_in6 sin6; + char addr6[INET6_ADDRSTRLEN]; +#endif + socklen_t slen; + int retval; + long arg3, arg4; + char *recv_buf, *address; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + /* overflow check */ + if ((arg3 + 2) < 3) { + RETURN_FALSE; + } + + recv_buf = emalloc(arg3 + 2); + memset(recv_buf, 0, arg3 + 2); + + switch (php_sock->type) { + case AF_UNIX: + slen = sizeof(s_un); + s_un.sun_family = AF_UNIX; + retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&s_un, (socklen_t *)&slen); + + if (retval < 0) { + efree(recv_buf); + PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno); + RETURN_FALSE; + } + + zval_dtor(arg2); + zval_dtor(arg5); + + ZVAL_STRINGL(arg2, recv_buf, retval, 0); + ZVAL_STRING(arg5, s_un.sun_path, 1); + break; + + case AF_INET: + slen = sizeof(sin); + memset(&sin, 0, slen); + sin.sin_family = AF_INET; + + if (arg6 == NULL) { + efree(recv_buf); + WRONG_PARAM_COUNT; + } + + retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin, (socklen_t *)&slen); + + if (retval < 0) { + efree(recv_buf); + PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno); + RETURN_FALSE; + } + + zval_dtor(arg2); + zval_dtor(arg5); + zval_dtor(arg6); + + address = inet_ntoa(sin.sin_addr); + + ZVAL_STRINGL(arg2, recv_buf, retval, 0); + ZVAL_STRING(arg5, address ? address : "0.0.0.0", 1); + ZVAL_LONG(arg6, ntohs(sin.sin_port)); + break; +#if HAVE_IPV6 + case AF_INET6: + slen = sizeof(sin6); + memset(&sin6, 0, slen); + sin6.sin6_family = AF_INET6; + + if (arg6 == NULL) { + efree(recv_buf); + WRONG_PARAM_COUNT; + } + + retval = recvfrom(php_sock->bsd_socket, recv_buf, arg3, arg4, (struct sockaddr *)&sin6, (socklen_t *)&slen); + + if (retval < 0) { + efree(recv_buf); + PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno); + RETURN_FALSE; + } + + zval_dtor(arg2); + zval_dtor(arg5); + zval_dtor(arg6); + + memset(addr6, 0, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &sin6.sin6_addr, addr6, INET6_ADDRSTRLEN); + + ZVAL_STRINGL(arg2, recv_buf, retval, 0); + ZVAL_STRING(arg5, addr6[0] ? addr6 : "::", 1); + ZVAL_LONG(arg6, ntohs(sin6.sin6_port)); + break; +#endif + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type); + RETURN_FALSE; + } + + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto int socket_sendto(resource socket, string buf, int len, int flags, string addr [, int port]) + Sends a message to a socket, whether it is connected or not */ +PHP_FUNCTION(socket_sendto) +{ + zval *arg1; + php_socket *php_sock; + struct sockaddr_un s_un; + struct sockaddr_in sin; +#if HAVE_IPV6 + struct sockaddr_in6 sin6; +#endif + int retval, buf_len, addr_len; + long len, flags, port = 0; + char *buf, *addr; + int argc = ZEND_NUM_ARGS(); + + if (zend_parse_parameters(argc TSRMLS_CC, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + switch (php_sock->type) { + case AF_UNIX: + memset(&s_un, 0, sizeof(s_un)); + s_un.sun_family = AF_UNIX; + snprintf(s_un.sun_path, 108, "%s", addr); + + retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &s_un, SUN_LEN(&s_un)); + break; + + case AF_INET: + if (argc != 6) { + WRONG_PARAM_COUNT; + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons((unsigned short) port); + + if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) { + RETURN_FALSE; + } + + retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin, sizeof(sin)); + break; +#if HAVE_IPV6 + case AF_INET6: + if (argc != 6) { + WRONG_PARAM_COUNT; + } + + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons((unsigned short) port); + + if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) { + RETURN_FALSE; + } + + retval = sendto(php_sock->bsd_socket, buf, (len > buf_len) ? buf_len : len, flags, (struct sockaddr *) &sin6, sizeof(sin6)); + break; +#endif + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type); + RETURN_FALSE; + } + + if (retval == -1) { + PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno); + RETURN_FALSE; + } + + RETURN_LONG(retval); +} +/* }}} */ + +/* {{{ proto mixed socket_get_option(resource socket, int level, int optname) U + Gets socket options for the socket */ +PHP_FUNCTION(socket_get_option) +{ + zval *arg1; + struct linger linger_val; + struct timeval tv; +#ifdef PHP_WIN32 + int timeout = 0; +#endif + socklen_t optlen; + php_socket *php_sock; + int other_val; + long level, optname; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &arg1, &level, &optname) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + if (level == IPPROTO_IP) { + switch (optname) { + case IP_MULTICAST_IF: { + struct in_addr if_addr; + unsigned int if_index; + optlen = sizeof(if_addr); + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&if_addr, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } + if (php_add4_to_if_index(&if_addr, php_sock, &if_index TSRMLS_CC) == SUCCESS) { + RETURN_LONG((long) if_index); + } else { + RETURN_FALSE; + } + } + } + } + + /* sol_socket options and general case */ + switch(optname) { + case SO_LINGER: + optlen = sizeof(linger_val); + + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&linger_val, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } + + array_init(return_value); + add_assoc_long(return_value, "l_onoff", linger_val.l_onoff); + add_assoc_long(return_value, "l_linger", linger_val.l_linger); + break; + + case SO_RCVTIMEO: + case SO_SNDTIMEO: +#ifndef PHP_WIN32 + optlen = sizeof(tv); + + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&tv, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } +#else + optlen = sizeof(int); + + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&timeout, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } + + tv.tv_sec = timeout ? timeout / 1000 : 0; + tv.tv_usec = timeout ? (timeout * 1000) % 1000000 : 0; +#endif + + array_init(return_value); + + add_assoc_long(return_value, "sec", tv.tv_sec); + add_assoc_long(return_value, "usec", tv.tv_usec); + break; + + default: + optlen = sizeof(other_val); + + if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&other_val, &optlen) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno); + RETURN_FALSE; + } + if (optlen == 1) + other_val = *((unsigned char *)&other_val); + + RETURN_LONG(other_val); + break; + } +} +/* }}} */ + +static int php_do_mcast_opt(php_socket *php_sock, int level, int optname, zval **arg4 TSRMLS_DC) +{ + HashTable *opt_ht; + unsigned int if_index; + int retval; + int (*mcast_req_fun)(php_socket *, int, struct sockaddr *, socklen_t, + unsigned TSRMLS_DC); +#ifdef HAS_MCAST_EXT + int (*mcast_sreq_fun)(php_socket *, int, struct sockaddr *, socklen_t, + struct sockaddr *, socklen_t, unsigned TSRMLS_DC); +#endif + + switch (optname) { + case MCAST_JOIN_GROUP: + mcast_req_fun = &php_mcast_join; + goto mcast_req_fun; + case MCAST_LEAVE_GROUP: + { + php_sockaddr_storage group = {0}; + socklen_t glen; + + mcast_req_fun = &php_mcast_leave; +mcast_req_fun: + convert_to_array_ex(arg4); + opt_ht = HASH_OF(*arg4); + + if (php_get_address_from_array(opt_ht, "group", php_sock, &group, + &glen TSRMLS_CC) == FAILURE) { + return FAILURE; + } + if (php_get_if_index_from_array(opt_ht, "interface", php_sock, + &if_index TSRMLS_CC) == FAILURE) { + return FAILURE; + } + + retval = mcast_req_fun(php_sock, level, (struct sockaddr*)&group, + glen, if_index TSRMLS_CC); + break; + } + +#ifdef HAS_MCAST_EXT + case MCAST_BLOCK_SOURCE: + mcast_sreq_fun = &php_mcast_block_source; + goto mcast_sreq_fun; + case MCAST_UNBLOCK_SOURCE: + mcast_sreq_fun = &php_mcast_unblock_source; + goto mcast_sreq_fun; + case MCAST_JOIN_SOURCE_GROUP: + mcast_sreq_fun = &php_mcast_join_source; + goto mcast_sreq_fun; + case MCAST_LEAVE_SOURCE_GROUP: + { + php_sockaddr_storage group = {0}, + source = {0}; + socklen_t glen, + slen; + + mcast_sreq_fun = &php_mcast_leave_source; + mcast_sreq_fun: + convert_to_array_ex(arg4); + opt_ht = HASH_OF(*arg4); + + if (php_get_address_from_array(opt_ht, "group", php_sock, &group, + &glen TSRMLS_CC) == FAILURE) { + return FAILURE; + } + if (php_get_address_from_array(opt_ht, "source", php_sock, &source, + &slen TSRMLS_CC) == FAILURE) { + return FAILURE; + } + if (php_get_if_index_from_array(opt_ht, "interface", php_sock, + &if_index TSRMLS_CC) == FAILURE) { + return FAILURE; + } + + retval = mcast_sreq_fun(php_sock, level, (struct sockaddr*)&group, + glen, (struct sockaddr*)&source, slen, if_index TSRMLS_CC); + break; + } +#endif + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "unexpected option in php_do_mcast_opt (level %d, option %d). " + "This is a bug.", level, optname); + return FAILURE; + } + + if (retval != 0) { + if (retval != -2) { /* error, but message already emitted */ + PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno); + } + return FAILURE; + } + return SUCCESS; +} + +/* {{{ proto bool socket_set_option(resource socket, int level, int optname, int|array optval) + Sets socket options for the socket */ +PHP_FUNCTION(socket_set_option) +{ + zval *arg1, **arg4; + struct linger lv; + php_socket *php_sock; + int ov, optlen, retval; +#ifdef PHP_WIN32 + int timeout; +#else + struct timeval tv; +#endif + long level, optname; + void *opt_ptr; + HashTable *opt_ht; + zval **l_onoff, **l_linger; + zval **sec, **usec; + + /* Multicast */ + unsigned int if_index; + struct in_addr if_addr; + unsigned char ipv4_mcast_ttl_lback; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllZ", &arg1, &level, &optname, &arg4) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket); + + set_errno(0); + + if (level == IPPROTO_IP) { + switch (optname) { + case MCAST_JOIN_GROUP: + case MCAST_LEAVE_GROUP: +#ifdef HAS_MCAST_EXT + case MCAST_BLOCK_SOURCE: + case MCAST_UNBLOCK_SOURCE: + case MCAST_JOIN_SOURCE_GROUP: + case MCAST_LEAVE_SOURCE_GROUP: +#endif + if (php_do_mcast_opt(php_sock, level, optname, arg4 TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } + + case IP_MULTICAST_IF: + if (php_get_if_index_from_zval(*arg4, &if_index TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } + + if (php_if_index_to_addr4(if_index, php_sock, &if_addr TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } + opt_ptr = &if_addr; + optlen = sizeof(if_addr); + goto dosockopt; + + case IP_MULTICAST_LOOP: + convert_to_boolean_ex(arg4); + goto ipv4_loop_ttl; + case IP_MULTICAST_TTL: + convert_to_long_ex(arg4); + if (Z_LVAL_PP(arg4) < 0L || Z_LVAL_PP(arg4) > 255L) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Expected a value between 0 and 255"); + RETURN_FALSE; + } +ipv4_loop_ttl: + ipv4_mcast_ttl_lback = (unsigned char) Z_LVAL_PP(arg4); + opt_ptr = &ipv4_mcast_ttl_lback; + optlen = sizeof(ipv4_mcast_ttl_lback); + goto dosockopt; + } + } + +#if HAVE_IPV6 + else if (level == IPPROTO_IPV6) { + switch (optname) { + case MCAST_JOIN_GROUP: + case MCAST_LEAVE_GROUP: +#ifdef HAS_MCAST_EXT + case MCAST_BLOCK_SOURCE: + case MCAST_UNBLOCK_SOURCE: + case MCAST_JOIN_SOURCE_GROUP: + case MCAST_LEAVE_SOURCE_GROUP: +#endif + if (php_do_mcast_opt(php_sock, level, optname, arg4 TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } + + case IPV6_MULTICAST_IF: + if (php_get_if_index_from_zval(*arg4, &if_index TSRMLS_CC) == FAILURE) { + RETURN_FALSE; + } + + opt_ptr = &if_index; + optlen = sizeof(if_index); + goto dosockopt; + + case IPV6_MULTICAST_LOOP: + convert_to_boolean_ex(arg4); + goto ipv6_loop_hops; + case IPV6_MULTICAST_HOPS: + convert_to_long_ex(arg4); + if (Z_LVAL_PP(arg4) < -1L || Z_LVAL_PP(arg4) > 255L) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Expected a value between -1 and 255"); + RETURN_FALSE; + } +ipv6_loop_hops: + ov = (int) Z_LVAL_PP(arg4); + opt_ptr = &ov; + optlen = sizeof(ov); + goto dosockopt; + } + } +#endif + + switch (optname) { + case SO_LINGER: { + const char l_onoff_key[] = "l_onoff"; + const char l_linger_key[] = "l_linger"; + + convert_to_array_ex(arg4); + opt_ht = HASH_OF(*arg4); + + if (zend_hash_find(opt_ht, l_onoff_key, sizeof(l_onoff_key), (void **)&l_onoff) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_onoff_key); + RETURN_FALSE; + } + if (zend_hash_find(opt_ht, l_linger_key, sizeof(l_linger_key), (void **)&l_linger) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_linger_key); + RETURN_FALSE; + } + + convert_to_long_ex(l_onoff); + convert_to_long_ex(l_linger); + + lv.l_onoff = (unsigned short)Z_LVAL_PP(l_onoff); + lv.l_linger = (unsigned short)Z_LVAL_PP(l_linger); + + optlen = sizeof(lv); + opt_ptr = &lv; + break; + } + + case SO_RCVTIMEO: + case SO_SNDTIMEO: { + const char sec_key[] = "sec"; + const char usec_key[] = "usec"; + + convert_to_array_ex(arg4); + opt_ht = HASH_OF(*arg4); + + if (zend_hash_find(opt_ht, sec_key, sizeof(sec_key), (void **)&sec) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", sec_key); + RETURN_FALSE; + } + if (zend_hash_find(opt_ht, usec_key, sizeof(usec_key), (void **)&usec) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", usec_key); + RETURN_FALSE; + } + + convert_to_long_ex(sec); + convert_to_long_ex(usec); +#ifndef PHP_WIN32 + tv.tv_sec = Z_LVAL_PP(sec); + tv.tv_usec = Z_LVAL_PP(usec); + optlen = sizeof(tv); + opt_ptr = &tv; +#else + timeout = Z_LVAL_PP(sec) * 1000 + Z_LVAL_PP(usec) / 1000; + optlen = sizeof(int); + opt_ptr = &timeout; +#endif + break; + } + + default: + convert_to_long_ex(arg4); + ov = Z_LVAL_PP(arg4); + + optlen = sizeof(ov); + opt_ptr = &ov; + break; + } + +dosockopt: + retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen); + if (retval != 0) { + if (retval != -2) { /* error, but message already emitted */ + PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno); + } + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +#ifdef HAVE_SOCKETPAIR +/* {{{ proto bool socket_create_pair(int domain, int type, int protocol, array &fd) U + Creates a pair of indistinguishable sockets and stores them in fds. */ +PHP_FUNCTION(socket_create_pair) +{ + zval *retval[2], *fds_array_zval; + php_socket *php_sock[2]; + PHP_SOCKET fds_array[2]; + long domain, type, protocol; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lllz", &domain, &type, &protocol, &fds_array_zval) == FAILURE) { + return; + } + + php_sock[0] = php_create_socket(); + php_sock[1] = php_create_socket(); + + if (domain != AF_INET +#if HAVE_IPV6 + && domain != AF_INET6 +#endif + && domain != AF_UNIX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", domain); + domain = AF_INET; + } + + if (type > 10) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", type); + type = SOCK_STREAM; + } + + if (socketpair(domain, type, protocol, fds_array) != 0) { + SOCKETS_G(last_error) = errno; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to create socket pair [%d]: %s", errno, php_strerror(errno TSRMLS_CC)); + efree(php_sock[0]); + efree(php_sock[1]); + RETURN_FALSE; + } + + zval_dtor(fds_array_zval); + array_init(fds_array_zval); + + MAKE_STD_ZVAL(retval[0]); + MAKE_STD_ZVAL(retval[1]); + + php_sock[0]->bsd_socket = fds_array[0]; + php_sock[1]->bsd_socket = fds_array[1]; + php_sock[0]->type = domain; + php_sock[1]->type = domain; + php_sock[0]->error = 0; + php_sock[1]->error = 0; + php_sock[0]->blocking = 1; + php_sock[1]->blocking = 1; + + ZEND_REGISTER_RESOURCE(retval[0], php_sock[0], le_socket); + ZEND_REGISTER_RESOURCE(retval[1], php_sock[1], le_socket); + + add_index_zval(fds_array_zval, 0, retval[0]); + add_index_zval(fds_array_zval, 1, retval[1]); + + RETURN_TRUE; +} +/* }}} */ +#endif + +#ifdef HAVE_SHUTDOWN +/* {{{ proto bool socket_shutdown(resource socket[, int how]) U + Shuts down a socket for receiving, sending, or both. */ +PHP_FUNCTION(socket_shutdown) +{ + zval *arg1; + long how_shutdown = 2; + php_socket *php_sock; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &how_shutdown) == FAILURE) { + return; + } + + ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket); + + if (shutdown(php_sock->bsd_socket, how_shutdown) != 0) { + PHP_SOCKET_ERROR(php_sock, "unable to shutdown socket", errno); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ +#endif + +/* {{{ proto int socket_last_error([resource socket]) U + Returns the last socket error (either the last used or the provided socket resource) */ +PHP_FUNCTION(socket_last_error) +{ + zval *arg1 = NULL; + php_socket *php_sock; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg1) == FAILURE) { + return; + } + + if (arg1) { + ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket); + RETVAL_LONG(php_sock->error); + } else { + RETVAL_LONG(SOCKETS_G(last_error)); + } +} +/* }}} */ + +/* {{{ proto void socket_clear_error([resource socket]) U + Clears the error on the socket or the last error code. */ +PHP_FUNCTION(socket_clear_error) +{ + zval *arg1 = NULL; + php_socket *php_sock; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg1) == FAILURE) { + return; + } + + if (arg1) { + ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg1, -1, le_socket_name, le_socket); + php_sock->error = 0; + } else { + SOCKETS_G(last_error) = 0; + } + + return; +} +/* }}} */ + +/* {{{ proto void socket_import_stream(resource stream) + Imports a stream that encapsulates a socket into a socket extension resource. */ +PHP_FUNCTION(socket_import_stream) +{ + zval *zstream; + php_stream *stream; + php_socket *retsock = NULL; + PHP_SOCKET socket; /* fd */ + php_sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); +#ifndef PHP_WIN32 + int t; +#endif + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) == FAILURE) { + return; + } + php_stream_from_zval(stream, &zstream); + + if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void**)&socket, 1)) { + /* error supposedly already shown */ + RETURN_FALSE; + } + + retsock = php_create_socket(); + + retsock->bsd_socket = socket; + + /* determine family */ + if (getsockname(socket, (struct sockaddr*)&addr, &addr_len) == 0) { + retsock->type = addr.ss_family; + } else { + PHP_SOCKET_ERROR(retsock, "unable to obtain socket family", errno); + goto error; + } + + /* determine blocking mode */ +#ifndef PHP_WIN32 + t = fcntl(socket, F_GETFL); + if(t == -1) { + PHP_SOCKET_ERROR(retsock, "unable to obtain blocking state", errno); + goto error; + } else { + retsock->blocking = !(t & O_NONBLOCK); + } +#else + /* on windows, check if the stream is a socket stream and read its + * private data; otherwise assume it's in non-blocking mode */ + if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) { + retsock->blocking = + ((php_netstream_data_t *)stream->abstract)->is_blocked; + } else { + retsock->blocking = 1; + } +#endif + + /* hold a zval reference to the stream (holding a php_stream* directly could + * also be done, but this might be slightly better if in the future we want + * to provide a socket_export_stream) */ + MAKE_STD_ZVAL(retsock->zstream); + *retsock->zstream = *zstream; + zval_copy_ctor(retsock->zstream); + Z_UNSET_ISREF_P(retsock->zstream); + Z_SET_REFCOUNT_P(retsock->zstream, 1); + + php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, + PHP_STREAM_BUFFER_NONE, NULL); + + ZEND_REGISTER_RESOURCE(return_value, retsock, le_socket); + return; +error: + if (retsock != NULL) + efree(retsock); + RETURN_FALSE; +} +/* }}} */ + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: fdm=marker + * vim: noet sw=4 ts=4 + */ diff --git a/ext/sockets/sockets.dsp b/ext/sockets/sockets.dsp new file mode 100644 index 0000000..961bab7 --- /dev/null +++ b/ext/sockets/sockets.dsp @@ -0,0 +1,117 @@ +# Microsoft Developer Studio Project File - Name="sockets" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=sockets - Win32 Debug_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sockets.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sockets.mak" CFG="sockets - Win32 Debug_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sockets - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "sockets - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sockets - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOCKETS_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\..\bindlib_w32" /D "WIN32" /D "PHP_EXPORTS" /D "COMPILE_DL_SOCKETS" /D ZTS=1 /D HAVE_SOCKETS=1 /D ZEND_DEBUG=0 /D "NDEBUG" /D "_WINDOWS" /D "ZEND_WIN32" /D "PHP_WIN32" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 php5ts.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_sockets.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"
+# SUBTRACT LINK32 /debug
+
+!ELSEIF "$(CFG)" == "sockets - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOCKETS_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\..\bindlib_w32" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "PHP_EXPORTS" /D "COMPILE_DL_SOCKETS" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SOCKETS=1 /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 php5ts_debug.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS/php_sockets.dll" /pdbtype:sept /libpath:"..\..\Debug_TS"
+
+!ENDIF
+
+# Begin Target
+
+# Name "sockets - Win32 Release_TS"
+# Name "sockets - Win32 Debug_TS"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\php_sockets_win.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sockets.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_sockets.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_sockets_win.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/ext/sockets/tests/bug46360.phpt b/ext/sockets/tests/bug46360.phpt new file mode 100644 index 0000000..c725a82 --- /dev/null +++ b/ext/sockets/tests/bug46360.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug 46360 - TCP_NODELAY constant (sock_get_option, sock_set_option) +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (version_compare(phpversion(), '5.2.7', '<')) { + die('skip old php, not eligible'); + } +?> +--FILE-- +<?php + var_dump('TCP_NODELAY'); +?> +--EXPECT-- +string(11) "TCP_NODELAY" diff --git a/ext/sockets/tests/bug49341.phpt b/ext/sockets/tests/bug49341.phpt new file mode 100644 index 0000000..961b5e7 --- /dev/null +++ b/ext/sockets/tests/bug49341.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #49341: add SO_REUSEPORT support for socket_set_option() +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); +} +if (PHP_OS !== 'Darwin' && false === strpos(PHP_OS, 'BSD')) { + die('skip is not *BSD.'); +} +--FILE-- +<?php +var_dump(defined('SO_REUSEPORT')); +--EXPECTF-- +bool(true) diff --git a/ext/sockets/tests/bug51958.phpt b/ext/sockets/tests/bug51958.phpt new file mode 100644 index 0000000..afccd6c --- /dev/null +++ b/ext/sockets/tests/bug51958.phpt @@ -0,0 +1,22 @@ +--TEST--
+Bug #51958: socket_accept() fails on IPv6 server sockets
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+if (PHP_OS != "WINNT")
+ die('skip test relies Winsock\'s error code for WSAEWOULDBLOCK/EAGAIN');
+--FILE--
+<?php
+$listenfd = socket_create(AF_INET6, SOCK_STREAM, SOL_TCP);
+socket_bind($listenfd, "::1", 13579);
+socket_listen($listenfd);
+socket_set_nonblock($listenfd);
+$connfd = @socket_accept($listenfd);
+echo socket_last_error();
+--EXPECT--
+10035
diff --git a/ext/sockets/tests/bug63000.phpt b/ext/sockets/tests/bug63000.phpt new file mode 100644 index 0000000..c806ba4 --- /dev/null +++ b/ext/sockets/tests/bug63000.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #63000: Multicast on OSX +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); +} +if (PHP_OS !== 'Darwin') { + die('is not OSX.'); +} +--FILE-- +<?php +$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); +socket_bind($socket, '0.0.0.0', 31057); + +$so = socket_set_option($socket, IPPROTO_IP, MCAST_JOIN_GROUP, array( + "group" => '224.0.0.251', + "interface" => 0, +)); +var_dump($so); +--EXPECTF-- +bool(true) diff --git a/ext/sockets/tests/ipv4loop.phpt b/ext/sockets/tests/ipv4loop.phpt new file mode 100644 index 0000000..9fdcc17 --- /dev/null +++ b/ext/sockets/tests/ipv4loop.phpt @@ -0,0 +1,49 @@ +--TEST-- +IPv4 Loopback test +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + /* Setup socket server */ + $server = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); + if (!$server) { + die('Unable to create AF_INET socket [server]'); + } + if (!socket_bind($server, '127.0.0.1', 31337)) { + die('Unable to bind to 127.0.0.1:31337'); + } + if (!socket_listen($server, 2)) { + die('Unable to listen on socket'); + } + + /* Connect to it */ + $client = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); + if (!$client) { + die('Unable to create AF_INET socket [client]'); + } + if (!socket_connect($client, '127.0.0.1', 31337)) { + die('Unable to connect to server socket'); + } + + /* Accept that connection */ + $socket = socket_accept($server); + if (!$socket) { + die('Unable to accept connection'); + } + + socket_write($client, "ABCdef123\n"); + + $data = socket_read($socket, 10, PHP_BINARY_READ); + var_dump($data); + + socket_close($client); + socket_close($socket); + socket_close($server); +?> +--EXPECT-- +string(10) "ABCdef123 +" diff --git a/ext/sockets/tests/ipv6_skipif.inc b/ext/sockets/tests/ipv6_skipif.inc new file mode 100644 index 0000000..1f82463 --- /dev/null +++ b/ext/sockets/tests/ipv6_skipif.inc @@ -0,0 +1,6 @@ +<?php +if (!defined("AF_INET6")) { + die('skip no IPv6 support'); +} +if (@stream_socket_client('udp://[::1]:8888') === false) + die('skip no IPv6 support'); diff --git a/ext/sockets/tests/ipv6loop.phpt b/ext/sockets/tests/ipv6loop.phpt new file mode 100644 index 0000000..6967605 --- /dev/null +++ b/ext/sockets/tests/ipv6loop.phpt @@ -0,0 +1,50 @@ +--TEST-- +IPv6 Loopback test +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } + require 'ipv6_skipif.inc'; +?> +--FILE-- +<?php + /* Setup socket server */ + $server = socket_create(AF_INET6, SOCK_STREAM, getprotobyname('tcp')); + if (!$server) { + die('Unable to create AF_INET6 socket [server]'); + } + if (!socket_bind($server, '::1', 31337)) { + die('Unable to bind to [::1]:31337'); + } + if (!socket_listen($server, 2)) { + die('Unable to listen on socket'); + } + + /* Connect to it */ + $client = socket_create(AF_INET6, SOCK_STREAM, getprotobyname('tcp')); + if (!$client) { + die('Unable to create AF_INET6 socket [client]'); + } + if (!socket_connect($client, '::1', 31337)) { + die('Unable to connect to server socket'); + } + + /* Accept that connection */ + $socket = socket_accept($server); + if (!$socket) { + die('Unable to accept connection'); + } + + socket_write($client, "ABCdef123\n"); + + $data = socket_read($socket, 10, PHP_BINARY_READ); + var_dump($data); + + socket_close($client); + socket_close($socket); + socket_close($server); +?> +--EXPECT-- +string(10) "ABCdef123 +" diff --git a/ext/sockets/tests/mcast_helpers.php.inc b/ext/sockets/tests/mcast_helpers.php.inc new file mode 100644 index 0000000..ad65a3f --- /dev/null +++ b/ext/sockets/tests/mcast_helpers.php.inc @@ -0,0 +1,8 @@ +<?php +function checktimeout($sock, $limit) { + $readfs = array($sock); + $writefs = $exceptfs = array(); + if (socket_select($readfs, $writefs, $exceptfs, 0, $limit*1000) != 1) { + die("Socket read timeout hit. Can be a bug, a test bug, or a firewall issue."); + } +} diff --git a/ext/sockets/tests/mcast_ipv4_recv.phpt b/ext/sockets/tests/mcast_ipv4_recv.phpt new file mode 100644 index 0000000..8c90ae0 --- /dev/null +++ b/ext/sockets/tests/mcast_ipv4_recv.phpt @@ -0,0 +1,197 @@ +--TEST--
+Multicast support: IPv4 receive options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '0.0.0.0', 3000);
+$so = socket_set_option($s, IPPROTO_IP, MCAST_JOIN_GROUP, array(
+ "group" => '224.0.0.23',
+ "interface" => 'lo',
+));
+if ($so === false) {
+ die('skip interface \'lo\' is unavailable.');
+}
+if (!defined("MCAST_BLOCK_SOURCE")) {
+ die('skip source operations are unavailable');
+}
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+$domain = AF_INET;
+$level = IPPROTO_IP;
+$interface = "lo";
+$mcastaddr = '224.0.0.23';
+$sblock = "127.0.0.1";
+
+echo "creating send socket bound to 127.0.0.1\n";
+$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($sends1, '127.0.0.1');
+var_dump($br);
+
+echo "creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to $mcastaddr\n";
+$sends2 = socket_create($domain, SOCK_DGRAM, SOL_UDP);
+var_dump($br);
+
+echo "creating receive socket\n";
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP);
+var_dump($s);
+$br = socket_bind($s, '0.0.0.0', 3000);
+var_dump($br);
+
+$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+));
+var_dump($so);
+
+$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+
+$i = 0;
+checktimeout($s, 500);
+while (($str = socket_read($s, 3000)) !== FALSE) {
+ $i++;
+ echo "$i> ", $str, "\n";
+
+if ($i == 1) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 2) {
+ echo "re-joining group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends2, $m = "ignored mcast packet (different interface)", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 3) {
+ echo "blocking source\n";
+ $so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 4) {
+ echo "unblocking source\n";
+ $so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 5) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 6) {
+ echo "joining source group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 7) {
+ echo "leaving source group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 8) {
+/* echo "rjsg\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);*/
+ break;
+}
+
+}
+--EXPECTF--
+creating send socket bound to 127.0.0.1
+bool(true)
+creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to 224.0.0.23
+bool(true)
+creating receive socket
+resource(%d) of type (Socket)
+bool(true)
+bool(true)
+int(14)
+1> initial packet
+leaving group
+bool(true)
+int(20)
+int(14)
+2> unicast packet
+re-joining group
+bool(true)
+int(42)
+int(12)
+3> mcast packet
+blocking source
+bool(true)
+int(31)
+int(14)
+4> unicast packet
+unblocking source
+bool(true)
+int(27)
+5> mcast packet from 127.0.0.1
+leaving group
+bool(true)
+int(20)
+int(14)
+6> unicast packet
+joining source group
+bool(true)
+int(27)
+7> mcast packet from 127.0.0.1
+leaving source group
+bool(true)
+int(20)
+int(14)
+8> unicast packet
diff --git a/ext/sockets/tests/mcast_ipv4_send.phpt b/ext/sockets/tests/mcast_ipv4_send.phpt new file mode 100644 index 0000000..ac5bce9 --- /dev/null +++ b/ext/sockets/tests/mcast_ipv4_send.phpt @@ -0,0 +1,65 @@ +--TEST--
+Multicast support: IPv4 send options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) {
+ die("skip interface 1 either doesn't exist or has no ipv4 address");
+}
+--FILE--
+<?php
+$domain = AF_INET;
+$level = IPPROTO_IP;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+
+echo "Setting IP_MULTICAST_TTL\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_TTL, 9);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_TTL);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_LOOP\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_LOOP);
+var_dump($r);
+$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_LOOP);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_IF\n";
+echo "interface 0:\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_IF, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_IF);
+var_dump($r);
+echo "interface 1:\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_IF, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_IF);
+var_dump($r);
+echo "\n";
+
+--EXPECT--
+Setting IP_MULTICAST_TTL
+bool(true)
+int(9)
+
+Setting IP_MULTICAST_LOOP
+bool(true)
+int(0)
+bool(true)
+int(1)
+
+Setting IP_MULTICAST_IF
+interface 0:
+bool(true)
+int(0)
+interface 1:
+bool(true)
+int(1)
diff --git a/ext/sockets/tests/mcast_ipv4_send_error.phpt b/ext/sockets/tests/mcast_ipv4_send_error.phpt new file mode 100644 index 0000000..5cd3d8e --- /dev/null +++ b/ext/sockets/tests/mcast_ipv4_send_error.phpt @@ -0,0 +1,79 @@ +--TEST-- +Multicast support: IPv4 send options with unusual values +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); +} +if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) { + die("skip interface 1 either doesn't exist or has no ipv4 address"); +} +--FILE-- +<?php +$domain = AF_INET; +$level = IPPROTO_IP; +$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err"); + +echo "Setting IP_MULTICAST_LOOP with 256\n"; +//if we had a simple cast to unsigned char, this would be the same as 0 +$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 256); +var_dump($r); +$r = socket_get_option($s, $level, IP_MULTICAST_LOOP); +var_dump($r); +echo "\n"; + +echo "Setting IP_MULTICAST_LOOP with false\n"; +//should convert to (unsigned char)0 +$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, false); +var_dump($r); +$r = socket_get_option($s, $level, IP_MULTICAST_LOOP); +var_dump($r); +echo "\n"; + +echo "Setting IP_MULTICAST_TTL with 256\n"; +//if we had a simple cast to unsigned char, this would be the same as 0 +$r = socket_set_option($s, $level, IP_MULTICAST_TTL, 256); +var_dump($r); +$r = socket_get_option($s, $level, IP_MULTICAST_TTL); +var_dump($r); +echo "\n"; + +echo "Setting IP_MULTICAST_TTL with \"254\"\n"; +$r = socket_set_option($s, $level, IP_MULTICAST_TTL, "254"); +var_dump($r); +$r = socket_get_option($s, $level, IP_MULTICAST_TTL); +var_dump($r); +echo "\n"; + +echo "Setting IP_MULTICAST_TTL with -1\n"; +//should give error, not be the same as 255 +$r = socket_set_option($s, $level, IP_MULTICAST_TTL, -1); +var_dump($r); +$r = socket_get_option($s, $level, IP_MULTICAST_TTL); +var_dump($r); +echo "\n"; + +--EXPECTF-- +Setting IP_MULTICAST_LOOP with 256 +bool(true) +int(1) + +Setting IP_MULTICAST_LOOP with false +bool(true) +int(0) + +Setting IP_MULTICAST_TTL with 256 + +Warning: socket_set_option(): Expected a value between 0 and 255 in %s on line %d +bool(false) +int(1) + +Setting IP_MULTICAST_TTL with "254" +bool(true) +int(254) + +Setting IP_MULTICAST_TTL with -1 + +Warning: socket_set_option(): Expected a value between 0 and 255 in %s on line %d +bool(false) +int(254) diff --git a/ext/sockets/tests/mcast_ipv6_recv.phpt b/ext/sockets/tests/mcast_ipv6_recv.phpt new file mode 100644 index 0000000..38390c0 --- /dev/null +++ b/ext/sockets/tests/mcast_ipv6_recv.phpt @@ -0,0 +1,223 @@ +--TEST--
+Multicast support: IPv6 receive options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '::', 3000);
+/* On Linux, there is no route ff00::/8 by default on lo, which makes it
+ * troublesome to send multicast traffic from lo, which we must since
+ * we're dealing with interface-local traffic... */
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+if ($so === false) {
+ die('skip unable to join multicast group on any interface.');
+}
+$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000);
+if ($r === false) {
+ die('skip unable to send multicast packet.');
+}
+
+if (!defined("MCAST_JOIN_SOURCE_GROUP"))
+ die('skip source operations are unavailable');
+
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+ "source" => '2001::dead:beef',
+));
+if ($so === false) {
+ die('skip protocol independent multicast API is unavailable.');
+}
+
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+$domain = AF_INET6;
+$level = IPPROTO_IPV6;
+$interface = 0;
+$mcastaddr = 'ff01::114';
+$sblock = "?";
+
+echo "creating send socket\n";
+$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($sends1);
+
+echo "creating receive socket\n";
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($s);
+$br = socket_bind($s, '::0', 3000) or die("err");
+var_dump($br);
+
+$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+)) or die("err");
+var_dump($so);
+
+$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+checktimeout($s, 500);
+$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort);
+var_dump($r, $str, $from);
+$sblock = $from;
+
+$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+
+$i = 0;
+checktimeout($s, 500);
+while (($str = socket_read($s, 3000)) !== FALSE) {
+ $i++;
+ echo "$i> ", $str, "\n";
+
+if ($i == 1) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 2) {
+ echo "re-joining group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 3) {
+ echo "blocking source\n";
+ $so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 4) {
+ echo "unblocking source\n";
+ $so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 5) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 6) {
+ echo "joining source group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet from desired source", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 7) {
+ echo "leaving source group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 8) {
+ /*echo "joining source group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);*/
+ break;
+}
+
+}
+--EXPECTF--
+creating send socket
+resource(%d) of type (Socket)
+creating receive socket
+resource(%d) of type (Socket)
+bool(true)
+bool(true)
+int(14)
+int(14)
+string(14) "testing packet"
+string(%d) "%s"
+int(14)
+1> initial packet
+leaving group
+bool(true)
+int(20)
+int(14)
+2> unicast packet
+re-joining group
+bool(true)
+int(12)
+3> mcast packet
+blocking source
+bool(true)
+int(31)
+int(14)
+4> unicast packet
+unblocking source
+bool(true)
+int(12)
+5> mcast packet
+leaving group
+bool(true)
+int(20)
+int(14)
+6> unicast packet
+joining source group
+bool(true)
+int(32)
+7> mcast packet from desired source
+leaving source group
+bool(true)
+int(20)
+int(14)
+8> unicast packet
diff --git a/ext/sockets/tests/mcast_ipv6_recv_limited.phpt b/ext/sockets/tests/mcast_ipv6_recv_limited.phpt new file mode 100644 index 0000000..fda0998 --- /dev/null +++ b/ext/sockets/tests/mcast_ipv6_recv_limited.phpt @@ -0,0 +1,131 @@ +--TEST--
+Multicast support: IPv6 receive options (limited)
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '::', 3000);
+/* On Linux, there is no route ff00::/8 by default on lo, which makes it
+ * troublesome to send multicast traffic from lo, which we must since
+ * we're dealing with interface-local traffic... */
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+if ($so === false) {
+ die('skip unable to join multicast group on any interface.');
+}
+$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000);
+if ($r === false) {
+ die('skip unable to send multicast packet.');
+}
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+if (defined("MCAST_JOIN_SOURCE_GROUP")) {
+ $so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+ "source" => '2001::dead:beef',
+ ));
+ if ($so !== false) {
+ die('skip protocol independent multicast API is available.');
+ }
+}
+
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+$domain = AF_INET6;
+$level = IPPROTO_IPV6;
+$interface = 0;
+$mcastaddr = 'ff01::114';
+$sblock = "?";
+
+echo "creating send socket\n";
+$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($sends1);
+
+echo "creating receive socket\n";
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($s);
+$br = socket_bind($s, '::0', 3000) or die("err");
+var_dump($br);
+
+$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+)) or die("err");
+var_dump($so);
+
+$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+checktimeout($s, 500);
+$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort);
+var_dump($r, $str, $from);
+$sblock = $from;
+
+$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+
+$i = 0;
+checktimeout($s, 500);
+while (($str = socket_read($s, 3000, 500)) !== FALSE) {
+ $i++;
+ echo "$i> ", $str, "\n";
+
+if ($i == 1) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 2) {
+ echo "re-joining group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 3) {
+ break;
+}
+
+}
+--EXPECTF--
+creating send socket
+resource(%d) of type (Socket)
+creating receive socket
+resource(%d) of type (Socket)
+bool(true)
+bool(true)
+int(14)
+int(14)
+string(14) "testing packet"
+string(%d) "%s"
+int(14)
+1> initial packet
+leaving group
+bool(true)
+int(20)
+int(14)
+2> unicast packet
+re-joining group
+bool(true)
+int(12)
+3> mcast packet
diff --git a/ext/sockets/tests/mcast_ipv6_send.phpt b/ext/sockets/tests/mcast_ipv6_send.phpt new file mode 100644 index 0000000..b8d38bf --- /dev/null +++ b/ext/sockets/tests/mcast_ipv6_send.phpt @@ -0,0 +1,70 @@ +--TEST--
+Multicast support: IPv6 send options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+$level = IPPROTO_IPV6;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("skip Can not create socket");
+if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) {
+ die("skip interface 1 either doesn't exist or has no ipv6 address");
+}
+--FILE--
+<?php
+$domain = AF_INET6;
+$level = IPPROTO_IPV6;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+
+echo "Setting IPV6_MULTICAST_TTL\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_HOPS, 9);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_HOPS);
+var_dump($r);
+echo "\n";
+
+echo "Setting IPV6_MULTICAST_LOOP\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_LOOP, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_LOOP);
+var_dump($r);
+$r = socket_set_option($s, $level, IPV6_MULTICAST_LOOP, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_LOOP);
+var_dump($r);
+echo "\n";
+
+echo "Setting IPV6_MULTICAST_IF\n";
+echo "interface 0:\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_IF, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_IF);
+var_dump($r);
+echo "interface 1:\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_IF, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_IF);
+var_dump($r);
+echo "\n";
+
+--EXPECT--
+Setting IPV6_MULTICAST_TTL
+bool(true)
+int(9)
+
+Setting IPV6_MULTICAST_LOOP
+bool(true)
+int(0)
+bool(true)
+int(1)
+
+Setting IPV6_MULTICAST_IF
+interface 0:
+bool(true)
+int(0)
+interface 1:
+bool(true)
+int(1)
diff --git a/ext/sockets/tests/socket_accept-wrongparams.phpt b/ext/sockets/tests/socket_accept-wrongparams.phpt new file mode 100644 index 0000000..6bce05a --- /dev/null +++ b/ext/sockets/tests/socket_accept-wrongparams.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test parameter handling in socket_accept() +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +var_dump(socket_accept(null)); +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 +--EXPECTF-- +Warning: socket_accept() expects parameter 1 to be resource, null given in %s on line %d +NULL diff --git a/ext/sockets/tests/socket_bind.phpt b/ext/sockets/tests/socket_bind.phpt new file mode 100644 index 0000000..7ea2df8 --- /dev/null +++ b/ext/sockets/tests/socket_bind.phpt @@ -0,0 +1,41 @@ +--TEST-- +ext/sockets - socket_bind - basic test +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip - sockets extension not available.'); + } + if (getenv("SKIP_ONLINE_TESTS")) { + die("skip test requiring internet connection"); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $s_bind = socket_bind($s_c, '0.0.0.0', 31330+$rand); + var_dump($s_bind); + + // Connect to destination address + $s_conn = socket_connect($s_c, 'www.php.net', 80); + var_dump($s_conn); + + // Write + $request = 'GET / HTTP/1.1' . "\r\n"; + $s_write = socket_write($s_c, $request); + var_dump($s_write); + + // Close + $s_close = socket_close($s_c); + var_dump($s_close); +?> + +--EXPECTF-- +bool(true) +bool(true) +int(16) +NULL + diff --git a/ext/sockets/tests/socket_bind_params.phpt b/ext/sockets/tests/socket_bind_params.phpt new file mode 100644 index 0000000..d68a62a --- /dev/null +++ b/ext/sockets/tests/socket_bind_params.phpt @@ -0,0 +1,29 @@ +--TEST-- +ext/sockets - socket_bind - test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip - sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c = socket_create_listen(31330+$rand); + $s_w = socket_bind(); + var_dump($s_w); + $s_w = socket_bind($s_c); + var_dump($s_w); + socket_close($s_c); + +?> +--EXPECTF-- + +Warning: socket_bind() expects at least 2 parameters, 0 given in %s on line %i +NULL + +Warning: socket_bind() expects at least 2 parameters, 1 given in %s on line %i +NULL diff --git a/ext/sockets/tests/socket_close_params.phpt b/ext/sockets/tests/socket_close_params.phpt new file mode 100644 index 0000000..a00330f --- /dev/null +++ b/ext/sockets/tests/socket_close_params.phpt @@ -0,0 +1,21 @@ +--TEST-- +ext/sockets - socket_close - test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip - sockets extension not available.'); + } +?> +--FILE-- +<?php + // wrong parameter count + $s_c = socket_close(); + var_dump($s_c); +?> +--EXPECTF-- + +Warning: socket_close() expects exactly 1 parameter, 0 given in %s on line %i +NULL diff --git a/ext/sockets/tests/socket_connect_error.phpt b/ext/sockets/tests/socket_connect_error.phpt new file mode 100644 index 0000000..33e60f3 --- /dev/null +++ b/ext/sockets/tests/socket_connect_error.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test error cases when creating a socket +--CREDITS-- +Russell Flynn <russ@redpill-linpro.com> +#PHPTestFest2009 Norway 2009-06-09 \o/ +--INI-- +error_reporting=E_ALL +display_errors=1 +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + echo 'skip sockets extension not available.'; +} +?> +--FILE-- +<?php + // Test with no arguments + $server = socket_create(); + + // Test with less arguments than required + $server = socket_create(SOCK_STREAM, getprotobyname('tcp')); + + // Test with non integer parameters + $server = socket_create(array(), 1, 1); + +?> +--EXPECTF-- +Warning: socket_create() expects exactly 3 parameters, 0 given in %s on line %d + +Warning: socket_create() expects exactly 3 parameters, 2 given in %s on line %d + +Warning: socket_create() expects parameter 1 to be long, array given in %s on line %d + diff --git a/ext/sockets/tests/socket_connect_params.phpt b/ext/sockets/tests/socket_connect_params.phpt new file mode 100644 index 0000000..44f0ffd --- /dev/null +++ b/ext/sockets/tests/socket_connect_params.phpt @@ -0,0 +1,33 @@ +--TEST-- +ext/sockets - socket_connect - test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip - sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c = socket_create_listen(31330+$rand); + // wrong parameter count + $s_w = socket_connect(); + $s_w = socket_connect($s_c); + $s_w = socket_connect($s_c, '0.0.0.0'); + $s_w = socket_connect($s_c, '0.0.0.0', 31330+$rand); + + socket_close($s_c); + +?> +--EXPECTF-- + +Warning: socket_connect() expects at least 2 parameters, 0 given in %s on line %i + +Warning: socket_connect() expects at least 2 parameters, 1 given in %s on line %i + +Warning: socket_connect(): Socket of type AF_INET requires 3 arguments in %s on line %i + +Warning: socket_connect(): unable to connect [%i]: %a in %s on line %i diff --git a/ext/sockets/tests/socket_create_listen-nobind.phpt b/ext/sockets/tests/socket_create_listen-nobind.phpt new file mode 100644 index 0000000..90ae26e --- /dev/null +++ b/ext/sockets/tests/socket_create_listen-nobind.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test if socket_create_listen() returns false, when it cannot bind to the port. +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +$filename = dirname(__FILE__) . '/006_root_check.tmp'; +$fp = fopen($filename, 'w'); +fclose($fp); +if (fileowner($filename) == 0) { + unlink ($filename); + die('SKIP Test cannot be run as root.'); +} +--FILE-- +<?php +$sock = socket_create_listen(80); +--EXPECTF-- +Warning: socket_create_listen(): unable to bind to given address [13]: Permission denied in %s on line %d +--CLEAN-- +<?php +unlink(dirname(__FILE__) . '/006_root_check.tmp'); +--CREDITS-- +Till Klampaeckel, till@php.net +PHP Testfest Berlin 2009-05-09
\ No newline at end of file diff --git a/ext/sockets/tests/socket_create_listen-win32.phpt b/ext/sockets/tests/socket_create_listen-win32.phpt new file mode 100644 index 0000000..23bf963 --- /dev/null +++ b/ext/sockets/tests/socket_create_listen-win32.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test if socket binds on 31338 +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) != 'WIN') { + die('skip.. Not valid for non Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sock = socket_create_listen(31338); +socket_getsockname($sock, $addr, $port); +var_dump($addr, $port); +--EXPECT-- +string(9) "127.0.0.1" +int(31338) +--CREDITS-- +Till Klampaeckel, till@php.net +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_create_listen-wrongparams.phpt b/ext/sockets/tests/socket_create_listen-wrongparams.phpt new file mode 100644 index 0000000..ecc5172 --- /dev/null +++ b/ext/sockets/tests/socket_create_listen-wrongparams.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test if socket_create_listen throws E_WARNING with wrong parameters. +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sock1 = socket_create_listen(array()); +$sock2 = socket_create_listen(31337, array()); +--EXPECTF-- +Warning: socket_create_listen() expects parameter 1 to be long, array given in %s on line %d + +Warning: socket_create_listen() expects parameter 2 to be long, array given in %s on line %d +--CREDITS-- +Till Klampaeckel, till@php.net +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_create_listen.phpt b/ext/sockets/tests/socket_create_listen.phpt new file mode 100644 index 0000000..76f2942 --- /dev/null +++ b/ext/sockets/tests/socket_create_listen.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test if socket binds on 31338 +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip.. Not valid for Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sock = socket_create_listen(31338); +socket_getsockname($sock, $addr, $port); +var_dump($addr, $port); +--EXPECT-- +string(7) "0.0.0.0" +int(31338) +--CREDITS-- +Till Klampaeckel, till@php.net +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_create_listen_params.phpt b/ext/sockets/tests/socket_create_listen_params.phpt new file mode 100644 index 0000000..56a9c8d --- /dev/null +++ b/ext/sockets/tests/socket_create_listen_params.phpt @@ -0,0 +1,23 @@ +--TEST-- +ext/sockets - socket_create_listen - test for empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip - sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c_l = socket_create_listen(); + var_dump($s_c_l); + if ($s_c_l !== false) { + @socket_close($s_c_l); + } +?> +--EXPECTF-- +Warning: socket_create_listen() expects at least 1 parameter, 0 given in %s on line %i +NULL diff --git a/ext/sockets/tests/socket_create_listen_used.phpt b/ext/sockets/tests/socket_create_listen_used.phpt new file mode 100644 index 0000000..1e45f82 --- /dev/null +++ b/ext/sockets/tests/socket_create_listen_used.phpt @@ -0,0 +1,30 @@ +--TEST-- +ext/sockets - socket_create_listen - test for used socket +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip - sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + // wrong parameter count + $s_c_l = socket_create_listen(31330+$rand); + var_dump($s_c_l); + // default invocation + $s_c_l2 = socket_create_listen(31330+$rand); + var_dump($s_c_l2); + socket_close($s_c_l2); + socket_close($s_c_l); +?> +--EXPECTF-- +resource(%i) of type (Socket) + +Warning: socket_create_listen(): unable to bind to given address [%i]: %a in %s on line %i +bool(false) + +Warning: socket_close() expects parameter 1 to be resource, boolean given in %s on line %i diff --git a/ext/sockets/tests/socket_create_pair-wrongparams-win32.phpt b/ext/sockets/tests/socket_create_pair-wrongparams-win32.phpt new file mode 100644 index 0000000..de33d95 --- /dev/null +++ b/ext/sockets/tests/socket_create_pair-wrongparams-win32.phpt @@ -0,0 +1,38 @@ +--TEST-- +Test parameter handling in socket_create_pair() +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) != 'WIN') { + die('skip.. Not valid for non Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +var_dump(socket_create_pair(AF_INET, null, null)); + +$domain = 'unknown'; +var_dump(socket_create_pair($domain, SOCK_STREAM, 0, $sockets)); + +var_dump(socket_create_pair(AF_INET, null, null, $sockets)); + +var_dump(socket_create_pair(31337, null, null, $sockets)); + +var_dump(socket_create_pair(AF_INET, 31337, 0, $sockets)); +--EXPECTF-- +Warning: socket_create_pair() expects exactly 4 parameters, 3 given in %s on line %d +NULL + +Warning: socket_create_pair() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d +NULL +bool(true) + +Warning: socket_create_pair(): invalid socket domain [31337] specified for argument 1, assuming AF_INET in %s on line %d +bool(true) + +Warning: socket_create_pair(): invalid socket type [31337] specified for argument 2, assuming SOCK_STREAM in %s on line %d +bool(true) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_create_pair-wrongparams.phpt b/ext/sockets/tests/socket_create_pair-wrongparams.phpt new file mode 100644 index 0000000..afca2b8 --- /dev/null +++ b/ext/sockets/tests/socket_create_pair-wrongparams.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test parameter handling in socket_create_pair() +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip.. Not valid for Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +var_dump(socket_create_pair(AF_INET, null, null)); + +$domain = 'unknown'; +var_dump(socket_create_pair($domain, SOCK_STREAM, 0, $sockets)); + +var_dump(socket_create_pair(AF_INET, null, null, $sockets)); + +var_dump(socket_create_pair(31337, null, null, $sockets)); + +var_dump(socket_create_pair(AF_INET, 31337, 0, $sockets)); +--EXPECTF-- +Warning: socket_create_pair() expects exactly 4 parameters, 3 given in %s on line %d +NULL + +Warning: socket_create_pair() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d +NULL + +Warning: socket_create_pair(): unable to create socket pair [%d]: %s not supported in %s on line %d +bool(false) + +Warning: socket_create_pair(): invalid socket domain [31337] specified for argument 1, assuming AF_INET in %s on line %d + +Warning: socket_create_pair(): unable to create socket pair [%d]: %s not supported in %s on line %d +bool(false) + +Warning: socket_create_pair(): invalid socket type [31337] specified for argument 2, assuming SOCK_STREAM in %s on line %d + +Warning: socket_create_pair(): unable to create socket pair [%d]: %s not supported %s on line %d +bool(false) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_create_pair.phpt b/ext/sockets/tests/socket_create_pair.phpt new file mode 100644 index 0000000..6af6e42 --- /dev/null +++ b/ext/sockets/tests/socket_create_pair.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test for socket_create_pair() +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = array(); +if (strtolower(substr(PHP_OS, 0, 3)) == 'win') { + $domain = AF_INET; +} else { + $domain = AF_UNIX; +} +socket_create_pair($domain, SOCK_STREAM, 0, $sockets); +var_dump($sockets); +--EXPECT-- +array(2) { + [0]=> + resource(4) of type (Socket) + [1]=> + resource(5) of type (Socket) +} diff --git a/ext/sockets/tests/socket_create_params.phpt b/ext/sockets/tests/socket_create_params.phpt new file mode 100644 index 0000000..13a1c73 --- /dev/null +++ b/ext/sockets/tests/socket_create_params.phpt @@ -0,0 +1,24 @@ +--TEST-- +ext/sockets - socket_create - test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $s_w = socket_create(); + $s_w = socket_create(AF_INET); + $s_w = socket_create(AF_INET, SOCK_STREAM); +?> +--EXPECTF-- + +Warning: socket_create() expects exactly 3 parameters, 0 given in %s on line %i + +Warning: socket_create() expects exactly 3 parameters, 1 given in %s on line %i + +Warning: socket_create() expects exactly 3 parameters, 2 given in %s on line %i diff --git a/ext/sockets/tests/socket_getpeername.phpt b/ext/sockets/tests/socket_getpeername.phpt new file mode 100644 index 0000000..280fa2a --- /dev/null +++ b/ext/sockets/tests/socket_getpeername.phpt @@ -0,0 +1,33 @@ +--TEST-- +ext/sockets - socket_getsockname - basic test +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $s_bind = socket_bind($s_c, '0.0.0.0', 31330+$rand); + var_dump($s_bind); + + // Connect to destination address + $s_peer = socket_getpeername($s_c, $ip, $port); + var_dump($s_peer); + var_dump($ip); + var_dump($port); + socket_close($s_c); +?> + +--EXPECTF-- +bool(true) + +Warning: socket_getpeername(): unable to retrieve peer name [%i]: %a in %s on line %i +bool(false) +NULL +NULL diff --git a/ext/sockets/tests/socket_getpeername_ipv4loop.phpt b/ext/sockets/tests/socket_getpeername_ipv4loop.phpt new file mode 100644 index 0000000..aa59abb --- /dev/null +++ b/ext/sockets/tests/socket_getpeername_ipv4loop.phpt @@ -0,0 +1,59 @@ +--TEST-- +ext/sockets - socket_getpeername_ipv4loop - basic test +--CREDITS-- +# TestFest 2009 - NorwayUG +# $Id: socket_getpeername_ipv4loop.phpt 494 2009-06-09 20:38:05Z tatjana.andersen@redpill-linpro.com $ +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + /* Bind and connect sockets to localhost */ + $localhost = '127.0.0.1'; + + /* Hold the port associated to address */ + $port = 31337; + + /* Setup socket server */ + $server = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); + if (!$server) { + die('Unable to create AF_INET socket [server]'); + } + + if (!socket_bind($server, $localhost, $port)) { + die('Unable to bind to '.$localhost.':'.$port); + } + if (!socket_listen($server, 2)) { + die('Unable to listen on socket'); + } + + /* Connect to it */ + $client = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); + if (!$client) { + die('Unable to create AF_INET socket [client]'); + } + if (!socket_connect($client, $localhost, $port)) { + die('Unable to connect to server socket'); + } + + /* Accept that connection */ + $socket = socket_accept($server); + if (!$socket) { + die('Unable to accept connection'); + } + + if (!socket_getpeername($client, $address, $port)) { + die('Unable to retrieve peer name'); + } + var_dump($address, $port); + + socket_close($client); + socket_close($socket); + socket_close($server); +?> +--EXPECT-- +string(9) "127.0.0.1" +int(31337) diff --git a/ext/sockets/tests/socket_getpeername_ipv6loop.phpt b/ext/sockets/tests/socket_getpeername_ipv6loop.phpt new file mode 100644 index 0000000..e865f3e --- /dev/null +++ b/ext/sockets/tests/socket_getpeername_ipv6loop.phpt @@ -0,0 +1,60 @@ +--TEST-- +ext/sockets - socket_getpeername_ipv6loop - basic test +--CREDITS-- +# TestFest 2009 - NorwayUG +# $Id: socket_getpeername_ipv6loop.phpt 494 2009-06-09 20:38:05Z tatjana.andersen@redpill-linpro.com $ +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); +} +require 'ipv6_skipif.inc'; +?> +--FILE-- +<?php + /* Bind and connect sockets to localhost */ + $localhost = '::1'; + + /* Hold the port associated to address */ + $port = 31337; + + /* Setup socket server */ + $server = socket_create(AF_INET6, SOCK_STREAM, getprotobyname('tcp')); + if (!$server) { + die('Unable to create AF_INET6 socket [server]'); + } + + if (!socket_bind($server, $localhost, $port)) { + die('Unable to bind to '.$localhost.':'.$port); + } + if (!socket_listen($server, 2)) { + die('Unable to listen on socket'); + } + + /* Connect to it */ + $client = socket_create(AF_INET6, SOCK_STREAM, getprotobyname('tcp')); + if (!$client) { + die('Unable to create AF_INET6 socket [client]'); + } + if (!socket_connect($client, $localhost, $port)) { + die('Unable to connect to server socket'); + } + + /* Accept that connection */ + $socket = socket_accept($server); + if (!$socket) { + die('Unable to accept connection'); + } + + if (!socket_getpeername($client, $address, $port)) { + die('Unable to retrieve peer name'); + } + var_dump($address, $port); + + socket_close($client); + socket_close($socket); + socket_close($server); +?> +--EXPECT-- +string(3) "::1" +int(31337) diff --git a/ext/sockets/tests/socket_getsockname.phpt b/ext/sockets/tests/socket_getsockname.phpt new file mode 100644 index 0000000..877bef5 --- /dev/null +++ b/ext/sockets/tests/socket_getsockname.phpt @@ -0,0 +1,32 @@ +--TEST-- +ext/sockets - socket_getsockname - basic test +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $s_bind = socket_bind($s_c, '0.0.0.0', 31330+$rand); + var_dump($s_bind); + + // Connect to destination address + $s_conn = socket_getsockname($s_c, $ip, $port); + var_dump($s_conn); + var_dump($ip); + var_dump($port); + socket_close($s_c); +?> + +--EXPECTF-- +bool(true) +bool(true) +string(7) "0.0.0.0" +int(%i) + diff --git a/ext/sockets/tests/socket_import_stream-1.phpt b/ext/sockets/tests/socket_import_stream-1.phpt new file mode 100644 index 0000000..222fca5 --- /dev/null +++ b/ext/sockets/tests/socket_import_stream-1.phpt @@ -0,0 +1,26 @@ +--TEST-- +socket_import_stream: Basic test +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} + +--FILE-- +<?php + +$domain = (strtoupper(substr(PHP_OS, 0, 3) == 'WIN') ? STREAM_PF_INET : STREAM_PF_UNIX); +$s = stream_socket_pair($domain, STREAM_SOCK_STREAM, 0); + +$s0 = reset($s); +$s1 = next($s); + +$sock = socket_import_stream($s0); +var_dump($sock); +socket_write($sock, "test message"); +socket_close($sock); + +var_dump(stream_get_contents($s1)); +--EXPECTF-- +resource(%d) of type (Socket) +string(12) "test message" diff --git a/ext/sockets/tests/socket_import_stream-2.phpt b/ext/sockets/tests/socket_import_stream-2.phpt new file mode 100644 index 0000000..085f0e3 --- /dev/null +++ b/ext/sockets/tests/socket_import_stream-2.phpt @@ -0,0 +1,49 @@ +--TEST-- +socket_import_stream: Bad arguments +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} + +--FILE-- +<?php + +var_dump(socket_import_stream()); +var_dump(socket_import_stream(1, 2)); +var_dump(socket_import_stream(1)); +var_dump(socket_import_stream(new stdclass)); +var_dump(socket_import_stream(fopen(__FILE__, "rb"))); +var_dump(socket_import_stream(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))); +$s = stream_socket_server("udp://127.0.0.1:58392", $errno, $errstr, STREAM_SERVER_BIND); +var_dump($s); +var_dump(fclose($s)); +var_dump(socket_import_stream($s)); + + +echo "Done."; +--EXPECTF-- +Warning: socket_import_stream() expects exactly 1 parameter, 0 given in %s on line %d +NULL + +Warning: socket_import_stream() expects exactly 1 parameter, 2 given in %s on line %d +NULL + +Warning: socket_import_stream() expects parameter 1 to be resource, integer given in %s on line %d +NULL + +Warning: socket_import_stream() expects parameter 1 to be resource, object given in %s on line %d +NULL + +Warning: socket_import_stream(): cannot represent a stream of type STDIO as a Socket Descriptor in %s on line %d +bool(false) + +Warning: socket_import_stream(): supplied resource is not a valid stream resource in %s on line %d +bool(false) +resource(%d) of type (stream) +bool(true) + +Warning: socket_import_stream(): %d is not a valid stream resource in %s on line %d +bool(false) +Done. + diff --git a/ext/sockets/tests/socket_import_stream-3.phpt b/ext/sockets/tests/socket_import_stream-3.phpt new file mode 100644 index 0000000..2261a03 --- /dev/null +++ b/ext/sockets/tests/socket_import_stream-3.phpt @@ -0,0 +1,46 @@ +--TEST-- +socket_import_stream: Test with multicasting +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); +$br = socket_bind($s, '0.0.0.0', 58381); +if ($br === false) + die("SKIP IPv4/port 58381 not available"); +$so = socket_set_option($s, IPPROTO_IP, MCAST_JOIN_GROUP, array( + "group" => '224.0.0.23', + "interface" => "lo", +)); +if ($so === false) + die("SKIP joining group 224.0.0.23 on interface lo failed"); +--FILE-- +<?php + +$stream = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND); +$sock = socket_import_stream($stream); +var_dump($sock); +$so = socket_set_option($sock, IPPROTO_IP, MCAST_JOIN_GROUP, array( + "group" => '224.0.0.23', + "interface" => "lo", +)); +var_dump($so); + +$sendsock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); +var_dump($sendsock); +$br = socket_bind($sendsock, '127.0.0.1'); +$so = socket_sendto($sendsock, $m = "my message", strlen($m), 0, "224.0.0.23", 58381); +var_dump($so); + +stream_set_blocking($stream, 0); +var_dump(fread($stream, strlen($m))); +echo "Done.\n"; +--EXPECTF-- +resource(%d) of type (Socket) +bool(true) +resource(%d) of type (Socket) +int(10) +string(10) "my message" +Done. + diff --git a/ext/sockets/tests/socket_import_stream-4-win.phpt b/ext/sockets/tests/socket_import_stream-4-win.phpt new file mode 100644 index 0000000..b36764f --- /dev/null +++ b/ext/sockets/tests/socket_import_stream-4-win.phpt @@ -0,0 +1,103 @@ +--TEST-- +socket_import_stream: effects of closing +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die("skip Not Valid for Linux"); +} + +--FILE-- +<?php + +function test($stream, $sock) { + if ($stream !== null) { + echo "stream_set_blocking "; + print_r(stream_set_blocking($stream, 0)); + echo "\n"; + } + if ($sock !== null) { + echo "socket_set_block "; + print_r(socket_set_block($sock)); + echo "\n"; + echo "socket_get_option "; + print_r(socket_get_option($sock, SOL_SOCKET, SO_TYPE)); + echo "\n"; + } + echo "\n"; +} + +echo "normal\n"; +$stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND); +$sock0 = socket_import_stream($stream0); +test($stream0, $sock0); + +echo "\nunset stream\n"; +$stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND); +$sock1 = socket_import_stream($stream1); +unset($stream1); +test(null, $sock1); + +echo "\nunset socket\n"; +$stream2 = stream_socket_server("udp://0.0.0.0:58382", $errno, $errstr, STREAM_SERVER_BIND); +$sock2 = socket_import_stream($stream2); +unset($sock2); +test($stream2, null); + +echo "\nclose stream\n"; +$stream3 = stream_socket_server("udp://0.0.0.0:58383", $errno, $errstr, STREAM_SERVER_BIND); +$sock3 = socket_import_stream($stream3); +fclose($stream3); +test($stream3, $sock3); + +echo "\nclose socket\n"; +$stream4 = stream_socket_server("udp://0.0.0.0:58384", $errno, $errstr, STREAM_SERVER_BIND); +$sock4 = socket_import_stream($stream4); +socket_close($sock4); +test($stream4, $sock4); + +echo "Done.\n"; +--EXPECTF-- +normal +stream_set_blocking 1 +socket_set_block 1 +socket_get_option 2 + + +unset stream +socket_set_block 1 +socket_get_option 2 + + +unset socket +stream_set_blocking 1 + + +close stream +stream_set_blocking +Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d + +socket_set_block +Warning: socket_set_block(): unable to set blocking mode [%d]: An operation was attempted on something that is not a socket. + in %ssocket_import_stream-4-win.php on line %d + +socket_get_option +Warning: socket_get_option(): unable to retrieve socket option [%d]: An operation was attempted on something that is not a socket. + in %ssocket_import_stream-4-win.php on line %d + + + +close socket +stream_set_blocking +Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d + +socket_set_block +Warning: socket_set_block(): %d is not a valid Socket resource in %s on line %d + +socket_get_option +Warning: socket_get_option(): %d is not a valid Socket resource in %s on line %d + + +Done. diff --git a/ext/sockets/tests/socket_import_stream-4.phpt b/ext/sockets/tests/socket_import_stream-4.phpt new file mode 100644 index 0000000..8095d8d --- /dev/null +++ b/ext/sockets/tests/socket_import_stream-4.phpt @@ -0,0 +1,100 @@ +--TEST-- +socket_import_stream: effects of closing +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die("skip Not Valid for Windows"); +} +--FILE-- +<?php + +function test($stream, $sock) { + if ($stream !== null) { + echo "stream_set_blocking "; + print_r(stream_set_blocking($stream, 0)); + echo "\n"; + } + if ($sock !== null) { + echo "socket_set_block "; + print_r(socket_set_block($sock)); + echo "\n"; + echo "socket_get_option "; + print_r(socket_get_option($sock, SOL_SOCKET, SO_TYPE)); + echo "\n"; + } + echo "\n"; +} + +echo "normal\n"; +$stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND); +$sock0 = socket_import_stream($stream0); +test($stream0, $sock0); + +echo "\nunset stream\n"; +$stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND); +$sock1 = socket_import_stream($stream1); +unset($stream1); +test(null, $sock1); + +echo "\nunset socket\n"; +$stream2 = stream_socket_server("udp://0.0.0.0:58382", $errno, $errstr, STREAM_SERVER_BIND); +$sock2 = socket_import_stream($stream2); +unset($sock2); +test($stream2, null); + +echo "\nclose stream\n"; +$stream3 = stream_socket_server("udp://0.0.0.0:58383", $errno, $errstr, STREAM_SERVER_BIND); +$sock3 = socket_import_stream($stream3); +fclose($stream3); +test($stream3, $sock3); + +echo "\nclose socket\n"; +$stream4 = stream_socket_server("udp://0.0.0.0:58384", $errno, $errstr, STREAM_SERVER_BIND); +$sock4 = socket_import_stream($stream4); +socket_close($sock4); +test($stream4, $sock4); + +echo "Done.\n"; +--EXPECTF-- +normal +stream_set_blocking 1 +socket_set_block 1 +socket_get_option 2 + + +unset stream +socket_set_block 1 +socket_get_option 2 + + +unset socket +stream_set_blocking 1 + + +close stream +stream_set_blocking +Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d + +socket_set_block +Warning: socket_set_block(): unable to set blocking mode [%d]: %s in %s on line %d + +socket_get_option +Warning: socket_get_option(): unable to retrieve socket option [%d]: %s in %s on line %d + + + +close socket +stream_set_blocking +Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d + +socket_set_block +Warning: socket_set_block(): %d is not a valid Socket resource in %s on line %d + +socket_get_option +Warning: socket_get_option(): %d is not a valid Socket resource in %s on line %d + + +Done. diff --git a/ext/sockets/tests/socket_import_stream-5.phpt b/ext/sockets/tests/socket_import_stream-5.phpt new file mode 100644 index 0000000..d48531e --- /dev/null +++ b/ext/sockets/tests/socket_import_stream-5.phpt @@ -0,0 +1,23 @@ +--TEST-- +socket_import_stream: effects of leaked handles +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +if (!function_exists('leak_variable')) + die('SKIP only for debug builds'); +--FILE-- +<?php + +$stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND); +$sock0 = socket_import_stream($stream0); +leak_variable($stream0, true); + +$stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND); +$sock1 = socket_import_stream($stream1); +leak_variable($sock1, true); + +echo "Done.\n"; +--EXPECT-- +Done. diff --git a/ext/sockets/tests/socket_listen-wrongparams.phpt b/ext/sockets/tests/socket_listen-wrongparams.phpt new file mode 100644 index 0000000..b5e1354 --- /dev/null +++ b/ext/sockets/tests/socket_listen-wrongparams.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test parameter handling in socket_listen(). +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip.. Not valid for Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +var_dump(socket_listen(null)); +$socket = socket_create(AF_UNIX, SOCK_STREAM, 0); +var_dump(socket_listen($socket)); +--EXPECTF-- +Warning: socket_listen() expects parameter 1 to be resource, null given in %s on line %d +NULL + +Warning: socket_listen(): unable to listen on socket [%d]: Invalid argument in %s on line %d +bool(false) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_listen_params.phpt b/ext/sockets/tests/socket_listen_params.phpt new file mode 100644 index 0000000..65c1117 --- /dev/null +++ b/ext/sockets/tests/socket_listen_params.phpt @@ -0,0 +1,21 @@ +--TEST-- +ext/sockets - socket_listen - test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + // wrong parameter count + $s_c = socket_listen(); + var_dump($s_c); +?> +--EXPECTF-- + +Warning: socket_listen() expects at least 1 parameter, 0 given in %s on line %i +NULL diff --git a/ext/sockets/tests/socket_read_params.phpt b/ext/sockets/tests/socket_read_params.phpt new file mode 100644 index 0000000..3b4821a --- /dev/null +++ b/ext/sockets/tests/socket_read_params.phpt @@ -0,0 +1,28 @@ +--TEST-- +ext/sockets - socket_read- test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + // wrong parameter count + $s_c = socket_read(); + $s_c = socket_read(14); + $s_c_l = socket_create_listen(31330+$rand); + $s_c = socket_read($s_c_l, 25); + socket_close($s_c_l); +?> +--EXPECTF-- + +Warning: socket_read() expects at least 2 parameters, 0 given in %s on line %i + +Warning: socket_read() expects at least 2 parameters, 1 given in %s on line %i + +Warning: socket_read(): unable to read from socket [%i]: %a in %s on line %i diff --git a/ext/sockets/tests/socket_select-wrongparams-1-win32.phpt b/ext/sockets/tests/socket_select-wrongparams-1-win32.phpt new file mode 100644 index 0000000..34d46d6 --- /dev/null +++ b/ext/sockets/tests/socket_select-wrongparams-1-win32.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test parameter handling in socket_select(). +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) != 'WIN') { + die('skip.. Not valid for non Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = array(); +$domain = AF_INET; +socket_create_pair($domain, SOCK_STREAM, 0, $sockets); + +$write = null; +$except = null; +$time = -1; +var_dump(socket_select($sockets, $write, $except, $time)); +--EXPECTF-- +int(0) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_select-wrongparams-1.phpt b/ext/sockets/tests/socket_select-wrongparams-1.phpt new file mode 100644 index 0000000..848088f --- /dev/null +++ b/ext/sockets/tests/socket_select-wrongparams-1.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test parameter handling in socket_select(). +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip.. Not valid for Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = array(); +$domain = AF_UNIX; +socket_create_pair($domain, SOCK_STREAM, 0, $sockets); + +$write = null; +$except = null; +$time = -1; +var_dump(socket_select($sockets, $write, $except, $time)); +--EXPECTF-- +Warning: socket_select(): unable to select [%d]: Invalid argument in %s on line %d +bool(false) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_select-wrongparams-2.phpt b/ext/sockets/tests/socket_select-wrongparams-2.phpt new file mode 100644 index 0000000..c149973 --- /dev/null +++ b/ext/sockets/tests/socket_select-wrongparams-2.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test parameter handling in socket_select(). +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = null; +$write = null; +$except = null; +$time = 0; +var_dump(socket_select($sockets, $write, $except, $time)); +socket_select($sockets, $write, $except); +--EXPECTF-- +Warning: socket_select(): no resource arrays were passed to select in %s on line %d +bool(false) + +Warning: socket_select() expects at least 4 parameters, 3 given in %s on line %d +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_select-wrongparams-3.phpt b/ext/sockets/tests/socket_select-wrongparams-3.phpt new file mode 100644 index 0000000..51686f9 --- /dev/null +++ b/ext/sockets/tests/socket_select-wrongparams-3.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test parameter handling in socket_select(). +--DESCRIPTION-- +Time must be long, otherwise it's casted. +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = array(); +if (strtolower(substr(PHP_OS, 0, 3)) == 'win') { + $domain = AF_INET; +} else { + $domain = AF_UNIX; +} +socket_create_pair($domain, SOCK_STREAM, 0, $sockets); + +$write = null; +$except = null; +$time = array(); +var_dump(socket_select($sockets, $write, $except, $time)); +--EXPECT-- +int(0) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_select-wrongparams-4.phpt b/ext/sockets/tests/socket_select-wrongparams-4.phpt new file mode 100644 index 0000000..7a107b4 --- /dev/null +++ b/ext/sockets/tests/socket_select-wrongparams-4.phpt @@ -0,0 +1,29 @@ +--TEST-- +Test parameter handling in socket_select(). +--DESCRIPTION-- +usec > 999999 +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = array(); +if (strtolower(substr(PHP_OS, 0, 3)) == 'win') { + $domain = AF_INET; +} else { + $domain = AF_UNIX; +} +socket_create_pair($domain, SOCK_STREAM, 0, $sockets); + +$write = null; +$except = null; +$time = 0; +$usec = 2000000; +var_dump(socket_select($sockets, $write, $except, $time, $usec)); +--EXPECT-- +int(0) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_select.phpt b/ext/sockets/tests/socket_select.phpt new file mode 100644 index 0000000..3896a09 --- /dev/null +++ b/ext/sockets/tests/socket_select.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test parameter handling in socket_select(). +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$sockets = array(); +if (strtolower(substr(PHP_OS, 0, 3)) == 'win') { + $domain = AF_INET; +} else { + $domain = AF_UNIX; +} +socket_create_pair($domain, SOCK_STREAM, 0, $sockets); + +$write = null; +$except = null; +var_dump(socket_select($sockets, $write, $except, 0)); +--EXPECT-- +int(0) +--CREDITS-- +Till Klampaeckel, till@php.net +Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt b/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt new file mode 100644 index 0000000..bf95044 --- /dev/null +++ b/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt @@ -0,0 +1,57 @@ +--TEST-- +Test if socket_recvfrom() receives data sent by socket_sendto() via IPv4 UDP +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php + $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + if (!$socket) { + die('Unable to create AF_INET socket'); + } + if (!socket_set_nonblock($socket)) { + die('Unable to set nonblocking mode for socket'); + } + socket_recvfrom($socket, $buf, 12, 0, $from, $port); // cause warning + $address = '127.0.0.1'; + socket_sendto($socket, '', 1, 0, $address); // cause warning + if (!socket_bind($socket, $address, 1223)) { + die("Unable to bind to $address:1223"); + } + + $msg = "Ping!"; + $len = strlen($msg); + $bytes_sent = socket_sendto($socket, $msg, $len, 0, $address, 1223); + if ($bytes_sent == -1) { + die('An error occurred while sending to the socket'); + } else if ($bytes_sent != $len) { + die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected'); + } + + $from = ""; + $port = 0; + socket_recvfrom($socket, $buf, 12, 0); // cause warning + socket_recvfrom($socket, $buf, 12, 0, $from); // cause warning + $bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from, $port); + if ($bytes_received == -1) { + die('An error occurred while receiving from the socket'); + } else if ($bytes_received != $len) { + die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected'); + } + echo "Received $buf from remote address $from and remote port $port" . PHP_EOL; + + socket_close($socket); +--EXPECTF-- +Warning: socket_recvfrom(): unable to recvfrom [%d]: %a in %s on line %d + +Warning: Wrong parameter count for socket_sendto() in %s on line %d + +Warning: socket_recvfrom() expects at least 5 parameters, 4 given in %s on line %d + +Warning: Wrong parameter count for socket_recvfrom() in %s on line %d +Received Ping! from remote address 127.0.0.1 and remote port 1223 +--CREDITS-- +Falko Menge <mail at falko-menge dot de> +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt new file mode 100644 index 0000000..ec96509 --- /dev/null +++ b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt @@ -0,0 +1,62 @@ +--TEST-- +Test if socket_recvfrom() receives data sent by socket_sendto() via IPv6 UDP (Win32) +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +if (substr(PHP_OS, 0, 3) != 'WIN') { + die('skip only for Windows'); +} +require 'ipv6_skipif.inc'; +--FILE-- +<?php + $socket = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP); + if (!$socket) { + die('Unable to create AF_INET6 socket'); + } + if (!socket_set_nonblock($socket)) { + die('Unable to set nonblocking mode for socket'); + } + socket_recvfrom($socket, $buf, 12, 0, $from, $port); // cause warning + $address = '::1'; + socket_sendto($socket, '', 1, 0, $address); // cause warning + if (!socket_bind($socket, $address, 1223)) { + die("Unable to bind to $address:1223"); + } + + $msg = "Ping!"; + $len = strlen($msg); + $bytes_sent = socket_sendto($socket, $msg, $len, 0, $address, 1223); + if ($bytes_sent == -1) { + die('An error occurred while sending to the socket'); + } else if ($bytes_sent != $len) { + die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected'); + } + + $from = ""; + $port = 0; + socket_recvfrom($socket, $buf, 12, 0); // cause warning + socket_recvfrom($socket, $buf, 12, 0, $from); // cause warning + $bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from, $port); + if ($bytes_received == -1) { + die('An error occurred while receiving from the socket'); + } else if ($bytes_received != $len) { + die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected'); + } + echo "Received $buf from remote address $from and remote port $port" . PHP_EOL; + + socket_close($socket); +--EXPECTF-- +Warning: socket_recvfrom(): unable to recvfrom [10022]: An invalid argument was supplied. + in %s on line %d + +Warning: Wrong parameter count for socket_sendto() in %s on line %d + +Warning: socket_recvfrom() expects at least 5 parameters, 4 given in %s on line %d + +Warning: Wrong parameter count for socket_recvfrom() in %s on line %d +Received Ping! from remote address ::1 and remote port 1223 +--CREDITS-- +Falko Menge <mail at falko-menge dot de> +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt new file mode 100644 index 0000000..2beb808 --- /dev/null +++ b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt @@ -0,0 +1,61 @@ +--TEST-- +Test if socket_recvfrom() receives data sent by socket_sendto() via IPv6 UDP +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip Not valid for Windows'); +} +require 'ipv6_skipif.inc'; +--FILE-- +<?php + $socket = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP); + if (!$socket) { + die('Unable to create AF_INET6 socket'); + } + if (!socket_set_nonblock($socket)) { + die('Unable to set nonblocking mode for socket'); + } + socket_recvfrom($socket, $buf, 12, 0, $from, $port); // cause warning + $address = '::1'; + socket_sendto($socket, '', 1, 0, $address); // cause warning + if (!socket_bind($socket, $address, 1223)) { + die("Unable to bind to $address:1223"); + } + + $msg = "Ping!"; + $len = strlen($msg); + $bytes_sent = socket_sendto($socket, $msg, $len, 0, $address, 1223); + if ($bytes_sent == -1) { + die('An error occurred while sending to the socket'); + } else if ($bytes_sent != $len) { + die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected'); + } + + $from = ""; + $port = 0; + socket_recvfrom($socket, $buf, 12, 0); // cause warning + socket_recvfrom($socket, $buf, 12, 0, $from); // cause warning + $bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from, $port); + if ($bytes_received == -1) { + die('An error occurred while receiving from the socket'); + } else if ($bytes_received != $len) { + die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected'); + } + echo "Received $buf from remote address $from and remote port $port" . PHP_EOL; + + socket_close($socket); +--EXPECTF-- +Warning: socket_recvfrom(): unable to recvfrom [11]: Resource temporarily unavailable in %s on line %d + +Warning: Wrong parameter count for socket_sendto() in %s on line %d + +Warning: socket_recvfrom() expects at least 5 parameters, 4 given in %s on line %d + +Warning: Wrong parameter count for socket_recvfrom() in %s on line %d +Received Ping! from remote address ::1 and remote port 1223 +--CREDITS-- +Falko Menge <mail at falko-menge dot de> +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt b/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt new file mode 100644 index 0000000..55ad75c --- /dev/null +++ b/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test if socket_recvfrom() receives data sent by socket_sendto() through a Unix domain socket +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip.. Not valid for Windows'); +} +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php + $socket = socket_create(AF_UNIX, SOCK_DGRAM, SOL_UDP); // cause warning + $socket = socket_create(AF_UNIX, SOCK_DGRAM, 0); + if (!$socket) { + die('Unable to create AF_UNIX socket'); + } + if (!socket_set_nonblock($socket)) { + die('Unable to set nonblocking mode for socket'); + } + socket_recvfrom($socket, $buf, 12, 0, $from, $port); // cause warning + $address = sprintf("/tmp/%s.sock", uniqid()); + if (!socket_bind($socket, $address)) { + die("Unable to bind to $address"); + } + + $msg = "Ping!"; + $len = strlen($msg); + $bytes_sent = socket_sendto($socket, $msg, $len, 0); // cause warning + $bytes_sent = socket_sendto($socket, $msg, $len, 0, $address); + if ($bytes_sent == -1) { + @unlink($address); + die('An error occurred while sending to the socket'); + } else if ($bytes_sent != $len) { + @unlink($address); + die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected'); + } + + $from = ""; + var_dump(socket_recvfrom($socket, $buf, 0, 0, $from)); // expect false + $bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from); + if ($bytes_received == -1) { + @unlink($address); + die('An error occurred while receiving from the socket'); + } else if ($bytes_received != $len) { + @unlink($address); + die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected'); + } + echo "Received $buf"; + + socket_close($socket); + @unlink($address); +?> +--EXPECTF-- +Warning: socket_create(): Unable to create socket [%d]: Protocol not supported in %s on line %d + +Warning: socket_recvfrom(): unable to recvfrom [%d]: Resource temporarily unavailable in %s on line %d + +Warning: socket_sendto() expects at least 5 parameters, 4 given in %s on line %d +bool(false) +Received Ping! +--CREDITS-- +Falko Menge <mail at falko-menge dot de> +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_set_block-retval.phpt b/ext/sockets/tests/socket_set_block-retval.phpt new file mode 100644 index 0000000..2aa4b0e --- /dev/null +++ b/ext/sockets/tests/socket_set_block-retval.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test socket_set_block return values +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +?> +--FILE-- +<?php + +$socket = socket_create_listen(31339); +var_dump(socket_set_block($socket)); +socket_close($socket); + +$socket2 = socket_create_listen(31340); +socket_close($socket2); +var_dump(socket_set_block($socket2)); + +?> +--EXPECTF-- +bool(true) + +Warning: socket_set_block(): %d is not a valid Socket resource in %s on line %d +bool(false) +--CREDITS-- +Robin Mehner, robin@coding-robin.de +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_set_block-wrongparams.phpt b/ext/sockets/tests/socket_set_block-wrongparams.phpt new file mode 100644 index 0000000..7c80695 --- /dev/null +++ b/ext/sockets/tests/socket_set_block-wrongparams.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test if socket_set_block throws E_WARNING with wrong parameters. +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +?> +--FILE-- +<?php +socket_set_block(array()); +?> +--EXPECTF-- +Warning: socket_set_block() expects parameter 1 to be resource, array given in %s on line %d +--CREDITS-- +Robin Mehner, robin@coding-robin.de +PHP Testfest Berlin 2009-05-09 + diff --git a/ext/sockets/tests/socket_set_nonblock-retval.phpt b/ext/sockets/tests/socket_set_nonblock-retval.phpt new file mode 100644 index 0000000..b908618 --- /dev/null +++ b/ext/sockets/tests/socket_set_nonblock-retval.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test socket_set_nonblock return values +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +?> +--FILE-- +<?php + +$socket = socket_create_listen(31339); +var_dump(socket_set_nonblock($socket)); +socket_close($socket); + +$socket2 = socket_create_listen(31340); +socket_close($socket2); +var_dump(socket_set_nonblock($socket2)); + +?> +--EXPECTF-- +bool(true) + +Warning: socket_set_nonblock(): %d is not a valid Socket resource in %s on line %d +bool(false) +--CREDITS-- +Robin Mehner, robin@coding-robin.de +PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_set_nonblock-wrongparams.phpt b/ext/sockets/tests/socket_set_nonblock-wrongparams.phpt new file mode 100644 index 0000000..4b7e5be --- /dev/null +++ b/ext/sockets/tests/socket_set_nonblock-wrongparams.phpt @@ -0,0 +1,13 @@ +--TEST-- +Test if socket_set_nonblock throws E_WARNING with wrong parameters. +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP The sockets extension is not loaded.'); +} +--FILE-- +<?php +$socket = socket_set_nonblock(array()); +?> +--EXPECTF-- +Warning: socket_set_nonblock() expects parameter 1 to be resource, array given in %s on line %d diff --git a/ext/sockets/tests/socket_set_nonblock.phpt b/ext/sockets/tests/socket_set_nonblock.phpt new file mode 100644 index 0000000..55137d3 --- /dev/null +++ b/ext/sockets/tests/socket_set_nonblock.phpt @@ -0,0 +1,24 @@ +--TEST-- +ext/sockets - socket_set_block - basic test +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + $s_c_l = socket_create_listen(31330+$rand); + socket_set_nonblock($s_c_l); + var_dump($s_c_l); + #socket_accept($s_c_l); + socket_close($s_c_l); +?> + +--EXPECTF-- +resource(%i) of type (Socket) + diff --git a/ext/sockets/tests/socket_set_option_error_socket_option.phpt b/ext/sockets/tests/socket_set_option_error_socket_option.phpt new file mode 100644 index 0000000..eaa0e64 --- /dev/null +++ b/ext/sockets/tests/socket_set_option_error_socket_option.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test if socket_set_option() returns 'unable to set socket option' failure for invalid options +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +$filename = dirname(__FILE__) . '/006_root_check.tmp'; +$fp = fopen($filename, 'w'); +fclose($fp); +if (fileowner($filename) == 0) { + unlink ($filename); + die('SKIP Test cannot be run as root.'); +} +?> +--FILE-- +<?php +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +if (!$socket) { + die('Unable to create AF_INET socket [socket]'); +} + +socket_set_option( $socket, SOL_SOCKET, 1, 1); +socket_close($socket); +?> +--CLEAN-- +<?php +unlink(dirname(__FILE__) . '/006_root_check.tmp'); +--EXPECTF-- +Warning: socket_set_option(): unable to set socket option [%d]: Permission denied in %s on line %d +--CREDITS-- +Moritz Neuhaeuser, info@xcompile.net +PHP Testfest Berlin 2009-05-10 diff --git a/ext/sockets/tests/socket_set_option_rcvtimeo.phpt b/ext/sockets/tests/socket_set_option_rcvtimeo.phpt new file mode 100644 index 0000000..ea14fd3 --- /dev/null +++ b/ext/sockets/tests/socket_set_option_rcvtimeo.phpt @@ -0,0 +1,39 @@ +--TEST-- +Test if socket_set_option() works, option:SO_RCVTIMEO +--DESCRIPTION-- +-wrong params +-set/get params comparison +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +?> +--FILE-- +<?php +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +if (!$socket) { + die('Unable to create AF_INET socket [socket]'); +} +socket_set_block($socket); + +//wrong params +$retval_1 = socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, array()); + +//set/get comparison +$options = array("sec" => 1, "usec" => 0); +$retval_2 = socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, $options); +$retval_3 = socket_get_option( $socket, SOL_SOCKET, SO_RCVTIMEO); + +var_dump($retval_2); +var_dump($retval_3 === $options); +socket_close($socket); +?> + +--EXPECTF-- +Warning: socket_set_option(): no key "sec" passed in optval in %s on line %d +bool(true) +bool(true) +--CREDITS-- +Moritz Neuhaeuser, info@xcompile.net +PHP Testfest Berlin 2009-05-10 diff --git a/ext/sockets/tests/socket_set_option_seolinger.phpt b/ext/sockets/tests/socket_set_option_seolinger.phpt new file mode 100644 index 0000000..36606b4 --- /dev/null +++ b/ext/sockets/tests/socket_set_option_seolinger.phpt @@ -0,0 +1,50 @@ +--TEST-- +Test if socket_set_option() works, option:SO_SEOLINGER +--DESCRIPTION-- +-wrong params +-set/get params comparison +-l_linger not given +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +?> +--FILE-- +<?php +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + +if (!$socket) { + die('Unable to create AF_INET socket [socket]'); +} +// wrong params +$retval_1 = socket_set_option( $socket, SOL_SOCKET, SO_LINGER, array()); + +// set/get comparison +$options = array("l_onoff" => 1, "l_linger" => 1); +$retval_2 = socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options); +$retval_3 = socket_get_option( $socket, SOL_SOCKET, SO_LINGER); + +//l_linger not given +$options_2 = array("l_onoff" => 1); +var_dump(socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_2)); + +var_dump($retval_2); +var_dump($retval_3["l_linger"] === $options["l_linger"]); +// value of l_onoff is not always 1, Darwin returns 128 +var_dump((bool)$retval_3["l_onoff"] === (bool)$options["l_onoff"]); + +socket_close($socket); +?> + +--EXPECTF-- +Warning: socket_set_option(): no key "l_onoff" passed in optval in %s on line %d + +Warning: socket_set_option(): no key "l_linger" passed in optval in %s on line %d +bool(false) +bool(true) +bool(true) +bool(true) +--CREDITS-- +Moritz Neuhaeuser, info@xcompile.net +PHP Testfest Berlin 2009-05-10 diff --git a/ext/sockets/tests/socket_set_option_sndtimeo.phpt b/ext/sockets/tests/socket_set_option_sndtimeo.phpt new file mode 100644 index 0000000..6fd008c --- /dev/null +++ b/ext/sockets/tests/socket_set_option_sndtimeo.phpt @@ -0,0 +1,39 @@ +--TEST-- +Test if socket_set_option() works, option:SO_SNDTIMEO +--DESCRIPTION-- +-wrong params +-set/get params comparison +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +?> +--FILE-- +<?php +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +if (!$socket) { + die('Unable to create AF_INET socket [socket]'); +} +socket_set_block($socket); + +//wrong params +$retval_1 = socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, array()); + +//set/get comparison +$options = array("sec" => 1, "usec" => 0); +$retval_2 = socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, $options); +$retval_3 = socket_get_option( $socket, SOL_SOCKET, SO_SNDTIMEO); + +var_dump($retval_2); +var_dump($retval_3 === $options); +socket_close($socket); +?> + +--EXPECTF-- +Warning: socket_set_option(): no key "sec" passed in optval in %s on line %d +bool(true) +bool(true) +--CREDITS-- +Moritz Neuhaeuser, info@xcompile.net +PHP Testfest Berlin 2009-05-10 diff --git a/ext/sockets/tests/socket_strerror.phpt b/ext/sockets/tests/socket_strerror.phpt new file mode 100644 index 0000000..fb9925e --- /dev/null +++ b/ext/sockets/tests/socket_strerror.phpt @@ -0,0 +1,157 @@ +--TEST-- +ext/sockets - socket_strerror - basic test +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets') || !function_exists('socket_strerror')) { + die('skip sockets extension not available.'); + } + if (!stristr(PHP_OS, "Linux")) { + die('skip - test validates linux error strings only.'); + } +?> +--FILE-- +<?php + $s_s = socket_strerror(); + for ($i=0;$i<=132;$i++) { + var_dump(socket_strerror($i)); + } +?> +--EXPECTF-- + +Warning: socket_strerror() expects exactly 1 parameter, 0 given in %s on line %i +string(7) "Success" +string(23) "Operation not permitted" +string(25) "No such file or directory" +string(15) "No such process" +string(23) "Interrupted system call" +string(18) "Input/output error" +string(25) "No such device or address" +string(22) "Argument list too long" +string(17) "Exec format error" +string(19) "Bad file descriptor" +string(18) "No child processes" +string(32) "Resource temporarily unavailable" +string(22) "Cannot allocate memory" +string(17) "Permission denied" +string(11) "Bad address" +string(21) "Block device required" +string(23) "Device or resource busy" +string(11) "File exists" +string(25) "Invalid cross-device link" +string(14) "No such device" +string(15) "Not a directory" +string(14) "Is a directory" +string(16) "Invalid argument" +string(29) "Too many open files in system" +string(19) "Too many open files" +string(30) "Inappropriate ioctl for device" +string(14) "Text file busy" +string(14) "File too large" +string(23) "No space left on device" +string(12) "Illegal seek" +string(21) "Read-only file system" +string(14) "Too many links" +string(11) "Broken pipe" +string(32) "Numerical argument out of domain" +string(29) "Numerical result out of range" +string(25) "Resource deadlock avoided" +string(18) "File name too long" +string(18) "No locks available" +string(24) "Function not implemented" +string(19) "Directory not empty" +string(33) "Too many levels of symbolic links" +string(16) "Unknown error 41" +string(26) "No message of desired type" +string(18) "Identifier removed" +string(27) "Channel number out of range" +string(24) "Level 2 not synchronized" +string(14) "Level 3 halted" +string(13) "Level 3 reset" +string(24) "Link number out of range" +string(28) "Protocol driver not attached" +string(26) "No CSI structure available" +string(14) "Level 2 halted" +string(16) "Invalid exchange" +string(26) "Invalid request descriptor" +string(13) "Exchange full" +string(8) "No anode" +string(20) "Invalid request code" +string(12) "Invalid slot" +string(16) "Unknown error 58" +string(20) "Bad font file format" +string(19) "Device not a stream" +string(17) "No data available" +string(13) "Timer expired" +string(24) "Out of streams resources" +string(29) "Machine is not on the network" +string(21) "Package not installed" +string(16) "Object is remote" +string(21) "Link has been severed" +string(15) "Advertise error" +string(13) "Srmount error" +string(27) "Communication error on send" +string(14) "Protocol error" +string(18) "Multihop attempted" +string(18) "RFS specific error" +string(11) "Bad message" +string(37) "Value too large for defined data type" +string(26) "Name not unique on network" +string(28) "File descriptor in bad state" +string(22) "Remote address changed" +string(38) "Can not access a needed shared library" +string(36) "Accessing a corrupted shared library" +string(31) ".lib section in a.out corrupted" +string(47) "Attempting to link in too many shared libraries" +string(37) "Cannot exec a shared library directly" +string(49) "Invalid or incomplete multibyte or wide character" +string(43) "Interrupted system call should be restarted" +string(18) "Streams pipe error" +string(14) "Too many users" +string(30) "Socket operation on non-socket" +string(28) "Destination address required" +string(16) "Message too long" +string(30) "Protocol wrong type for socket" +string(22) "Protocol not available" +string(22) "Protocol not supported" +string(25) "Socket type not supported" +string(23) "Operation not supported" +string(29) "Protocol family not supported" +string(40) "Address family not supported by protocol" +string(22) "Address already in use" +string(31) "Cannot assign requested address" +string(15) "Network is down" +string(22) "Network is unreachable" +string(35) "Network dropped connection on reset" +string(32) "Software caused connection abort" +string(24) "Connection reset by peer" +string(25) "No buffer space available" +string(39) "Transport endpoint is already connected" +string(35) "Transport endpoint is not connected" +string(45) "Cannot send after transport endpoint shutdown" +string(34) "Too many references: cannot splice" +string(20) "Connection timed out" +string(18) "Connection refused" +string(12) "Host is down" +string(16) "No route to host" +string(29) "Operation already in progress" +string(25) "Operation now in progress" +string(%d) "Stale%sfile handle" +string(24) "Structure needs cleaning" +string(27) "Not a XENIX named type file" +string(29) "No XENIX semaphores available" +string(20) "Is a named type file" +string(16) "Remote I/O error" +string(19) "Disk quota exceeded" +string(15) "No medium found" +string(17) "Wrong medium type" +string(18) "Operation canceled" +string(26) "Required key not available" +string(15) "Key has expired" +string(20) "Key has been revoked" +string(27) "Key was rejected by service" +string(10) "Owner died" +string(21) "State not recoverable" +string(%d) "%s" diff --git a/ext/sockets/tests/socket_write_params.phpt b/ext/sockets/tests/socket_write_params.phpt new file mode 100644 index 0000000..00360f7 --- /dev/null +++ b/ext/sockets/tests/socket_write_params.phpt @@ -0,0 +1,28 @@ +--TEST-- +ext/sockets - socket_write - test with empty parameters +--CREDITS-- +Florian Anderiasch +fa@php.net +--SKIPIF-- +<?php + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $rand = rand(1,999); + // wrong parameter count + $s_w = socket_write(); + $s_c = socket_create_listen(31330+$rand); + $s_w = socket_write($s_c); + $s_w = socket_write($s_c, "foo"); + socket_close($s_c); +?> +--EXPECTF-- + +Warning: socket_write() expects at least 2 parameters, 0 given in %s on line %i + +Warning: socket_write() expects at least 2 parameters, 1 given in %s on line %i + +Warning: socket_write(): unable to write to socket [%i]: %a in %s on line %i diff --git a/ext/sockets/tests/unixloop.phpt b/ext/sockets/tests/unixloop.phpt new file mode 100644 index 0000000..4a19444 --- /dev/null +++ b/ext/sockets/tests/unixloop.phpt @@ -0,0 +1,58 @@ +--TEST-- +Unix domain socket Loopback test +--SKIPIF-- +<?php +if (substr(PHP_OS, 0, 3) == 'WIN') { + die('skip.. Not valid for Windows'); +} + if (!extension_loaded('sockets')) { + die('skip sockets extension not available.'); + } +?> +--FILE-- +<?php + $sock_path = sprintf("/tmp/%s.sock", uniqid()); + + if (file_exists($sock_path)) + die('Temporary socket already exists.'); + + /* Setup socket server */ + $server = socket_create(AF_UNIX, SOCK_STREAM, 0); + if (!$server) { + die('Unable to create AF_UNIX socket [server]'); + } + if (!socket_bind($server, $sock_path)) { + die("Unable to bind to $sock_path"); + } + if (!socket_listen($server, 2)) { + die('Unable to listen on socket'); + } + + /* Connect to it */ + $client = socket_create(AF_UNIX, SOCK_STREAM, 0); + if (!$client) { + die('Unable to create AF_UNIX socket [client]'); + } + if (!socket_connect($client, $sock_path)) { + die('Unable to connect to server socket'); + } + + /* Accept that connection */ + $socket = socket_accept($server); + if (!$socket) { + die('Unable to accept connection'); + } + + socket_write($client, "ABCdef123\n"); + + $data = socket_read($socket, 10, PHP_BINARY_READ); + var_dump($data); + + socket_close($client); + socket_close($socket); + socket_close($server); + @unlink($sock_path); +?> +--EXPECT-- +string(10) "ABCdef123 +" diff --git a/ext/sockets/unix_socket_constants.h b/ext/sockets/unix_socket_constants.h new file mode 100644 index 0000000..fb190d8 --- /dev/null +++ b/ext/sockets/unix_socket_constants.h @@ -0,0 +1,426 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Jason Greene <jason@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* This file is to be included by sockets.c */ + +#ifdef EPERM + /* Operation not permitted */ + REGISTER_LONG_CONSTANT("SOCKET_EPERM", EPERM, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOENT + /* No such file or directory */ + REGISTER_LONG_CONSTANT("SOCKET_ENOENT", ENOENT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EINTR + /* Interrupted system call */ + REGISTER_LONG_CONSTANT("SOCKET_EINTR", EINTR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EIO + /* I/O error */ + REGISTER_LONG_CONSTANT("SOCKET_EIO", EIO, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENXIO + /* No such device or address */ + REGISTER_LONG_CONSTANT("SOCKET_ENXIO", ENXIO, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef E2BIG + /* Arg list too long */ + REGISTER_LONG_CONSTANT("SOCKET_E2BIG", E2BIG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADF + /* Bad file number */ + REGISTER_LONG_CONSTANT("SOCKET_EBADF", EBADF, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EAGAIN + /* Try again */ + REGISTER_LONG_CONSTANT("SOCKET_EAGAIN", EAGAIN, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOMEM + /* Out of memory */ + REGISTER_LONG_CONSTANT("SOCKET_ENOMEM", ENOMEM, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EACCES + /* Permission denied */ + REGISTER_LONG_CONSTANT("SOCKET_EACCES", EACCES, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EFAULT + /* Bad address */ + REGISTER_LONG_CONSTANT("SOCKET_EFAULT", EFAULT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTBLK + /* Block device required */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTBLK", ENOTBLK, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBUSY + /* Device or resource busy */ + REGISTER_LONG_CONSTANT("SOCKET_EBUSY", EBUSY, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EEXIST + /* File exists */ + REGISTER_LONG_CONSTANT("SOCKET_EEXIST", EEXIST, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EXDEV + /* Cross-device link */ + REGISTER_LONG_CONSTANT("SOCKET_EXDEV", EXDEV, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENODEV + /* No such device */ + REGISTER_LONG_CONSTANT("SOCKET_ENODEV", ENODEV, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTDIR + /* Not a directory */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTDIR", ENOTDIR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EISDIR + /* Is a directory */ + REGISTER_LONG_CONSTANT("SOCKET_EISDIR", EISDIR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EINVAL + /* Invalid argument */ + REGISTER_LONG_CONSTANT("SOCKET_EINVAL", EINVAL, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENFILE + /* File table overflow */ + REGISTER_LONG_CONSTANT("SOCKET_ENFILE", ENFILE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EMFILE + /* Too many open files */ + REGISTER_LONG_CONSTANT("SOCKET_EMFILE", EMFILE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTTY + /* Not a typewriter */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTTY", ENOTTY, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOSPC + /* No space left on device */ + REGISTER_LONG_CONSTANT("SOCKET_ENOSPC", ENOSPC, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ESPIPE + /* Illegal seek */ + REGISTER_LONG_CONSTANT("SOCKET_ESPIPE", ESPIPE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EROFS + /* Read-only file system */ + REGISTER_LONG_CONSTANT("SOCKET_EROFS", EROFS, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EMLINK + /* Too many links */ + REGISTER_LONG_CONSTANT("SOCKET_EMLINK", EMLINK, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EPIPE + /* Broken pipe */ + REGISTER_LONG_CONSTANT("SOCKET_EPIPE", EPIPE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENAMETOOLONG + /* File name too long */ + REGISTER_LONG_CONSTANT("SOCKET_ENAMETOOLONG", ENAMETOOLONG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOLCK + /* No record locks available */ + REGISTER_LONG_CONSTANT("SOCKET_ENOLCK", ENOLCK, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOSYS + /* Function not implemented */ + REGISTER_LONG_CONSTANT("SOCKET_ENOSYS", ENOSYS, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTEMPTY + /* Directory not empty */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTEMPTY", ENOTEMPTY, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ELOOP + /* Too many symbolic links encountered */ + REGISTER_LONG_CONSTANT("SOCKET_ELOOP", ELOOP, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EWOULDBLOCK + /* Operation would block */ + REGISTER_LONG_CONSTANT("SOCKET_EWOULDBLOCK", EWOULDBLOCK, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOMSG + /* No message of desired type */ + REGISTER_LONG_CONSTANT("SOCKET_ENOMSG", ENOMSG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EIDRM + /* Identifier removed */ + REGISTER_LONG_CONSTANT("SOCKET_EIDRM", EIDRM, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ECHRNG + /* Channel number out of range */ + REGISTER_LONG_CONSTANT("SOCKET_ECHRNG", ECHRNG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EL2NSYNC + /* Level 2 not synchronized */ + REGISTER_LONG_CONSTANT("SOCKET_EL2NSYNC", EL2NSYNC, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EL3HLT + /* Level 3 halted */ + REGISTER_LONG_CONSTANT("SOCKET_EL3HLT", EL3HLT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EL3RST + /* Level 3 reset */ + REGISTER_LONG_CONSTANT("SOCKET_EL3RST", EL3RST, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ELNRNG + /* Link number out of range */ + REGISTER_LONG_CONSTANT("SOCKET_ELNRNG", ELNRNG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EUNATCH + /* Protocol driver not attached */ + REGISTER_LONG_CONSTANT("SOCKET_EUNATCH", EUNATCH, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOCSI + /* No CSI structure available */ + REGISTER_LONG_CONSTANT("SOCKET_ENOCSI", ENOCSI, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EL2HLT + /* Level 2 halted */ + REGISTER_LONG_CONSTANT("SOCKET_EL2HLT", EL2HLT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADE + /* Invalid exchange */ + REGISTER_LONG_CONSTANT("SOCKET_EBADE", EBADE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADR + /* Invalid request descriptor */ + REGISTER_LONG_CONSTANT("SOCKET_EBADR", EBADR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EXFULL + /* Exchange full */ + REGISTER_LONG_CONSTANT("SOCKET_EXFULL", EXFULL, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOANO + /* No anode */ + REGISTER_LONG_CONSTANT("SOCKET_ENOANO", ENOANO, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADRQC + /* Invalid request code */ + REGISTER_LONG_CONSTANT("SOCKET_EBADRQC", EBADRQC, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADSLT + /* Invalid slot */ + REGISTER_LONG_CONSTANT("SOCKET_EBADSLT", EBADSLT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOSTR + /* Device not a stream */ + REGISTER_LONG_CONSTANT("SOCKET_ENOSTR", ENOSTR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENODATA + /* No data available */ + REGISTER_LONG_CONSTANT("SOCKET_ENODATA", ENODATA, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ETIME + /* Timer expired */ + REGISTER_LONG_CONSTANT("SOCKET_ETIME", ETIME, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOSR + /* Out of streams resources */ + REGISTER_LONG_CONSTANT("SOCKET_ENOSR", ENOSR, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENONET + /* Machine is not on the network */ + REGISTER_LONG_CONSTANT("SOCKET_ENONET", ENONET, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EREMOTE + /* Object is remote */ + REGISTER_LONG_CONSTANT("SOCKET_EREMOTE", EREMOTE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOLINK + /* Link has been severed */ + REGISTER_LONG_CONSTANT("SOCKET_ENOLINK", ENOLINK, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EADV + /* Advertise error */ + REGISTER_LONG_CONSTANT("SOCKET_EADV", EADV, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ESRMNT + /* Srmount error */ + REGISTER_LONG_CONSTANT("SOCKET_ESRMNT", ESRMNT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ECOMM + /* Communication error on send */ + REGISTER_LONG_CONSTANT("SOCKET_ECOMM", ECOMM, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EPROTO + /* Protocol error */ + REGISTER_LONG_CONSTANT("SOCKET_EPROTO", EPROTO, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EMULTIHOP + /* Multihop attempted */ + REGISTER_LONG_CONSTANT("SOCKET_EMULTIHOP", EMULTIHOP, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADMSG + /* Not a data message */ + REGISTER_LONG_CONSTANT("SOCKET_EBADMSG", EBADMSG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTUNIQ + /* Name not unique on network */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTUNIQ", ENOTUNIQ, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EBADFD + /* File descriptor in bad state */ + REGISTER_LONG_CONSTANT("SOCKET_EBADFD", EBADFD, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EREMCHG + /* Remote address changed */ + REGISTER_LONG_CONSTANT("SOCKET_EREMCHG", EREMCHG, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ERESTART + /* Interrupted system call should be restarted */ + REGISTER_LONG_CONSTANT("SOCKET_ERESTART", ERESTART, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ESTRPIPE + /* Streams pipe error */ + REGISTER_LONG_CONSTANT("SOCKET_ESTRPIPE", ESTRPIPE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EUSERS + /* Too many users */ + REGISTER_LONG_CONSTANT("SOCKET_EUSERS", EUSERS, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTSOCK + /* Socket operation on non-socket */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTSOCK", ENOTSOCK, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EDESTADDRREQ + /* Destination address required */ + REGISTER_LONG_CONSTANT("SOCKET_EDESTADDRREQ", EDESTADDRREQ, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EMSGSIZE + /* Message too long */ + REGISTER_LONG_CONSTANT("SOCKET_EMSGSIZE", EMSGSIZE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EPROTOTYPE + /* Protocol wrong type for socket */ + REGISTER_LONG_CONSTANT("SOCKET_EPROTOTYPE", EPROTOTYPE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOPROTOOPT + /* Protocol not available */ + REGISTER_LONG_CONSTANT("SOCKET_ENOPROTOOPT", ENOPROTOOPT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EPROTONOSUPPORT + /* Protocol not supported */ + REGISTER_LONG_CONSTANT("SOCKET_EPROTONOSUPPORT", EPROTONOSUPPORT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ESOCKTNOSUPPORT + /* Socket type not supported */ + REGISTER_LONG_CONSTANT("SOCKET_ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EOPNOTSUPP + /* Operation not supported on transport endpoint */ + REGISTER_LONG_CONSTANT("SOCKET_EOPNOTSUPP", EOPNOTSUPP, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EPFNOSUPPORT + /* Protocol family not supported */ + REGISTER_LONG_CONSTANT("SOCKET_EPFNOSUPPORT", EPFNOSUPPORT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EAFNOSUPPORT + /* Address family not supported by protocol */ + REGISTER_LONG_CONSTANT("SOCKET_EAFNOSUPPORT", EAFNOSUPPORT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EADDRINUSE + /* Address already in use */ + REGISTER_LONG_CONSTANT("SOCKET_EADDRINUSE", EADDRINUSE, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EADDRNOTAVAIL + /* Cannot assign requested address */ + REGISTER_LONG_CONSTANT("SOCKET_EADDRNOTAVAIL", EADDRNOTAVAIL, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENETDOWN + /* Network is down */ + REGISTER_LONG_CONSTANT("SOCKET_ENETDOWN", ENETDOWN, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENETUNREACH + /* Network is unreachable */ + REGISTER_LONG_CONSTANT("SOCKET_ENETUNREACH", ENETUNREACH, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENETRESET + /* Network dropped connection because of reset */ + REGISTER_LONG_CONSTANT("SOCKET_ENETRESET", ENETRESET, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ECONNABORTED + /* Software caused connection abort */ + REGISTER_LONG_CONSTANT("SOCKET_ECONNABORTED", ECONNABORTED, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ECONNRESET + /* Connection reset by peer */ + REGISTER_LONG_CONSTANT("SOCKET_ECONNRESET", ECONNRESET, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOBUFS + /* No buffer space available */ + REGISTER_LONG_CONSTANT("SOCKET_ENOBUFS", ENOBUFS, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EISCONN + /* Transport endpoint is already connected */ + REGISTER_LONG_CONSTANT("SOCKET_EISCONN", EISCONN, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOTCONN + /* Transport endpoint is not connected */ + REGISTER_LONG_CONSTANT("SOCKET_ENOTCONN", ENOTCONN, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ESHUTDOWN + /* Cannot send after transport endpoint shutdown */ + REGISTER_LONG_CONSTANT("SOCKET_ESHUTDOWN", ESHUTDOWN, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ETOOMANYREFS + /* Too many references: cannot splice */ + REGISTER_LONG_CONSTANT("SOCKET_ETOOMANYREFS", ETOOMANYREFS, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ETIMEDOUT + /* Connection timed out */ + REGISTER_LONG_CONSTANT("SOCKET_ETIMEDOUT", ETIMEDOUT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ECONNREFUSED + /* Connection refused */ + REGISTER_LONG_CONSTANT("SOCKET_ECONNREFUSED", ECONNREFUSED, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EHOSTDOWN + /* Host is down */ + REGISTER_LONG_CONSTANT("SOCKET_EHOSTDOWN", EHOSTDOWN, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EHOSTUNREACH + /* No route to host */ + REGISTER_LONG_CONSTANT("SOCKET_EHOSTUNREACH", EHOSTUNREACH, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EALREADY + /* Operation already in progress */ + REGISTER_LONG_CONSTANT("SOCKET_EALREADY", EALREADY, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EINPROGRESS + /* Operation now in progress */ + REGISTER_LONG_CONSTANT("SOCKET_EINPROGRESS", EINPROGRESS, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EISNAM + /* Is a named type file */ + REGISTER_LONG_CONSTANT("SOCKET_EISNAM", EISNAM, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EREMOTEIO + /* Remote I/O error */ + REGISTER_LONG_CONSTANT("SOCKET_EREMOTEIO", EREMOTEIO, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EDQUOT + /* Quota exceeded */ + REGISTER_LONG_CONSTANT("SOCKET_EDQUOT", EDQUOT, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef ENOMEDIUM + /* No medium found */ + REGISTER_LONG_CONSTANT("SOCKET_ENOMEDIUM", ENOMEDIUM, CONST_CS | CONST_PERSISTENT); +#endif +#ifdef EMEDIUMTYPE + /* Wrong medium type */ + REGISTER_LONG_CONSTANT("SOCKET_EMEDIUMTYPE", EMEDIUMTYPE, CONST_CS | CONST_PERSISTENT); +#endif diff --git a/ext/sockets/win32_socket_constants.h b/ext/sockets/win32_socket_constants.h new file mode 100644 index 0000000..542347d --- /dev/null +++ b/ext/sockets/win32_socket_constants.h @@ -0,0 +1,74 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Jason Greene <jason@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +/* This file is to be included by sockets.c */ + +REGISTER_LONG_CONSTANT("SOCKET_EINTR", WSAEINTR, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EBADF", WSAEBADF, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EACCES", WSAEACCES, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EFAULT", WSAEFAULT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EINVAL", WSAEINVAL, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EMFILE", WSAEMFILE, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EWOULDBLOCK", WSAEWOULDBLOCK, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EINPROGRESS", WSAEINPROGRESS, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EALREADY", WSAEALREADY, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENOTSOCK", WSAENOTSOCK, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EDESTADDRREQ", WSAEDESTADDRREQ, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EMSGSIZE", WSAEMSGSIZE, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EPROTOTYPE", WSAEPROTOTYPE, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENOPROTOOPT", WSAENOPROTOOPT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EPROTONOSUPPORT", WSAEPROTONOSUPPORT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ESOCKTNOSUPPORT", WSAESOCKTNOSUPPORT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EOPNOTSUPP", WSAEOPNOTSUPP, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EPFNOSUPPORT", WSAEPFNOSUPPORT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EAFNOSUPPORT", WSAEAFNOSUPPORT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EADDRINUSE", WSAEADDRINUSE, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EADDRNOTAVAIL", WSAEADDRNOTAVAIL, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENETDOWN", WSAENETDOWN, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENETUNREACH", WSAENETUNREACH, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENETRESET", WSAENETRESET, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ECONNABORTED", WSAECONNABORTED, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ECONNRESET", WSAECONNRESET, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENOBUFS", WSAENOBUFS, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EISCONN", WSAEISCONN, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENOTCONN", WSAENOTCONN, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ESHUTDOWN", WSAESHUTDOWN, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ETOOMANYREFS", WSAETOOMANYREFS, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ETIMEDOUT", WSAETIMEDOUT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ECONNREFUSED", WSAECONNREFUSED, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ELOOP", WSAELOOP, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENAMETOOLONG", WSAENAMETOOLONG, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EHOSTDOWN", WSAEHOSTDOWN, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EHOSTUNREACH", WSAEHOSTUNREACH, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ENOTEMPTY", WSAENOTEMPTY, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EPROCLIM", WSAEPROCLIM, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EUSERS", WSAEUSERS, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EDQUOT", WSAEDQUOT, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_ESTALE", WSAESTALE, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EREMOTE", WSAEREMOTE, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_EDISCON", WSAEDISCON, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_SYSNOTREADY", WSASYSNOTREADY, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_VERNOTSUPPORTED", WSAVERNOTSUPPORTED, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_NOTINITIALISED", WSANOTINITIALISED, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_HOST_NOT_FOUND", WSAHOST_NOT_FOUND, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_TRY_AGAIN", WSATRY_AGAIN, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_NO_RECOVERY", WSANO_RECOVERY, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_NO_DATA", WSANO_DATA, CONST_CS | CONST_PERSISTENT); +REGISTER_LONG_CONSTANT("SOCKET_NO_ADDRESS", WSANO_ADDRESS, CONST_CS | CONST_PERSISTENT); |