summaryrefslogtreecommitdiff
path: root/ext/sockets
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sockets')
-rw-r--r--ext/sockets/CREDITS2
-rw-r--r--ext/sockets/config.m448
-rw-r--r--ext/sockets/config.w3217
-rw-r--r--ext/sockets/multicast.c545
-rw-r--r--ext/sockets/multicast.h92
-rw-r--r--ext/sockets/package.xml66
-rw-r--r--ext/sockets/php_sockets.h90
-rw-r--r--ext/sockets/sockets.c2599
-rw-r--r--ext/sockets/sockets.dsp117
-rw-r--r--ext/sockets/tests/bug46360.phpt17
-rw-r--r--ext/sockets/tests/bug49341.phpt15
-rw-r--r--ext/sockets/tests/bug51958.phpt22
-rw-r--r--ext/sockets/tests/bug63000.phpt22
-rw-r--r--ext/sockets/tests/ipv4loop.phpt49
-rw-r--r--ext/sockets/tests/ipv6_skipif.inc6
-rw-r--r--ext/sockets/tests/ipv6loop.phpt50
-rw-r--r--ext/sockets/tests/mcast_helpers.php.inc8
-rw-r--r--ext/sockets/tests/mcast_ipv4_recv.phpt197
-rw-r--r--ext/sockets/tests/mcast_ipv4_send.phpt65
-rw-r--r--ext/sockets/tests/mcast_ipv4_send_error.phpt79
-rw-r--r--ext/sockets/tests/mcast_ipv6_recv.phpt223
-rw-r--r--ext/sockets/tests/mcast_ipv6_recv_limited.phpt131
-rw-r--r--ext/sockets/tests/mcast_ipv6_send.phpt70
-rw-r--r--ext/sockets/tests/socket_accept-wrongparams.phpt16
-rw-r--r--ext/sockets/tests/socket_bind.phpt41
-rw-r--r--ext/sockets/tests/socket_bind_params.phpt29
-rw-r--r--ext/sockets/tests/socket_close_params.phpt21
-rw-r--r--ext/sockets/tests/socket_connect_error.phpt33
-rw-r--r--ext/sockets/tests/socket_connect_params.phpt33
-rw-r--r--ext/sockets/tests/socket_create_listen-nobind.phpt25
-rw-r--r--ext/sockets/tests/socket_create_listen-win32.phpt21
-rw-r--r--ext/sockets/tests/socket_create_listen-wrongparams.phpt18
-rw-r--r--ext/sockets/tests/socket_create_listen.phpt21
-rw-r--r--ext/sockets/tests/socket_create_listen_params.phpt23
-rw-r--r--ext/sockets/tests/socket_create_listen_used.phpt30
-rw-r--r--ext/sockets/tests/socket_create_pair-wrongparams-win32.phpt38
-rw-r--r--ext/sockets/tests/socket_create_pair-wrongparams.phpt44
-rw-r--r--ext/sockets/tests/socket_create_pair.phpt24
-rw-r--r--ext/sockets/tests/socket_create_params.phpt24
-rw-r--r--ext/sockets/tests/socket_getpeername.phpt33
-rw-r--r--ext/sockets/tests/socket_getpeername_ipv4loop.phpt59
-rw-r--r--ext/sockets/tests/socket_getpeername_ipv6loop.phpt60
-rw-r--r--ext/sockets/tests/socket_getsockname.phpt32
-rw-r--r--ext/sockets/tests/socket_import_stream-1.phpt26
-rw-r--r--ext/sockets/tests/socket_import_stream-2.phpt49
-rw-r--r--ext/sockets/tests/socket_import_stream-3.phpt46
-rw-r--r--ext/sockets/tests/socket_import_stream-4-win.phpt103
-rw-r--r--ext/sockets/tests/socket_import_stream-4.phpt100
-rw-r--r--ext/sockets/tests/socket_import_stream-5.phpt23
-rw-r--r--ext/sockets/tests/socket_listen-wrongparams.phpt24
-rw-r--r--ext/sockets/tests/socket_listen_params.phpt21
-rw-r--r--ext/sockets/tests/socket_read_params.phpt28
-rw-r--r--ext/sockets/tests/socket_select-wrongparams-1-win32.phpt25
-rw-r--r--ext/sockets/tests/socket_select-wrongparams-1.phpt26
-rw-r--r--ext/sockets/tests/socket_select-wrongparams-2.phpt23
-rw-r--r--ext/sockets/tests/socket_select-wrongparams-3.phpt28
-rw-r--r--ext/sockets/tests/socket_select-wrongparams-4.phpt29
-rw-r--r--ext/sockets/tests/socket_select.phpt25
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt57
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt62
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt61
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_unix.phpt64
-rw-r--r--ext/sockets/tests/socket_set_block-retval.phpt28
-rw-r--r--ext/sockets/tests/socket_set_block-wrongparams.phpt18
-rw-r--r--ext/sockets/tests/socket_set_nonblock-retval.phpt28
-rw-r--r--ext/sockets/tests/socket_set_nonblock-wrongparams.phpt13
-rw-r--r--ext/sockets/tests/socket_set_nonblock.phpt24
-rw-r--r--ext/sockets/tests/socket_set_option_error_socket_option.phpt33
-rw-r--r--ext/sockets/tests/socket_set_option_rcvtimeo.phpt39
-rw-r--r--ext/sockets/tests/socket_set_option_seolinger.phpt50
-rw-r--r--ext/sockets/tests/socket_set_option_sndtimeo.phpt39
-rw-r--r--ext/sockets/tests/socket_strerror.phpt157
-rw-r--r--ext/sockets/tests/socket_write_params.phpt28
-rw-r--r--ext/sockets/tests/unixloop.phpt58
-rw-r--r--ext/sockets/unix_socket_constants.h426
-rw-r--r--ext/sockets/win32_socket_constants.h74
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);