]> granicus.if.org Git - php/commitdiff
update sockets to work with winsock as well
authorDaniel Beulshausen <dbeu@php.net>
Thu, 17 May 2001 17:02:37 +0000 (17:02 +0000)
committerDaniel Beulshausen <dbeu@php.net>
Thu, 17 May 2001 17:02:37 +0000 (17:02 +0000)
ext/sockets/CREDITS
ext/sockets/php_sockets.h
ext/sockets/php_sockets_win.c [new file with mode: 0644]
ext/sockets/php_sockets_win.h [new file with mode: 0644]
ext/sockets/sockets.c
ext/sockets/sockets.dsp [new file with mode: 0644]

index 674a9cebadfd72ee0ab44b41cccd921604747be3..cd360009824a1f0583c3ec6e6185d3558acfc8c4 100644 (file)
@@ -1,2 +1,2 @@
 Sockets
-Chris Vandomelen, Sterling Hughes
+Chris Vandomelen, Sterling Hughes, Daniel Beulshausen
index 66055b8ee05af2c5f17eaaa24a1390076c43ea9a..422451793d1c7f8aa815688d536904c4b837d200 100644 (file)
@@ -13,6 +13,9 @@
    | 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>                      |
    +----------------------------------------------------------------------+
  */
 
@@ -35,50 +38,59 @@ extern zend_module_entry sockets_module_entry;
 PHP_MINIT_FUNCTION(sockets);
 PHP_MINFO_FUNCTION(sockets);
 
-PHP_FUNCTION(fd_alloc);
-PHP_FUNCTION(fd_dealloc);
-PHP_FUNCTION(fd_set);
-PHP_FUNCTION(fd_isset);
-PHP_FUNCTION(fd_clear);
-PHP_FUNCTION(fd_zero);
-PHP_FUNCTION(select);
-PHP_FUNCTION(open_listen_sock);
-PHP_FUNCTION(accept_connect);
-PHP_FUNCTION(set_nonblock);
-PHP_FUNCTION(listen);
-PHP_FUNCTION(close);
-PHP_FUNCTION(write);
-PHP_FUNCTION(read);
-PHP_FUNCTION(getsockname);
-PHP_FUNCTION(getpeername);
-PHP_FUNCTION(socket);
-PHP_FUNCTION(connect);
-PHP_FUNCTION(strerror);
-PHP_FUNCTION(bind);
-PHP_FUNCTION(recv);
-PHP_FUNCTION(send);
-PHP_FUNCTION(recvfrom);
-PHP_FUNCTION(sendto);
-PHP_FUNCTION(build_iovec);
-PHP_FUNCTION(fetch_iovec);
-PHP_FUNCTION(free_iovec);
-PHP_FUNCTION(add_iovec);
-PHP_FUNCTION(delete_iovec);
-PHP_FUNCTION(set_iovec);
-PHP_FUNCTION(recvmsg);
-PHP_FUNCTION(sendmsg);
-PHP_FUNCTION(readv);
-PHP_FUNCTION(writev);
-PHP_FUNCTION(getsockopt);
-PHP_FUNCTION(setsockopt);
-PHP_FUNCTION(socketpair);
-PHP_FUNCTION(shutdown);
+PHP_FUNCTION(socket_fd_alloc);
+PHP_FUNCTION(socket_fd_free);
+PHP_FUNCTION(socket_fd_set);
+PHP_FUNCTION(socket_fd_isset);
+PHP_FUNCTION(socket_fd_clear);
+PHP_FUNCTION(socket_fd_zero);
+PHP_FUNCTION(socket_iovec_alloc);
+PHP_FUNCTION(socket_iovec_free);
+PHP_FUNCTION(socket_iovec_set);
+PHP_FUNCTION(socket_iovec_fetch);
+PHP_FUNCTION(socket_iovec_add);
+PHP_FUNCTION(socket_iovec_delete);
+PHP_FUNCTION(socket_select);
+PHP_FUNCTION(socket_create_listen);
+PHP_FUNCTION(socket_create_pair);
+PHP_FUNCTION(socket_accept);
+PHP_FUNCTION(socket_set_nonblock);
+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_recvmsg);
+PHP_FUNCTION(socket_sendmsg);
+PHP_FUNCTION(socket_readv);
+PHP_FUNCTION(socket_writev);
+PHP_FUNCTION(socket_getopt);
+PHP_FUNCTION(socket_setopt);
+PHP_FUNCTION(socket_shutdown);
 
 typedef struct php_iovec {
        struct iovec *iov_array;
        unsigned int count;
 } php_iovec_t;
 
+typedef struct {
+#ifdef PHP_WIN32
+       SOCKET socket;
+#else
+       int socket;
+#endif
+       int type;
+} php_socket;
+
 typedef struct {
        zend_bool use_system_read;
 } php_sockets_globals;
@@ -93,17 +105,14 @@ typedef struct {
 #endif
 
 #else
-
 #define phpext_sockets_ptr NULL
-
 #endif
 
-#endif /* PHP_SOCKETS_H */
-
+#endif
 
 /*
  * Local variables:
  * tab-width: 4
  * c-basic-offset: 4
  * End:
- */
+ */
\ No newline at end of file
diff --git a/ext/sockets/php_sockets_win.c b/ext/sockets/php_sockets_win.c
new file mode 100644 (file)
index 0000000..5956781
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP version 4.0                                                      |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.02 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available at through the world-wide-web at                           |
+   | http://www.php.net/license/2_02.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>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#ifdef PHP_WIN32
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "php.h"
+#include "php_sockets.h"
+#include "php_sockets_win.h"
+
+ssize_t readv(SOCKET sock, const struct iovec *iov, int iovcnt) {
+       size_t bytes, remain, len, pos = 0;
+       ssize_t retval;
+       int i;
+       char *buffer = NULL;
+
+       for(bytes=0, i=0; i<iovcnt; i++) {
+               bytes += iov[i].iov_len;
+       }
+
+       buffer = (char*)emalloc(bytes);
+       if (buffer == NULL) {
+               return -1;
+       }
+
+       retval = recv(sock, buffer, bytes, 0);
+       if(retval < 0) {
+               efree(buffer);
+               return retval;
+       }
+
+       remain = bytes = (size_t) retval;
+       
+       for(i=0; i<iovcnt; i++) {
+               len = (iov[i].iov_len < remain) ? iov[i].iov_len : remain;
+               memcpy(iov[i].iov_base, buffer+pos, len);
+               pos += len;
+               remain -= len;
+       }
+
+       efree(buffer);
+       return bytes;
+}
+
+ssize_t writev(SOCKET sock, const struct iovec *iov, int iovcnt) {
+       size_t bytes, pos = 0;
+       ssize_t retval;
+       int i;
+       char *buffer = NULL;
+
+       for(bytes=0, i=0; i<iovcnt; i++) {
+               bytes += iov[i].iov_len;
+       }
+
+       buffer = (char*)emalloc(bytes);
+       
+       if(buffer == NULL) {
+               return -1;
+       }
+
+       for(i=0; i<iovcnt; i++) {
+               memcpy(buffer+pos, iov[i].iov_base, iov[i].iov_len);
+               pos += iov[i].iov_len;
+       }
+
+       retval = send(sock, buffer, bytes, 0);
+       efree(buffer);
+       
+       return retval;
+}
+
+ssize_t recvmsg(SOCKET sock, struct msghdr *msg, int flags) {
+       set_errno(WSAEOPNOTSUPP);
+       return -1;
+}
+
+ssize_t sendmsg(SOCKET sock, struct msghdr *msg, int flags) {
+       set_errno(WSAEOPNOTSUPP);
+       return -1;
+}
+
+int socketpair(int domain, int type, int protocol, SOCKET sock[2]) {
+       struct sockaddr_in address;
+       SOCKET redirect;
+       int size = sizeof(address);
+
+       if(domain != AF_INET) {
+               set_errno(WSAENOPROTOOPT);
+               return -1;
+       }
+
+
+       sock[0] = socket(domain, type, protocol);
+       address.sin_addr.s_addr = INADDR_ANY;
+       address.sin_family              = AF_INET;
+       address.sin_port                = 0;
+
+       bind(sock[0], (struct sockaddr*)&address, sizeof(address));
+       if(getsockname(sock[0], (struct sockaddr *)&address, &size) != 0) {
+
+    }
+
+       listen(sock[0], 2);
+       sock[1] = socket(domain, type, protocol);       
+       address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+       connect(sock[1], (struct sockaddr*)&address, sizeof(address));
+       redirect = accept(sock[0],(struct sockaddr*)&address, &size);
+
+       close(sock[0]);
+       sock[0] = redirect;
+
+       if(sock[0] == INVALID_SOCKET ) {
+               close(sock[0]);
+               close(sock[1]);
+               set_errno(WSAECONNABORTED);
+               return -1;
+       }
+       
+       return 0;
+}
+
+int inet_aton(const char *cp, struct in_addr *inp) {
+  inp->s_addr = inet_addr(cp);
+
+  if (inp->s_addr == INADDR_NONE) {
+         return 0;
+  }
+
+  return 1;
+}
+
+int fcntl(int fd, int cmd, ...) {
+    va_list va;
+       int retval;
+
+    va_start(va, cmd);
+
+       switch(cmd) {
+               case F_GETFL:
+               case F_SETFD:
+               case F_GETFD:
+               default:
+                       retval = -1;
+                       break;
+
+               case F_SETFL:
+                       retval = ioctlsocket(fd, cmd, va_arg(va, int*));
+                       break;
+       }
+
+       va_end(va);
+       return retval;
+}
+#endif
\ No newline at end of file
diff --git a/ext/sockets/php_sockets_win.h b/ext/sockets/php_sockets_win.h
new file mode 100644 (file)
index 0000000..cbb225b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP version 4.0                                                      |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.02 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available at through the world-wide-web at                           |
+   | http://www.php.net/license/2_02.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>                      |
+   +----------------------------------------------------------------------+
+ */
+
+#ifdef PHP_WIN32
+
+#define F_SETFL                0
+#define F_GETFL                1
+#define F_SETFD                2
+#define F_GETFD                3
+
+#define O_NONBLOCK FIONBIO
+
+#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 set_h_errno(a) WSASetLastError(a)
+#define close(a) closesocket(a)
+#define CMSG_DATA(cmsg) ((cmsg)->cmsg_data)
+#define IS_INVALID_SOCKET(a)  (a->socket == INVALID_SOCKET)
+
+typedef long ssize_t;
+
+struct sockaddr_un {
+       short   sun_family;
+       char    sun_path[108];
+};
+
+struct iovec {
+       char *  iov_base;
+       int     iov_len;
+};
+
+struct msghdr {
+       void*                   msg_name;
+       socklen_t               msg_namelen;
+       struct iovec*   msg_iov;
+       int                             msg_iovlen;
+       void*                   msg_control;
+       socklen_t               msg_controllen;
+       int                             msg_flags;
+};
+
+struct cmsghdr {
+       socklen_t       cmsg_len;
+       int                     cmsg_level;
+       int                     cmsg_type;
+       unsigned char      cmsg_data[];
+};
+
+ssize_t readv(SOCKET sock, const struct iovec *iov, int iovcnt);
+ssize_t writev(SOCKET sock, const struct iovec *iov, int iovcnt);
+ssize_t recvmsg(SOCKET sock, struct msghdr *msg, int flags);
+ssize_t sendmsg(SOCKET sock, struct msghdr *msg, int flags);
+int socketpair(int domain, int type, int protocol, SOCKET sock[2]);
+int inet_aton(const char *cp, struct in_addr *inp);
+int fcntl(int fd, int cmd, ...);
+
+#endif
index 67666e523ee795edd60ea1019d140b4fdf3991c1..6de3e454e22e706ff2429878fd8cfaac6f385327 100644 (file)
@@ -13,7 +13,9 @@
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
    | Authors: Chris Vandomelen <chrisv@b0rked.dhs.org>                    |
-   |          Sterling Hughes <sterling@php.net>                          |
+   |          Sterling Hughes  <sterling@php.net>                         |
+   |                                                                      |
+   | WinSock: Daniel Beulshausen <daniel@php4win.de>                      |
    +----------------------------------------------------------------------+
  */
 
 
 #include "php.h"
 
-
 #if HAVE_SOCKETS
 
-/* This hopefully will fix some compile errors on other platforms --
- * the usage of msg_control/msg_controllen are X/Open Extended attributes,
- * or so it seems, by reading HP/UX 10.20 manual pages.
- *
- * The second two defines are for Solaris 8 with the Sun WorkShop compiler.
- */
-
 #define _XOPEN_SOURCE_EXTENDED
 #define _XPG4_2
 #define __EXTENSIONS__
 #endif
 
 #include "ext/standard/info.h"
-#include "php_sockets.h"
 #include "php_ini.h"
 
-#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>
+#ifndef PHP_WIN32
+# include "php_sockets.h"
+# 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->socket < 0)
+# define set_errno(a) (errno = a)
+# define set_h_errno(a) (h_errno = a)
+#else /* windows */
+# include <winsock.h>
+# include "php_sockets.h"
+# include "php_sockets_win.h"
+#endif
 
 #ifdef ZTS
 int sockets_globals_id;
@@ -63,38 +66,29 @@ int sockets_globals_id;
 php_sockets_globals sockets_globals;
 #endif
 
-/* It seems some platforms don't have this... */
 
 #ifndef MSG_WAITALL
 #ifdef LINUX
-/* Well, it's defined on linux to this, and on a few
- * distributions, it doesn't get included... */
 #define MSG_WAITALL 0x00000100
 #else
 #define MSG_WAITALL 0x00000000
 #endif
 #endif
 
-/* Solaris 8 doesn't appear to define SUN_LEN in <sys/un.h> */
 #ifndef SUN_LEN
-#define SUN_LEN(su) \
-       (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
 #endif
 
-/* Use the read() wrapper, stopping at '\n', '\r', or '\0'. */
 #define PHP_NORMAL_READ 0x0001
-/* Use the read() wrapper, but read until the entire buffer is filled. */
 #define PHP_BINARY_READ 0x0002
-/* Use the system read() function. */
 #define PHP_SYSTEM_READ 0x0004
 
 typedef struct {
-       unsigned char info[128];
+       unsigned char info[256];
 } php_sockaddr_storage;
 
 
-static int le_iov;
-static int le_destroy;
+static int le_iov, le_destroy, le_socket;
 
 static unsigned char second_and_third_args_force_ref[] =
 {3, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
@@ -102,69 +96,53 @@ static unsigned char second_and_third_args_force_ref[] =
 static unsigned char second_fifth_and_sixth_args_force_ref[] =
 {6, BYREF_NONE, BYREF_FORCE, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
 
-static unsigned char fourth_arg_force_ref[] =
-{4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
-
 static unsigned char third_through_seventh_args_force_ref[] =
 {7, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE};
 
+
 function_entry sockets_functions[] = {
-       PHP_FE(fd_alloc,                        NULL)   /* OK */
-       PHP_FE(fd_dealloc,                      NULL)   /* OK */
-       PHP_FE(fd_set,                          NULL)   /* OK */
-       PHP_FE(fd_isset,                        NULL)   /* OK */
-       PHP_FE(fd_clear,                        NULL)   /* OK */
-       PHP_FE(fd_zero,                         NULL)   /* OK */
-       PHP_FE(select,                          NULL)   /* OK */
-       PHP_FE(open_listen_sock,                NULL)   /* OK */
-       PHP_FE(accept_connect,                  NULL)   /* OK */
-       PHP_FE(set_nonblock,                    NULL)   /* OK */
-       PHP_FE(listen,                          NULL)   /* OK */
-       PHP_FE(close,                           NULL)   /* OK */
-       PHP_FE(write,                           NULL)   /* OK */
-       PHP_FE(read,                            second_arg_force_ref)   /* OK */
-#if 0
-/* 
- * If and when asynchronous context switching is avaliable, 
- * this will work. Otherwise, forget it. 
- */
-       PHP_FE(signal,                          NULL)
-#endif
-/* 
- * These are defined elsewhere.. 
- * would these be more appropriate?
- */
-#if 0
-       PHP_FE(gethostbyname,                   second_arg_force_ref)   /* OK */
-       PHP_FE(gethostbyaddr,                   second_arg_force_ref)   /* OK */
-#endif
-       PHP_FE(getsockname,                     second_and_third_args_force_ref)        /* OK */
-       PHP_FE(getpeername,                     second_and_third_args_force_ref)        /* OK */
-       PHP_FE(socket,                          NULL)   /* OK */
-       PHP_FE(connect,                         NULL)   /* OK */
-       PHP_FE(strerror,                        NULL)   /* OK */
-       PHP_FE(bind,                            NULL)
-       PHP_FE(recv,                            second_arg_force_ref)
-       PHP_FE(send,                            NULL)
-       PHP_FE(recvfrom,                        second_fifth_and_sixth_args_force_ref)
-       PHP_FE(sendto,                          NULL)
-       PHP_FE(build_iovec,                     NULL)
-       PHP_FE(fetch_iovec,                     NULL)
-       PHP_FE(free_iovec,                      NULL)
-       PHP_FE(add_iovec,                       NULL)
-       PHP_FE(delete_iovec,            NULL)
-       PHP_FE(set_iovec,                       NULL)
-       PHP_FE(recvmsg,                         third_through_seventh_args_force_ref)
-       PHP_FE(sendmsg,                         NULL)
-       PHP_FE(readv,                           NULL)
-       PHP_FE(writev,                          NULL)
-       PHP_FE(getsockopt,                      fourth_arg_force_ref)
-       PHP_FE(setsockopt,                      NULL)
-       PHP_FE(socketpair,                      NULL)
-       PHP_FE(shutdown,            NULL)
+       PHP_FE(socket_fd_alloc,                 NULL)
+       PHP_FE(socket_fd_free,                  NULL)
+       PHP_FE(socket_fd_set,                   NULL)
+       PHP_FE(socket_fd_isset,                 NULL)
+       PHP_FE(socket_fd_clear,                 NULL)
+       PHP_FE(socket_fd_zero,                  NULL)
+       PHP_FE(socket_iovec_alloc,              NULL)
+       PHP_FE(socket_iovec_free,               NULL)
+       PHP_FE(socket_iovec_set,                NULL)
+       PHP_FE(socket_iovec_fetch,              NULL)
+       PHP_FE(socket_iovec_add,                NULL)
+       PHP_FE(socket_iovec_delete,             NULL)
+       PHP_FE(socket_select,                   NULL)
+       PHP_FE(socket_create,                   NULL)
+       PHP_FE(socket_create_listen,    NULL)
+       PHP_FE(socket_create_pair,              NULL)
+       PHP_FE(socket_accept,                   NULL)
+       PHP_FE(socket_set_nonblock,             NULL)
+       PHP_FE(socket_listen,                   NULL)
+       PHP_FE(socket_close,                    NULL)
+       PHP_FE(socket_write,                    NULL)
+       PHP_FE(socket_read,                     NULL)
+       PHP_FE(socket_getsockname,              second_and_third_args_force_ref)
+       PHP_FE(socket_getpeername,              second_and_third_args_force_ref)
+       PHP_FE(socket_connect,                  NULL)
+       PHP_FE(socket_strerror,                 NULL)
+       PHP_FE(socket_bind,                             NULL)
+       PHP_FE(socket_recv,                             NULL)
+       PHP_FE(socket_send,                             NULL)
+       PHP_FE(socket_recvfrom,                 second_fifth_and_sixth_args_force_ref)
+       PHP_FE(socket_sendto,                   NULL)
+       PHP_FE(socket_recvmsg,                  third_through_seventh_args_force_ref)
+       PHP_FE(socket_sendmsg,                  NULL)
+       PHP_FE(socket_readv,                    NULL)
+       PHP_FE(socket_writev,                   NULL)
+       PHP_FE(socket_getopt,                   NULL)
+       PHP_FE(socket_setopt,                   NULL)
+       PHP_FE(socket_shutdown,                 NULL)
        {NULL, NULL, NULL}
 };
 
+
 zend_module_entry sockets_module_entry = {
        "sockets",
        sockets_functions,
@@ -176,20 +154,24 @@ zend_module_entry sockets_module_entry = {
        STANDARD_MODULE_PROPERTIES
 };
 
+
 #ifdef COMPILE_DL_SOCKETS
 ZEND_GET_MODULE(sockets)
 #endif
 
+/* this should be mutex'ed */
+volatile int inet_ntoa_lock = 0;
+
 static void destroy_fd_sets(zend_rsrc_list_entry *rsrc)
 {
-       fd_set *set = (fd_set *) rsrc->ptr;
+       fd_set *set = (fd_set*)rsrc->ptr;
        efree(set);
 }
 
 static void destroy_iovec(zend_rsrc_list_entry *rsrc)
 {
-       int i;
-       php_iovec_t *iov = (php_iovec_t *) rsrc->ptr;
+       unsigned int i;
+       php_iovec_t *iov = (php_iovec_t*)rsrc->ptr;
 
        if (iov->count && iov->iov_array) {
                for (i = 0; i < iov->count; i++) {
@@ -201,842 +183,722 @@ static void destroy_iovec(zend_rsrc_list_entry *rsrc)
        }
 }
 
+static void destroy_socket(zend_rsrc_list_entry *rsrc) {
+       php_socket *php_sock = (php_socket*)rsrc->ptr;
+
+       close(php_sock->socket);
+       efree(php_sock);
+}
+
+static php_socket *open_listen_sock(int port)
+{
+       struct sockaddr_in la;
+       struct hostent *hp;
+       php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket));
+
+#ifndef PHP_WIN32
+       if ((hp = gethostbyname("0.0.0.0")) == NULL) {
+#else
+       if ((hp = gethostbyname("localhost")) == NULL) {
+#endif
+               efree(php_sock);
+               return NULL;
+       }
+       
+       memcpy((char *)&la.sin_addr, hp->h_addr, hp->h_length);
+       la.sin_family = hp->h_addrtype;
+       la.sin_port = htons((unsigned short)port);
+
+       php_sock->socket = socket(AF_INET, SOCK_STREAM, 0);
+       php_sock->type = AF_INET;
+       if (IS_INVALID_SOCKET(php_sock)) {
+               efree(php_sock);
+               return NULL;
+       }
+       if ((bind(php_sock->socket, (struct sockaddr *)&la, sizeof(la)) != 0)) {
+               efree(php_sock);
+               return NULL;
+       }
+       listen(php_sock->socket, 128);
+       return php_sock;
+}
+
+static php_socket *accept_connect(php_socket *php_sock, struct sockaddr *la)
+{
+       int m;
+       php_socket *retval = (php_socket*)emalloc(sizeof(php_socket));
+
+       m = sizeof(*la);
+       
+       retval->socket = accept(php_sock->socket, la, &m);
+       if (IS_INVALID_SOCKET(retval)) {
+               efree(retval);
+               return NULL;
+       }
+       return retval;
+}
+
+/* php_read -- wrapper around read() so that it only reads to a \r or \n. */
+int php_read(php_socket *php_sock, void *buf, int maxlen)
+{
+     int m = 0, n = 0;
+     int no_read = 0;
+     int nonblock = 0;
+        char *t = (char*)buf;
+
+     m = fcntl(php_sock->socket, F_GETFL);
+        
+        if (m < 0) {
+                return m;
+        }
+
+     nonblock = (m & O_NONBLOCK);
+     m = 0;
+
+        set_errno(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 = read(php_sock->socket, (void *) t, 1);
+                }
+                
+                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;
+}
+
+
 PHP_MINIT_FUNCTION(sockets)
 {
-       le_destroy = zend_register_list_destructors_ex(destroy_fd_sets, NULL, "sockets file descriptor set", module_number);
-       le_iov     = zend_register_list_destructors_ex(destroy_iovec,   NULL, "sockets i/o vector", module_number);
-
-       REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT);
-       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);
-       REGISTER_LONG_CONSTANT("MSG_PEEK", MSG_PEEK, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("SO_DEBUG", SO_DEBUG, CONST_CS | CONST_PERSISTENT);
-       REGISTER_LONG_CONSTANT("SO_REUSEADDR", SO_REUSEADDR, CONST_CS | CONST_PERSISTENT);
-       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);
+       struct protoent *pe;
+
+       le_socket       = zend_register_list_destructors_ex(destroy_socket,     NULL, "Socket", module_number);
+       le_destroy      = zend_register_list_destructors_ex(destroy_fd_sets,NULL, "Socket file descriptor set", module_number);
+       le_iov          = zend_register_list_destructors_ex(destroy_iovec,      NULL, "Socket I/O vector", module_number);
+
+       REGISTER_LONG_CONSTANT("AF_UNIX",               AF_UNIX,                CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("AF_INET",               AF_INET,                CONST_CS | CONST_PERSISTENT);
+       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);
+       REGISTER_LONG_CONSTANT("MSG_PEEK",              MSG_PEEK,               CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE,  CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SO_DEBUG",              SO_DEBUG,               CONST_CS | CONST_PERSISTENT);
+       REGISTER_LONG_CONSTANT("SO_REUSEADDR",  SO_REUSEADDR,   CONST_CS | CONST_PERSISTENT);
+       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("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("PHP_SYSTEM_READ", PHP_SYSTEM_READ, CONST_CS | CONST_PERSISTENT);
 
-       {
-               struct protoent *pe;
-               pe = getprotobyname("tcp");
-               if (pe) {
-                       REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
-               }
-               
-               pe = getprotobyname("udp");
-               if (pe) {
-                       REGISTER_LONG_CONSTANT("SOL_UDP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
-               }
+       if ((pe = getprotobyname("tcp"))) {
+               REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
+       }
+
+       if ((pe = getprotobyname("udp"))) {
+               REGISTER_LONG_CONSTANT("SOL_UDP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
        }
        
        return SUCCESS;
 }
 
+
 PHP_MINFO_FUNCTION(sockets)
 {
        php_info_print_table_start();
-       php_info_print_table_row(2, "sockets support", "enabled");
+       php_info_print_table_row(2, "Sockets Support", "enabled");
        php_info_print_table_end();
 }
 
-/* {{{ proto resource fd_alloc(void)
-   Allocates a file descriptor set */
-PHP_FUNCTION(fd_alloc)
+
+
+/* {{{ proto resource socket_fd_alloc(void)
+   Allocates a new file descriptor set */
+PHP_FUNCTION(socket_fd_alloc)
 {
        fd_set *set;
 
-       set = (fd_set *) emalloc(sizeof(fd_set));
-       if (!set) {
-               php_error(E_WARNING, "Can't allocate memory for fd_set");
+       if ((set = (fd_set*)emalloc(sizeof(fd_set))) == NULL) {
+               php_error(E_WARNING, "cannot allocate file descriptor");
                RETURN_FALSE;
        }
-       
+
+       FD_ZERO(set);   
        ZEND_REGISTER_RESOURCE(return_value, set, le_destroy);
 }
 /* }}} */
 
-/* {{{ proto bool fd_dealloc(int set)
-   De-allocates a file descriptor set */
-PHP_FUNCTION(fd_dealloc)
+/* {{{ proto bool socket_fd_dealloc(resource set)
+   Deallocates a file descriptor set */
+PHP_FUNCTION(socket_fd_free)
 {
-       zval **set;
+       zval **arg1;
        fd_set *the_set;
        
-       if (ZEND_NUM_ARGS() != 1 ||
-           zend_get_parameters_ex(1, &set) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
-       ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy);
-       
-       zend_list_delete(Z_LVAL_PP(set));
+       ZEND_FETCH_RESOURCE(the_set, fd_set *, arg1, -1, "File descriptor set", le_destroy);
        
+       zend_list_delete(Z_RESVAL_PP(arg1));
        RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto bool fd_set(int fd, resource set)
+/* {{{ proto bool socket_fd_set(resource socket, resource set)
    Adds a file descriptor to a set */
-PHP_FUNCTION(fd_set)
+PHP_FUNCTION(socket_fd_set)
 {
-       zval **set, **fd;
+       zval **arg1, **arg2;
        fd_set *the_set;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &fd, &set) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
-
-       ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy);
-
-       if (Z_LVAL_PP(fd) < 0) {
-               php_error(E_WARNING, "Can't set negative fd falues in a set");
-               RETURN_FALSE;
-       }
 
-       FD_SET(Z_LVAL_PP(fd), the_set);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       ZEND_FETCH_RESOURCE(the_set, fd_set*, arg2, -1, "File descriptor set", le_destroy);
 
+       FD_SET(php_sock->socket, the_set);
        RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto bool fd_clear(int fd, resource set)
+/* {{{ proto bool socket_fd_clear(resource socket, resource set)
    Clears a file descriptor from a set */
-PHP_FUNCTION(fd_clear)
+PHP_FUNCTION(socket_fd_clear)
 {
-       zval **set, **fd;
+       zval **arg1, **arg2;
        fd_set *the_set;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &fd, &set) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
 
-       ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy);
-
-       if (Z_LVAL_PP(fd) < 0) {
-               php_error(E_WARNING, "Can't clear negative fd values in a set");
-               RETURN_FALSE;
-       }
-
-       FD_CLR(Z_LVAL_PP(fd), the_set);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       ZEND_FETCH_RESOURCE(the_set, fd_set *, arg2, -1, "File descriptor set", le_destroy);
 
+       FD_CLR(php_sock->socket, the_set);
        RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto bool fd_isset(int fd, resource set)
+/* {{{ proto bool socket_fd_isset(resource socket, resource set)
    Checks to see if a file descriptor is set within the file descrirptor set */
-PHP_FUNCTION(fd_isset)
+PHP_FUNCTION(socket_fd_isset)
 {
-       zval **set, **fd;
+       zval **arg1, **arg2;
        fd_set *the_set;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &fd, &set) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
 
-       ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       ZEND_FETCH_RESOURCE(the_set, fd_set *, arg2, -1, "File descriptor set", le_destroy);
 
-       if (Z_LVAL_PP(fd) < 0) {
-               php_error(E_WARNING, "Can't check for negative fd values in a set");
-               RETURN_FALSE;
-       }
-
-       if (FD_ISSET(Z_LVAL_PP(fd), the_set)) {
+       if (FD_ISSET(php_sock->socket, the_set)) {
                RETURN_TRUE;
        }
-       
        RETURN_FALSE;
 }
 /* }}} */
 
-/* {{{ proto void fd_zero(resource set)
+/* {{{ proto bool socket_fd_zero(resource set)
    Clears a file descriptor set */
-PHP_FUNCTION(fd_zero)
+PHP_FUNCTION(socket_fd_zero)
 {
-       zval **set;
+       zval **arg1;
        fd_set *the_set;
 
-       if (ZEND_NUM_ARGS() != 1 || 
-           zend_get_parameters_ex(1, &set) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
-       ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy);
+       ZEND_FETCH_RESOURCE(the_set, fd_set *, arg1, -1, "File descriptor set", le_destroy);
 
        FD_ZERO(the_set);
-
        RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto int select(int max_fd, resource readfds, resource writefds, resource exceptfds, int tv_sec, int tv_usec)
+/* {{{ proto int socket_select(int max_sockets, resource read_fd, resource write_fd, resource except_fd, int tv_sec, int tv_usec)
    Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec */
-/* See select(2) man page for details.
-
-   From man page:
-   select waits for a number of file descriptors to change status.
-
-   Three independent sets of descriptors are watched.  Those in 
-   readfds will be watched to see if characters become avaliable for 
-   reading, those in writefds will be watched to see if it is ok to 
-   immediately write on them, and those in exceptfds will be watched 
-   for exceptions.  On exit, the sets are modified in place to 
-   indicate which descriptors actually changed status.
-
-   -1 is passed for any sets for which NULL would be passed to the 
-   system call.
- */
-
-PHP_FUNCTION(select)
+PHP_FUNCTION(socket_select)
 {
-       zval **max_fd, **readfds, **writefds, 
-            **exceptfds, **tv_sec, **tv_usec;
-
+       zval **arg1, **arg2, **arg3, **arg4, **arg5, **arg6;
        struct timeval tv;
        fd_set *rfds, *wfds, *xfds;
-       int ret = 0;
 
-       if (ZEND_NUM_ARGS() != 6 || 
-           zend_get_parameters_ex(6, &max_fd, &readfds, &writefds, &exceptfds, &tv_sec, &tv_usec) == FAILURE) {
+       if (zend_get_parameters_ex(6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(3, max_fd, tv_sec, tv_usec);
-
-       tv.tv_sec  = Z_LVAL_PP(tv_sec);
-       tv.tv_usec = Z_LVAL_PP(tv_usec);
-
-       if (Z_LVAL_PP(readfds) != 0) {
-               ZEND_FETCH_RESOURCE(rfds, fd_set *, readfds, -1, "File descriptor set", le_destroy);
-       } else {
-               rfds = NULL;
-       }
        
-       if (Z_LVAL_PP(writefds) != 0) {
-               ZEND_FETCH_RESOURCE(wfds, fd_set *, writefds, -1, "File descriptor set", le_destroy);
-       } else {
-               wfds = NULL;
-       }
-       
-       if (Z_LVAL_PP(exceptfds) != 0) {
-               ZEND_FETCH_RESOURCE(xfds, fd_set *, exceptfds, -1, "File descriptor set", le_destroy);
-       } else {
-               xfds = NULL;
-       }
-
-       ret = select(Z_LVAL_PP(max_fd), rfds, wfds, xfds, &tv);
+       convert_to_long_ex(arg1);
+       convert_to_long_ex(arg5);
+       convert_to_long_ex(arg6);
+       ZEND_FETCH_RESOURCE(rfds, fd_set*, arg2, -1, "File descriptor set", le_destroy);
+       ZEND_FETCH_RESOURCE(wfds, fd_set*, arg3, -1, "File descriptor set", le_destroy);
+       ZEND_FETCH_RESOURCE(xfds, fd_set*, arg4, -1, "File descriptor set", le_destroy);
+       tv.tv_sec  = Z_LVAL_PP(arg5);
+       tv.tv_usec = Z_LVAL_PP(arg6);
 
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_LONG(select(Z_LVAL_PP(arg1), rfds, wfds, xfds, &tv));
 }
 /* }}} */
 
-static int open_listen_sock(int port)
-{
-       int fd;
-       struct sockaddr_in la;
-       struct hostent *hp;
-
-       if ((hp = gethostbyname("0.0.0.0")) == NULL) {
-               return -1;
-       }
-       
-       memcpy((char *)&la.sin_addr, hp->h_addr, hp->h_length);
-       la.sin_family = hp->h_addrtype;
-       la.sin_port = htons(port);
-
-       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-               return -1;
-       }
-       if ((bind(fd, (struct sockaddr *)&la, sizeof(la)) < 0)) {
-               return -1;
-       }
-       listen(fd, 128);
-       return fd;
-}
-
-/* {{{ proto int open_listen_sock(int port)
+/* {{{ proto mixed socket_create_listen(int port)
    Opens a socket on port to accept connections */
-PHP_FUNCTION(open_listen_sock)
+PHP_FUNCTION(socket_create_listen)
 {
        zval **port;
-       int ret;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 1 || 
-           zend_get_parameters_ex(1, &port) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &port) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        convert_to_long_ex(port);
 
-       ret = open_listen_sock(Z_LVAL_PP(port));
-
-       RETURN_LONG(((ret < 0) ? -errno : ret));
-}
-/* }}} */
-
-static int accept_connect(int fd, struct sockaddr *la)
-{
-       int ret, m;
+       php_sock = open_listen_sock(Z_LVAL_PP(port));
 
-       m = sizeof(*la);
-       if ((ret = accept(fd, la, &m)) < 0) {
-               return -1;
+       if(php_sock == NULL) {
+               php_error(E_WARNING, "unable to create listening socket, %i", errno);
+               RETURN_FALSE;
        }
-       return ret;
+
+       ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
 }
+/* }}} */
 
-/* {{{ proto int accept_connect(int fd)
+/* {{{ proto socket socket_accept(resource socket)
    Accepts a connection on the listening socket fd */
-PHP_FUNCTION(accept_connect)
+PHP_FUNCTION(socket_accept)
 {
-       zval **fd;
-       int ret;
+       zval **arg1;
+       php_socket *php_sock, *new_sock;
        struct sockaddr_in sa;
 
-       if (ZEND_NUM_ARGS() != 1 || 
-           zend_get_parameters_ex(1, &fd) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
 
-       ret = accept_connect(Z_LVAL_PP(fd), (struct sockaddr *)&sa);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       new_sock = accept_connect(php_sock, (struct sockaddr*)&sa);
+
+       if(new_sock == NULL) {
+               php_error(E_WARNING, "unable to accept connection, %i", errno);
+               RETURN_FALSE
+       }
+       
+       ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);
 }
 /* }}} */
 
-/* {{{ proto bool set_nonblock(int fd)
+/* {{{ proto bool socket_set_nonblock(resource socket)
    Sets nonblocking mode for file descriptor fd */
-PHP_FUNCTION(set_nonblock)
+PHP_FUNCTION(socket_set_nonblock)
 {
-       zval **fd;
-       int ret;
+       zval **arg1;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 1 ||
-           zend_get_parameters_ex(1, &fd) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
-
-       ret = fcntl(Z_LVAL_PP(fd), F_SETFL, O_NONBLOCK);
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+
+       if (fcntl(php_sock->socket, F_SETFL, O_NONBLOCK) == 0) {
+               RETURN_TRUE;
+       }
+
+       RETURN_FALSE;
 }
 /* }}} */
 
-/* {{{ proto bool listen(int fd, int backlog)
+/* {{{ proto bool socket_listen(resource socket, int backlog)
    Sets the maximum number of connections allowed to be waited for on the socket specified by fd */
-PHP_FUNCTION(listen)
+PHP_FUNCTION(socket_listen)
 {
-       zval **fd, **backlog;
-       int ret;
+       zval **arg1, **arg2;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fd, &backlog) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(2, fd, backlog);
+       
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_long_ex(arg2);
 
-       ret = listen(Z_LVAL_PP(fd), Z_LVAL_PP(backlog));
+       if (listen(php_sock->socket, Z_LVAL_PP(arg2)) == 0) {
+               RETURN_FALSE;
+       }
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto bool close(int fd)
+/* {{{ proto void socket_close(resource socket)
    Closes a file descriptor */
-PHP_FUNCTION(close)
+PHP_FUNCTION(socket_close)
 {
-       zval **fd;
-       int ret;
+       zval **arg1;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 1 || 
-           zend_get_parameters_ex(1, &fd) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
-       ret = close(Z_LVAL_PP(fd));
-       
-       if (ret == -1) {
-               php_error(E_WARNING, "Invalid file descriptor");
-               RETURN_FALSE;
-       }
-       RETURN_TRUE;
+
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       zend_list_delete(Z_RESVAL_PP(arg1));
 }
 /* }}} */
 
-/* {{{ proto int write(int fd, string buf, int length)
-   Writes length bytes of buf to the file descriptor fd */
-PHP_FUNCTION(write)
+/* {{{ proto int socket_write(resource socket, string buf[, int length])
+   Writes the buffer to the file descriptor fd, length is optional */
+PHP_FUNCTION(socket_write)
 {
-       zval **fd, **buf, **length;
-       int ret;
+       zval **arg1, **arg2, **arg3;
+       php_socket *php_sock;
+       int retval, which, argc = ZEND_NUM_ARGS();
 
-       if (ZEND_NUM_ARGS() != 3 || 
-           zend_get_parameters_ex(3, &fd, &buf, &length) == FAILURE) {
+       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       
-       multi_convert_to_long_ex(2, fd, length);
-       convert_to_string_ex(buf);
 
-       if (Z_STRLEN_PP(buf) < Z_LVAL_PP(length)) {
-               ret = write(Z_LVAL_PP(fd), (void *)Z_STRVAL_PP(buf), Z_STRLEN_PP(buf));
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_string_ex(arg2);
+       if (argc == 3) {
+               convert_to_long_ex(arg3);
+               which = (Z_STRLEN_PP(arg2) < Z_LVAL_PP(arg3)) ? 1 : 0;
        } else {
-               ret = write(Z_LVAL_PP(fd), (void *)Z_STRVAL_PP(buf), Z_LVAL_PP(length));
+               which = 1;
        }
-       
-       RETURN_LONG(((ret < 0) ? -errno : ret));
-}
-/* }}} */
 
-/* {{{ proto int read(int fd, string &buf, int length [, int type])
-   Reads length bytes from fd into buf */
-
-/* php_read -- wrapper around read() so that it only reads to a \r or \n. */
-
-int php_read(int fd, void *buf, int maxlen)
-{
-     char *t;
-     int m = 0, n = 0;
-     int no_read = 0;
-     int nonblock = 0;
-
-     m = fcntl(fd, F_GETFL);
-     if (m < 0)
-       return m;
+#ifndef PHP_WIN32
+       retval = write(php_sock->socket, (void *)Z_STRVAL_PP(arg2), (which ? Z_STRLEN_PP(arg2) : Z_LVAL_PP(arg3)));
+#else
+       retval = send(php_sock->socket, Z_STRVAL_PP(arg2), (which ? Z_STRLEN_PP(arg2) : Z_LVAL_PP(arg3)), 0);
+#endif
 
-     nonblock = (m & O_NONBLOCK);
-     m = 0;
+       if (!retval) {
+               php_error(E_WARNING, "unable to write, %i", errno);
+               RETURN_LONG(0);
+       }
 
-     errno = 0;
-     t = (char *) buf;
-     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) {
-                    errno = ECONNRESET;
-                    return -1;
-               }
-          }
-         if (n < maxlen) {
-                 m = read(fd, (void *) t, 1);
-         }
-          if (errno != 0 && errno != ESPIPE && errno != EAGAIN) {
-               return -1;
-          }
-          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;
+       RETURN_LONG(retval);
 }
+/* }}} */
 
-PHP_FUNCTION(read)
+/* {{{ proto mixed socket_read(resource socket, int length [, int type])
+   Reads length bytes from socket */
+PHP_FUNCTION(socket_read)
 {
-       zval **fd, **buf, **length, **binary;
+       zval **arg1, **arg2, **arg3;
        char *tmpbuf;
-       int ret;
-       int (*read_function)(int, void *, int);
+       php_socket *php_sock;
+       int (*read_function)(int, void *, int) = (int (*)(int, void *, int)) php_read;
+       int retval, argc = ZEND_NUM_ARGS();
 
-       if (ZEND_NUM_ARGS() < 3 || ZEND_NUM_ARGS() > 4 ||
-           zend_get_parameters_ex(ZEND_NUM_ARGS(), &fd, &buf, &length, &binary) == FAILURE) {
+       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
-       multi_convert_to_long_ex(ZEND_NUM_ARGS() - 1, fd, length, binary);
-       convert_to_string_ex(buf);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_long_ex(arg2);
 
-       if (ZEND_NUM_ARGS() == 4) {
-               switch (Z_LVAL_PP(binary)) {
-               case PHP_SYSTEM_READ:
-               case PHP_BINARY_READ:
-                       read_function = (int (*)(int, void *, int)) read;
-                       break;
-               case PHP_NORMAL_READ:
-               default:
-                       read_function = (int (*)(int, void *, int)) php_read;
-                       break;
+       if (argc == 3) {
+               convert_to_long_ex(arg3);
+               switch (Z_LVAL_PP(arg3)) {
+                       case PHP_SYSTEM_READ:
+                       case PHP_BINARY_READ:
+                               read_function = (int (*)(int, void *, int)) read;
+                               break;
                }
-       } else {
-               read_function = (int (*)(int, void *, int)) php_read;
        }
 
-       tmpbuf = emalloc((Z_LVAL_PP(length)+1)*sizeof(char));
-       if (tmpbuf == NULL) {
-               php_error(E_WARNING, "Couldn't allocate memory from %s()", get_active_function_name());
+       if ((tmpbuf = (char*)emalloc((Z_LVAL_PP(arg2)+1)*sizeof(char))) == NULL) {
+               php_error(E_WARNING, "couldn't allocate memory");
                RETURN_FALSE;
        }
-       
-       ret = (*read_function)(Z_LVAL_PP(fd), tmpbuf, Z_LVAL_PP(length));
-       
-       if (ret >= 0) {
-               if(Z_STRLEN_PP(buf) > 0) {
-                       efree(Z_STRVAL_PP(buf));
-               }
 
-               tmpbuf[ret] = '\0';
-               Z_STRVAL_PP(buf) = erealloc(tmpbuf, ret+1);
-               Z_STRLEN_PP(buf) = ret;
+#ifndef PHP_WIN32
+       retval = (*read_function)(php_sock->socket, tmpbuf, Z_LVAL_PP(arg2));
+#else
+       retval = recv(php_sock->socket, tmpbuf, Z_LVAL_PP(arg2), 0);
+#endif
 
-               RETURN_LONG(ret);
-       } else {
+       if (retval <= 0) {
                efree(tmpbuf);
-               RETURN_LONG(-errno);
+               RETURN_FALSE;
        }
+
+       tmpbuf[retval] = '\0';
+       RETURN_STRING(tmpbuf, 1);
 }
 /* }}} */
 
-/* {{{ proto int getsockname(int fd, string &addr[, int &port])
+/* {{{ proto bool socket_getsockname(resource socket, string &addr[, int &port])
    Given an fd, stores a string representing sa.sin_addr and the value of sa.sin_port into addr and port describing the local side of a socket */
-
-/* A lock to prevent inet_ntoa() from causing problems in threading */
-volatile int inet_ntoa_lock = 0;
-
-PHP_FUNCTION(getsockname)
+PHP_FUNCTION(socket_getsockname)
 {
-       zval **fd, **addr, **port;
+       zval **arg1, **addr, **port;
        char *tmp;
        php_sockaddr_storage sa_storage;
+       php_socket *php_sock;
        struct sockaddr *sa;
        struct sockaddr_in *sin;
        struct sockaddr_un *s_un;
        int salen = sizeof(php_sockaddr_storage);
-       int ret;
+       int argc = ZEND_NUM_ARGS();
 
-       if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 || 
-           zend_get_parameters_ex(ZEND_NUM_ARGS(), &fd, &addr, &port) == FAILURE) {
+       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &addr, &port) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(ZEND_NUM_ARGS() - 1, fd, port);
+       
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_long_ex(port);
        convert_to_string_ex(addr);
 
        sa = (struct sockaddr *) &sa_storage;
 
-       ret = getsockname(Z_LVAL_PP(fd), sa, &salen);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+       if (getsockname(php_sock->socket, sa, &salen) != 0) {
+               php_error(E_WARNING, "unable to retrieve socket name, %i", errno);
+               RETURN_FALSE;
        } else {
                char *addr_string;
 
                switch (sa->sa_family) {
-               case AF_INET: {
-                       sin = (struct sockaddr_in *) sa;
-                       while (inet_ntoa_lock == 1);
-                       inet_ntoa_lock = 1;
-                       addr_string = inet_ntoa(sin->sin_addr);
-                       tmp = emalloc(strlen(addr_string) + 1);
-                       memset(tmp, 0, strlen(addr_string) + 1);
-                       strncpy(tmp, addr_string, strlen(addr_string));
-                       inet_ntoa_lock = 0;
-               
-                       if (Z_STRLEN_PP(addr) > 0) {
-                               efree(Z_STRVAL_PP(addr));
-                       }
-
-                       Z_STRVAL_PP(addr) = tmp;
-                       Z_STRLEN_PP(addr) = strlen(tmp);
-                       Z_LVAL_PP(port)   = htons(sin->sin_port);
-
-                       RETURN_LONG(ret);
-               }
-               case AF_UNIX: {
-                       if (Z_STRLEN_PP(addr) > 0) {
-                               efree(Z_STRVAL_PP(addr));
-                       }
-                       s_un = (struct sockaddr_un *) sa;
-                       Z_STRVAL_PP(addr) = estrndup(s_un->sun_path,strlen(s_un->sun_path));
-                       Z_STRLEN_PP(addr) = strlen(s_un->sun_path);
-                       RETURN_LONG(ret);
-               }
-               default:
-                       RETURN_LONG(-EINVAL);
+                       case AF_INET:
+                               sin = (struct sockaddr_in *) sa;
+                               while (inet_ntoa_lock == 1);
+                               inet_ntoa_lock = 1;
+                               addr_string = inet_ntoa(sin->sin_addr);
+                               tmp = (char*)emalloc(strlen(addr_string) + 1);
+                               memset(tmp, 0, strlen(addr_string) + 1);
+                               strncpy(tmp, addr_string, strlen(addr_string));
+                               inet_ntoa_lock = 0;
+                               
+                               if (Z_STRLEN_PP(addr) > 0) {
+                                       efree(Z_STRVAL_PP(addr));
+                               }
+                               
+                               Z_STRVAL_PP(addr) = tmp;
+                               Z_STRLEN_PP(addr) = strlen(tmp);
+                               Z_LVAL_PP(port)   = htons(sin->sin_port);
+                               RETURN_TRUE;
+                       
+                       case AF_UNIX:
+                               if (Z_STRLEN_PP(addr) > 0) {
+                                       efree(Z_STRVAL_PP(addr));
+                               }
+                               s_un = (struct sockaddr_un *) sa;
+                               Z_STRVAL_PP(addr) = estrndup(s_un->sun_path,strlen(s_un->sun_path));
+                               Z_STRLEN_PP(addr) = strlen(s_un->sun_path);
+                               RETURN_TRUE;
+                       
+                       default:
+                               RETURN_FALSE;
                }
        }
 }
 /* }}} */
 
-/* {{{ proto int gethostbyname(string name, string &addr)
-   Given a hostname, sets addr to be a human-readable version of the host's address */
-
-#if 0
-/* Another lock to prevent multiple threads from grabbing gethostbyname() */
-volatile int gethostbyname_lock = 0;
-
-PHP_FUNCTION(gethostbyname)
-{
-       zval **name, **addr;
-       int ret;
-       char *tmp, *addr_string;
-       struct hostent *host_struct;
-       struct in_addr a;
-
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &name, &addr) == FAILURE) {
-               WRONG_PARAM_COUNT;
-       }
-       convert_to_string_ex(name);
-       convert_to_string_ex(addr);
-
-       while (gethostbyname_lock == 1);
-       gethostbyname_lock = 1;
-
-       host_struct = gethostbyname(Z_STRVAL_PP(name));
-       if (!host_struct) {
-               gethostbyname_lock = 0;
-               RETURN_LONG(-(h_errno) - 10000);        /* return a value that is out of range for errno */
-       }
-       if (host_struct->h_addrtype != AF_INET) {
-               gethostbyname_lock = 0;
-               RETURN_LONG(-EINVAL);
-       }
-       while (inet_ntoa_lock == 1);
-       inet_ntoa_lock = 1;
-
-       a.s_addr = (int) (*(host_struct->h_addr_list[0]));
-       addr_string = inet_ntoa(a);
-       tmp = emalloc(strlen(addr_string) + 1);
-       strncpy(tmp, addr_string, strlen(addr_string));
-
-       inet_ntoa_lock = 0;
-       gethostbyname_lock = 0;
-
-       Z_STRVAL_PP(addr) = tmp;
-       Z_STRLEN_PP(addr) = strlen(tmp);
-       
-       RETURN_LONG(0);
-}
-
-/* }}} */
-
-#endif
-
-/* {{{ proto int getpeername(int fd, string &addr[, int &port])
+/* {{{ proto bool socket_getpeername(resource socket, string &addr[, int &port])
    Given an fd, stores a string representing sa.sin_addr and the value of sa.sin_port into addr and port describing the remote side of a socket */
-
-PHP_FUNCTION(getpeername)
+PHP_FUNCTION(socket_getpeername)
 {
-       zval **fd, **addr, **port;
+       zval **arg1, **arg2, **arg3;
        char *tmp;
        php_sockaddr_storage sa_storage;
+       php_socket *php_sock;
        struct sockaddr *sa;
        struct sockaddr_in *sin;
        struct sockaddr_un *s_un;
        int salen = sizeof(php_sockaddr_storage);
-       int ret;
+       int argc = ZEND_NUM_ARGS();
 
-       if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 || 
-           zend_get_parameters_ex(ZEND_NUM_ARGS(), &fd, &addr, &port) == FAILURE) {
+       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(ZEND_NUM_ARGS() - 1, fd, port);
-       convert_to_string_ex(addr);
+
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_string_ex(arg2);
+       convert_to_long_ex(arg3);
 
        sa = (struct sockaddr *) &sa_storage;
 
-       ret = getpeername(Z_LVAL_PP(fd), sa, &salen);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+       if (getpeername(php_sock->socket, sa, &salen) != 0) {
+               php_error(E_WARNING, "unable to retrieve peername, %i", errno);
+               RETURN_FALSE;
        } else {
                char *addr_string;
 
                switch (sa->sa_family) {
-               case AF_INET: {
+               case AF_INET:
                        sin = (struct sockaddr_in *) sa;
                        while (inet_ntoa_lock == 1);
                        inet_ntoa_lock = 1;
                        addr_string = inet_ntoa(sin->sin_addr);
-                       tmp = emalloc(strlen(addr_string) + 1);
+                       tmp = (char*)emalloc(strlen(addr_string) + 1);
                        memset(tmp, 0, strlen(addr_string) + 1);
                        strncpy(tmp, addr_string, strlen(addr_string));
                        inet_ntoa_lock = 0;
                
-                       if (Z_STRLEN_PP(addr) > 0) {
-                               efree(Z_STRVAL_PP(addr));
+                       if (Z_STRLEN_PP(arg2) > 0) {
+                               efree(Z_STRVAL_PP(arg2));
                        }
 
-                       Z_STRVAL_PP(addr) = tmp;
-                       Z_STRLEN_PP(addr) = strlen(tmp);
-                       if (ZEND_NUM_ARGS() > 2)
-                               Z_LVAL_PP(port)   = htons(sin->sin_port);
+                       Z_STRVAL_PP(arg2) = tmp;
+                       Z_STRLEN_PP(arg2) = strlen(tmp);
 
-                       RETURN_LONG(ret);
-               }
-               case AF_UNIX: {
-                       if (Z_STRLEN_PP(addr) > 0) {
-                               efree(Z_STRVAL_PP(addr));
+                       if (argc > 2) {
+                               Z_LVAL_PP(arg3) = htons(sin->sin_port);
                        }
-                       s_un = (struct sockaddr_un *) sa;
-                       Z_STRVAL_PP(addr) = estrndup(s_un->sun_path,strlen(s_un->sun_path));
-                       Z_STRLEN_PP(addr) = strlen(s_un->sun_path);
-                       RETURN_LONG(ret);
-               }
-               default:
-                       RETURN_LONG(-EINVAL);
-               }
-       }
-}
-/* }}} */
-
-/* {{{ proto int gethostbyaddr(string addr, string &name)
-   Given a human-readable address, sets name to be the host's name */
-
-#if 0
-/* Another lock to prevent multiple threads from grabbing gethostbyname() */
-volatile int gethostbyaddr_lock = 0;
-
-PHP_FUNCTION(gethostbyaddr)
-{
-       zval **name, **addr;
-       int ret;
-       char *tmp, *addr_string;
-       struct hostent *host_struct;
-       struct in_addr addr_buf;
-
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &addr, &name) == FAILURE) {
-               WRONG_PARAM_COUNT;
-       }
-       convert_to_string_ex(addr);
-       convert_to_string_ex(name);
 
-       ret = inet_aton(Z_STRVAL_PP(addr), &addr_buf);
-       
-       if (ret < 0) {
-               RETURN_LONG(-EINVAL);
-       }
-       
-       while (gethostbyaddr_lock == 1);
-       gethostbyaddr_lock = 1;
+                       RETURN_TRUE;
 
-       host_struct = gethostbyaddr((char *)&addr_buf, sizeof(addr_buf), AF_INET);
+               case AF_UNIX:
+                       if (Z_STRLEN_PP(arg2) > 0) {
+                               efree(Z_STRVAL_PP(arg2));
+                       }
+                       s_un = (struct sockaddr_un *) sa;
+                       Z_STRVAL_PP(arg2) = estrndup(s_un->sun_path,strlen(s_un->sun_path));
+                       Z_STRLEN_PP(arg2) = strlen(s_un->sun_path);
+                       RETURN_TRUE;
 
-       if (!host_struct) {
-               gethostbyaddr_lock = 0;
-               RETURN_LONG(-(h_errno) - 10000);
-       }
-       if (host_struct->h_addrtype != AF_INET) {
-               gethostbyaddr_lock = 0;
-               RETURN_LONG(-EINVAL);
+               default:
+                       RETURN_FALSE;
+               }
        }
-       
-       addr_string = host_struct->h_name;
-       tmp = emalloc(strlen(addr_string) + 1);
-       strncpy(tmp, addr_string, strlen(addr_string));
-
-       gethostbyaddr_lock = 0;
-
-       Z_STRVAL_PP(addr) = tmp;
-       Z_STRLEN_PP(addr) = strlen(tmp);
-
-       RETURN_LONG(0);
 }
 /* }}} */
 
-#endif
-
-/* {{{ proto int socket(int domain, int type, int protocol)
+/* {{{ proto mixed socket_create(int domain, int type, int protocol)
    Creates an endpoint for communication in the domain specified by domain, of type specified by type */
-PHP_FUNCTION(socket)
+PHP_FUNCTION(socket_create)
 {
-       zval **domain, **type, **protocol;
-       int ret;
+       zval **arg1, **arg2, **arg3;
+       php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket));
 
-       if (ZEND_NUM_ARGS() != 3 || 
-           zend_get_parameters_ex(3, &domain, &type, &protocol) == FAILURE) {
+       if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(3, domain, type, protocol);
 
-       if (Z_LVAL_PP(domain) != AF_INET && Z_LVAL_PP(domain) != AF_UNIX) {
-               php_error(E_WARNING, "invalid socket domain specified - assuming AF_INET");
-               Z_LVAL_PP(domain) = AF_INET;
+       convert_to_long_ex(arg1);
+       convert_to_long_ex(arg2);
+       convert_to_long_ex(arg3);
+
+       if (Z_LVAL_PP(arg1) != AF_UNIX && Z_LVAL_PP(arg1) != AF_INET) {
+               php_error(E_WARNING, "invalid socket domain [%i] specified, assuming AF_INET", Z_LVAL_PP(arg1));
+               Z_LVAL_PP(arg1) = AF_INET;
        }
        
-       if (Z_LVAL_PP(type) > 10) {
-               php_error(E_WARNING, "invalid socket type specified - assuming SOCK_STREAM");
-               Z_LVAL_PP(type) = SOCK_STREAM;
+       if (Z_LVAL_PP(arg2) > 10) {
+               php_error(E_WARNING, "invalid socket type [%i] specified, assuming SOCK_STREAM", Z_LVAL_PP(arg2));
+               Z_LVAL_PP(arg2) = SOCK_STREAM;
        }
        
-       ret = socket(Z_LVAL_PP(domain), Z_LVAL_PP(type), Z_LVAL_PP(protocol));
+       php_sock->socket = socket(Z_LVAL_PP(arg1), Z_LVAL_PP(arg2), Z_LVAL_PP(arg3));
+       php_sock->type = Z_LVAL_PP(arg1);
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       if(IS_INVALID_SOCKET(php_sock)) {
+               RETURN_FALSE;
+       }
+
+       ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);
 }
 /* }}} */
 
-/* {{{ proto int connect(int sockfd, string addr [, int port])
-   Opens a connection to addr:port on the socket specified by sockfd */
-PHP_FUNCTION(connect)
+/* {{{ 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 **sockfd, **addr, **port;
+       zval **arg1, **arg2, **arg3;
+       php_socket *php_sock;
        php_sockaddr_storage sa_storage;
        struct sockaddr *sa = (struct sockaddr *) &sa_storage;
        struct sockaddr_in *sin;
        struct sockaddr_un *s_un;
-       int ret;
+       int retval;
        socklen_t salen;
        struct in_addr addr_buf;
        struct hostent *host_struct;
        int argc = ZEND_NUM_ARGS();
 
-       if (argc < 2 || argc > 3 ||
-           zend_get_parameters_ex(argc, &sockfd, &addr, &port) == FAILURE) {
+       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(sockfd)
-       convert_to_string_ex(addr);
        
-       if (argc > 2) {
-               convert_to_long_ex(port);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_string_ex(arg2);
+       
+       if (argc == 3) {
+               convert_to_long_ex(arg3);
        }
 
        memset(sa, 0, sizeof(sa_storage));
-
        salen = sizeof(sa_storage);
 
-       ret = getsockname(Z_LVAL_PP(sockfd), sa, &salen);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+       if (getsockname(php_sock->socket, sa, &salen) != 0) {
+               php_error(E_WARNING, "failed connecting to [%s], %i", Z_STRVAL_PP(arg2), errno);
+               RETURN_FALSE;
        }
 
        switch(sa->sa_family) {
-               case AF_INET: {
+               case AF_INET:
                        sin = (struct sockaddr_in *)sa;
                        salen = sizeof(struct sockaddr_in);
 
@@ -1044,14 +906,14 @@ PHP_FUNCTION(connect)
                                WRONG_PARAM_COUNT;
                        }
 
-                       sin->sin_port = htons((unsigned short int)Z_LVAL_PP(port));
-                       if (inet_aton(Z_STRVAL_PP(addr), &addr_buf) == 0) {
+                       sin->sin_port = htons((unsigned short int)Z_LVAL_PP(arg3));
+                       if (inet_aton(Z_STRVAL_PP(arg2), &addr_buf) == 0) {
                                sin->sin_addr.s_addr = addr_buf.s_addr;
                        } else {
                                char *q = (char *) &(sin->sin_addr.s_addr);
-                               host_struct = gethostbyname(Z_STRVAL_PP(addr));
+                               host_struct = gethostbyname(Z_STRVAL_PP(arg2));
                                if (host_struct->h_addrtype != AF_INET) {
-                                       RETURN_LONG(-EINVAL);
+                                       RETURN_FALSE;
                                }
                                q[0] = host_struct->h_addr_list[0][0];
                                q[1] = host_struct->h_addr_list[0][1];
@@ -1059,156 +921,161 @@ PHP_FUNCTION(connect)
                                q[3] = host_struct->h_addr_list[0][3];
                        }
        
-                       ret = connect(Z_LVAL_PP(sockfd), (struct sockaddr *) sin, salen);
+                       retval = connect(php_sock->socket, (struct sockaddr *) sin, salen);
                        break;
-               }
-       case AF_UNIX: {
+
+               case AF_UNIX:
                        s_un = (struct sockaddr_un *)sa;
-                       snprintf(s_un->sun_path, 108, "%s", Z_STRVAL_PP(addr));
-                       ret = connect(Z_LVAL_PP(sockfd), (struct sockaddr *) s_un, SUN_LEN(s_un));
+                       snprintf(s_un->sun_path, 108, "%s", Z_STRVAL_PP(arg2));
+                       retval = connect(php_sock->socket, (struct sockaddr *) s_un, SUN_LEN(s_un));
                        break;
+
+               default:
+                       RETURN_FALSE;
+       }       
+       
+       if (retval != 0) {
+               php_error(E_WARNING, "unable to connect, %i", errno);
+               RETURN_FALSE;
        }
-       default:
-               ret = -1;
-               errno = EINVAL;
-       }       
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+
+       RETURN_FALSE;
 }
 /* }}} */
 
-/* {{{ proto string strerror(int errno)
+/* {{{ proto string socket_strerror(int errno)
    Returns a string describing an error */
-PHP_FUNCTION(strerror)
+PHP_FUNCTION(socket_strerror)
 {
-       zval **error;
+       zval **arg1;
        const char *buf;
-
-       if (ZEND_NUM_ARGS() != 1 || 
-           zend_get_parameters_ex(1, &error) == FAILURE) {
+       
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       if (Z_LVAL_PP(error) < -10000) {
-               Z_LVAL_PP(error) += 10000;
-               buf = hstrerror(-(Z_LVAL_PP(error)));
-       } else {
-               buf = strerror(-(Z_LVAL_PP(error)));
-       }
 
-       if (!buf) {
-               RETURN_FALSE;
+#ifndef PHP_WIN32
+       if (Z_LVAL_PP(arg1) < -10000) {
+               Z_LVAL_PP(arg1) += 10000;
+               buf = hstrerror(-(Z_LVAL_PP(arg1)));
+       } else {
+               buf = strerror(-(Z_LVAL_PP(arg1)));
        }
-       
-       RETURN_STRING((char *)buf, 1);
+#else
+       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                               FORMAT_MESSAGE_FROM_SYSTEM |
+                               FORMAT_MESSAGE_IGNORE_INSERTS,
+                               NULL,
+                               Z_LVAL_PP(arg1),
+                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                               (LPTSTR)&buf,
+                               0,
+                               NULL
+                               );
+#endif
+       RETURN_STRING(buf?(char*)buf:"", 1);
 }
 /* }}} */
 
-/* {{{ proto int bind(int sockfd, string addr [, int port])
-   Binds an open socket to a listening port */
-/* Port is only specified if sockfd is in the AF_INET family. */
-PHP_FUNCTION(bind)
+/* {{{ 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 **arg0, **arg1, **arg2;
-       long ret;
+       zval **arg1, **arg2, **arg3;
+       long retval;
        php_sockaddr_storage sa_storage;
-       struct sockaddr *sock_type = (struct sockaddr *) &sa_storage;
+       struct sockaddr *sock_type = (struct sockaddr*) &sa_storage;
        socklen_t length = sizeof(sa_storage);
-       
-       switch (ZEND_NUM_ARGS())
-       {
-               case 2:
-                       if (zend_get_parameters_ex(2, &arg0, &arg1) == FAILURE) {
-                               WRONG_PARAM_COUNT;
-                       }
-                       break;
+       php_socket *php_sock;
+       int argc = ZEND_NUM_ARGS();
+
+
+       if (argc < 2 ||  argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       switch (argc) {
                case 3:
-                       if (zend_get_parameters_ex(3, &arg0, &arg1, &arg2) == FAILURE) {
-                               WRONG_PARAM_COUNT;
-                       }
+                       convert_to_long_ex(arg3);
+               case 2:
+                       convert_to_string_ex(arg2);
+                       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
                        break;
-               default:
-                       WRONG_PARAM_COUNT;
        }
+       
 
-       convert_to_long_ex(arg0);
-
-       ret = getsockname(Z_LVAL_PP(arg0), sock_type, &length);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
-       }
-       if (sock_type->sa_family == AF_UNIX) {
+       if (php_sock->type == AF_UNIX) {
                struct sockaddr_un *sa = (struct sockaddr_un *) sock_type;
-               memset(sa, 0, sizeof(sa_storage)); /* This is safe -> sock_type = &sa_storage -> sa = sock_type */
+               memset(sa, 0, sizeof(sa_storage));
                sa->sun_family = AF_UNIX;
-               snprintf(sa->sun_path, 108, "%s", Z_STRVAL_PP(arg1));
-               ret = bind(Z_LVAL_PP(arg0), (struct sockaddr *) sa, SUN_LEN(sa));
-       } else if (sock_type->sa_family == AF_INET) {
-               struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
-               struct in_addr addr_buf;
+               snprintf(sa->sun_path, 108, "%s", Z_STRVAL_PP(arg2));
+               retval = bind(php_sock->socket, (struct sockaddr *) sa, SUN_LEN(sa));
 
-               memset(sa, 0, sizeof(sa_storage));
+       } else if (php_sock->type == AF_INET) {
+               
+               struct sockaddr_in sa;
+               struct hostent *hp;
 
-               if (ZEND_NUM_ARGS() != 3) {
+               if (argc != 3) {
                        WRONG_PARAM_COUNT;
                }
                
-               sa->sin_port = htons(Z_LVAL_PP(arg2));
-
-               if (inet_aton(Z_STRVAL_PP(arg1), &addr_buf) < 0) {
-                       struct hostent *host_struct;
-
-                       if ((host_struct = gethostbyname(Z_STRVAL_PP(arg1))) == NULL) {
-                               RETURN_LONG(-(h_errno) - 10000);
-                       }
-                       
-                       sa->sin_addr.s_addr = (int) *(host_struct->h_addr_list[0]);
-               } else {
-                       sa->sin_addr.s_addr = addr_buf.s_addr;
+               if ((hp = gethostbyname(Z_STRVAL_PP(arg2))) == NULL) {
+                       php_error(E_WARNING, "unable to lookup [%s], %i", Z_STRVAL_PP(arg2), h_errno);
+                       RETURN_FALSE;
                }
+               
+               memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length);
+               sa.sin_family   = hp->h_addrtype;
+               sa.sin_port             = htons((unsigned short)Z_LVAL_PP(arg3));
+               retval = bind(php_sock->socket, (struct sockaddr *)&sa, sizeof(sa));
 
-               ret = bind(Z_LVAL_PP(arg0), (struct sockaddr *) sa, sizeof(sa_storage));
        } else {
-               RETURN_LONG(-EPROTONOSUPPORT);
+               php_error(E_WARNING,"the specified port is not supported");
+               RETURN_FALSE;
        }
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       if (retval != 0) {
+               php_error(E_WARNING, "unable to bind address, %i", errno);
+               RETURN_FALSE;
+       }
+
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto resource build_iovec(int num_vectors [, int ...])
+/* {{{ proto resource socket_iovec_alloc(int num_vectors [, int ...])
    Builds a 'struct iovec' for use with sendmsg, recvmsg, writev, and readv */
 /* First parameter is number of vectors, each additional parameter is the
    length of the vector to create.
  */
-
-PHP_FUNCTION(build_iovec)
+PHP_FUNCTION(socket_iovec_alloc)
 {
        zval ***args = (zval ***)NULL;
        php_iovec_t *vector;
        struct iovec *vector_array;
-       int i, j, num_vectors, argcount = ZEND_NUM_ARGS();
+       int i, j, num_vectors, argc = ZEND_NUM_ARGS();
        
-       args = emalloc(argcount * sizeof(zval *));
+       args = (zval***)emalloc(argc*sizeof(zval**));
 
-       if (argcount < 1 ||
-           zend_get_parameters_array_ex(argcount, args) == FAILURE) {
-               if (args)
-                       efree(args);
+       if (argc < 1 || zend_get_parameters_array_ex(argc, args) == FAILURE) {
+               efree(args);
                WRONG_PARAM_COUNT;
        }
        
        convert_to_long_ex(args[0]);
        num_vectors = Z_LVAL_PP(args[0]);
        
-       vector_array = emalloc(sizeof(struct iovec) * (num_vectors + 1));
+       vector_array = (struct iovec*)emalloc(sizeof(struct iovec)*(num_vectors+1));
 
        for (i = 0, j = 1; i < num_vectors; i++, j++) {
                convert_to_long_ex(args[j]);
                
-               vector_array[i].iov_base emalloc(Z_LVAL_PP(args[j]));
-               vector_array[i].iov_len = Z_LVAL_PP(args[j]);
+               vector_array[i].iov_base        = (char*)emalloc(Z_LVAL_PP(args[j]));
+               vector_array[i].iov_len         = Z_LVAL_PP(args[j]);
        }
 
-       vector = emalloc(sizeof(php_iovec_t));
+       vector = (php_iovec_t*)emalloc(sizeof(php_iovec_t));
        vector->iov_array = vector_array;
        vector->count = num_vectors;
 
@@ -1216,15 +1083,14 @@ PHP_FUNCTION(build_iovec)
 }
 /* }}} */
 
-/* {{{ proto string fetch_iovec(resource iovec_id, int iovec_position)
+/* {{{ proto string socket_iovec_fetch(resource iovec, int iovec_position)
    Returns the data held in the iovec specified by iovec_id[iovec_position] */
-PHP_FUNCTION(fetch_iovec)
+PHP_FUNCTION(socket_iovec_fetch)
 {
        zval **iovec_id, **iovec_position;
        php_iovec_t *vector;
        
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &iovec_id, &iovec_position) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &iovec_id, &iovec_position) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
@@ -1234,20 +1100,20 @@ PHP_FUNCTION(fetch_iovec)
                php_error(E_WARNING, "Can't access a vector position past the amount of vectors set in the array");
                RETURN_NULL();
        }
+
        RETURN_STRINGL(vector->iov_array[Z_LVAL_PP(iovec_position)].iov_base,
                       vector->iov_array[Z_LVAL_PP(iovec_position)].iov_len, 1);
 }
 /* }}} */
 
-/* {{{ proto bool set_iovec(resource iovec_id, int iovec_position, string new_val)
+/* {{{ proto bool socket_iovec_set(resource iovec, int iovec_position, string new_val)
    Sets the data held in iovec_id[iovec_position] to new_val */
-PHP_FUNCTION(set_iovec)
+PHP_FUNCTION(socket_iovec_set)
 {
        zval **iovec_id, **iovec_position, **new_val;
        php_iovec_t *vector;
        
-       if (ZEND_NUM_ARGS() != 3 || 
-           zend_get_parameters_ex(3, &iovec_id, &iovec_position, &new_val) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &iovec_id, &iovec_position, &new_val) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
@@ -1269,25 +1135,24 @@ PHP_FUNCTION(set_iovec)
 }
 /* }}} */
 
-/* {{{ proto bool add_iovec(resource iovec_id, int iov_len)
+/* {{{ proto bool socket_iovec_add(resource iovec, int iov_len)
    Adds a new vector to the scatter/gather array */
-PHP_FUNCTION(add_iovec)
+PHP_FUNCTION(socket_iovec_add)
 {
        zval **iovec_id, **iov_len;
        php_iovec_t *vector;
        struct iovec *vector_array;
        
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &iovec_id, &iov_len) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &iovec_id, &iov_len) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
        ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov);
 
-       vector_array = emalloc(sizeof(struct iovec) * (vector->count + 2));
+       vector_array = (struct iovec*)emalloc(sizeof(struct iovec) * (vector->count + 2));
        memcpy(vector_array, vector->iov_array, sizeof(struct iovec) * vector->count);
 
-       vector_array[vector->count].iov_base = emalloc(Z_LVAL_PP(iov_len));
+       vector_array[vector->count].iov_base = (char*)emalloc(Z_LVAL_PP(iov_len));
        vector_array[vector->count].iov_len = Z_LVAL_PP(iov_len);
        efree(vector->iov_array);
        vector->iov_array = vector_array;
@@ -1298,17 +1163,16 @@ PHP_FUNCTION(add_iovec)
 
 /* }}} */
 
-/* {{{ proto bool delete_iovec(resource iovec_id, int iov_pos)
+/* {{{ proto bool socket_iovec_delete(resource iovec, int iov_pos)
    Deletes a vector from an array of vectors */
-PHP_FUNCTION(delete_iovec)
+PHP_FUNCTION(socket_iovec_delete)
 {
        zval **iovec_id, **iov_pos;
        php_iovec_t *vector;
        struct iovec *vector_array;
        int i;
        
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &iovec_id, &iov_pos) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &iovec_id, &iov_pos) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
@@ -1318,7 +1182,7 @@ PHP_FUNCTION(delete_iovec)
                php_error(E_WARNING, "Can't delete an IO vector that is out of array bounds");
                RETURN_FALSE;
        }
-       vector_array = emalloc(vector->count * sizeof(struct iovec));
+       vector_array = (struct iovec*)emalloc(vector->count * sizeof(struct iovec));
 
        for (i = 0; i < vector->count; i++) {
                if (i < Z_LVAL_PP(iov_pos)) {
@@ -1336,677 +1200,663 @@ PHP_FUNCTION(delete_iovec)
 
 /* }}} */
 
-/* {{{ proto bool free_iovec(resource iovec_id)
+/* {{{ proto bool socket_iovec_free(resource iovec)
    Frees the iovec specified by iovec_id */
-PHP_FUNCTION(free_iovec)
+PHP_FUNCTION(socket_iovec_free)
 {
-       zval **iovec_id;
+       zval **arg1;
        php_iovec_t *vector;
 
-       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &iovec_id) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
-       ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov);
+       ZEND_FETCH_RESOURCE(vector, php_iovec_t *, arg1, -1, "IO vector table", le_iov);
 
-       zend_list_delete(Z_LVAL_PP(iovec_id));
+       zend_list_delete(Z_RESVAL_PP(arg1));
 
        RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto int readv(int fd, resource iovec_id)
+/* {{{ proto bool socket_readv(resource socket, resource iovec_id)
    Reads from an fd, using the scatter-gather array defined by iovec_id */
-PHP_FUNCTION(readv)
+PHP_FUNCTION(socket_readv)
 {
-       zval **fd, **iovec_id;
+       zval **arg1, **arg2;
        php_iovec_t *vector;
-       int ret;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &fd, &iovec_id) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
-       ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       ZEND_FETCH_RESOURCE(vector, php_iovec_t *, arg2, -1, "IO vector table", le_iov);
 
-       ret = readv(Z_LVAL_PP(fd), vector->iov_array, vector->count);
+       if (readv(php_sock->socket, vector->iov_array, vector->count) != 0) {
+               php_error(E_WARNING, "unable to read, %i", errno);
+               RETURN_FALSE;
+       }
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto int writev(int fd, resource iovec_id)
+/* {{{ proto bool socket_writev(resource socket, resource iovec_id)
    Writes to a file descriptor, fd, using the scatter-gather array defined by iovec_id */
-PHP_FUNCTION(writev)
+PHP_FUNCTION(socket_writev)
 {
-       zval **fd, **iovec_id;
+       zval **arg1, **arg2;
        php_iovec_t *vector;
-       int ret;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 2 || 
-           zend_get_parameters_ex(2, &fd, &iovec_id) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
-       ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov);
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       ZEND_FETCH_RESOURCE(vector, php_iovec_t *, arg2, -1, "IO vector table", le_iov);
 
-       ret = writev(Z_LVAL_PP(fd), vector->iov_array, vector->count);
+       if (writev(php_sock->socket, vector->iov_array, vector->count) != 0) {
+               php_error(E_WARNING, "unable to write, %i", errno);
+               RETURN_FALSE;
+       }
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto int recv(int fd, string buf, int len, int flags)
+/* {{{ proto mixed socket_recv(resource socket, int len, int flags)
    Receives data from a connected socket */
-/* May be used with SOCK_DGRAM sockets. */
-PHP_FUNCTION(recv)
+PHP_FUNCTION(socket_recv)
 {
-       zval **fd, **buf, **len, **flags;
-       int ret;
+       zval **arg1, **arg2, **arg3;
        char *recv_buf;
+       php_socket *php_sock;
+       int retval;
 
-       if (ZEND_NUM_ARGS() != 4 || 
-           zend_get_parameters_ex(4, &fd, &buf, &len, &flags) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(3, fd, len, flags);
-       convert_to_string_ex(buf);
+       
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);      
+       convert_to_long_ex(arg2);
+       convert_to_long_ex(arg3);
 
-       recv_buf = emalloc(Z_LVAL_PP(len) + 2);
-       memset(recv_buf, 0, Z_LVAL_PP(len) + 2);
+       recv_buf = (char*)emalloc(Z_LVAL_PP(arg2) + 2);
+       memset(recv_buf, 0, Z_LVAL_PP(arg2) + 2);
 
-       ret = recv(Z_LVAL_PP(fd), recv_buf, Z_LVAL_PP(len), Z_LVAL_PP(flags));
-       
-       if (ret < 0) {
-               efree(recv_buf);
-               RETURN_LONG(-errno);
-       } else {
-               if (Z_STRLEN_PP(buf) > 0) {
-                       efree(Z_STRVAL_PP(buf));
-               }
-               Z_STRVAL_PP(buf) = estrndup(recv_buf, strlen(recv_buf));
-               Z_STRLEN_PP(buf) = strlen(recv_buf);
+       retval = recv(php_sock->socket, recv_buf, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3));
 
+       if (retval == 0) {
                efree(recv_buf);
-
-               RETURN_LONG(ret);
+               RETURN_FALSE;
        }
+
+       recv_buf[retval+1] = '\0';
+       RETURN_STRING(recv_buf, 0);
 }
 /* }}} */
 
-/* {{{ proto int send(int fd, string buf, int len, int flags)
+/* {{{ proto int socket_send(resource socket, string buf, int len, int flags)
    Sends data to a connected socket */
-/* May be used with SOCK_DGRAM sockets. */
-PHP_FUNCTION(send)
+PHP_FUNCTION(socket_send)
 {
-       zval **fd, **buf, **len, **flags;
-       int ret;
+       zval **arg1, **arg2, **arg3, **arg4;
+       php_socket *php_sock;
+       int retval;
 
-       if (ZEND_NUM_ARGS() != 4 || 
-           zend_get_parameters_ex(4, &fd, &buf, &len, &flags) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(3, fd, len, flags);
-       convert_to_string_ex(buf);
 
-       ret = send(Z_LVAL_PP(fd), Z_STRVAL_PP(buf),
-                  (Z_STRLEN_PP(buf) < Z_LVAL_PP(len) ? Z_STRLEN_PP(buf) : Z_LVAL_PP(len)),
-                  Z_LVAL_PP(flags));
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_long_ex(arg3);
+       convert_to_long_ex(arg4);
+       convert_to_string_ex(arg2);
+
+       retval = send(php_sock->socket, Z_STRVAL_PP(arg2), (Z_STRLEN_PP(arg2) < Z_LVAL_PP(arg3) ? Z_STRLEN_PP(arg2) : Z_LVAL_PP(arg3)), Z_LVAL_PP(arg4));
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_LONG(retval);
 }
 /* }}} */
 
-/* {{{ proto int recvfrom(int fd, string &buf, int len, int flags, string &name [, int &port])
+/* {{{ 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(recvfrom)
+PHP_FUNCTION(socket_recvfrom)
 {
-       zval **fd, **buf, **len, **flags, **name, **port;
-       int ret;
+       zval **arg1, **arg2, **arg3, **arg4, **arg5, **arg6;
        php_sockaddr_storage sa_storage;
+       php_socket *php_sock;
        struct sockaddr *sa = (struct sockaddr *) &sa_storage;
        socklen_t salen;
+       int retval, argc = ZEND_NUM_ARGS();
 
-       switch (ZEND_NUM_ARGS()) 
-       {
-               case 5:
-                       if (zend_get_parameters_ex(5, &fd, &buf, &len, &flags, &name) == FAILURE) {
-                               WRONG_PARAM_COUNT;
-                       }
-                       break;
+
+       if(argc < 5 || argc > 6 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       switch (argc) {
                case 6:
-                       if (zend_get_parameters_ex(6, &fd, &buf, &len, &flags, &name, &port) == FAILURE) {
-                               WRONG_PARAM_COUNT;
-                       }
+                       convert_to_long_ex(arg6);
+               case 5:
+                       convert_to_string_ex(arg5);
+                       convert_to_long_ex(arg4);
+                       convert_to_long_ex(arg3);
+                       convert_to_string_ex(arg2);
+                       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
                        break;
-               default:
-                       WRONG_PARAM_COUNT;
        }
 
        salen = sizeof(sa_storage);
-
-       ret = getsockname(Z_LVAL_PP(fd), sa, &salen);
        
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+       if (getsockname(php_sock->socket, sa, &salen) != 0) {
+               php_error(E_WARNING, "unable to recvfrom, %i", errno);
+               RETURN_LONG(0);
        }
 
-       switch (sa->sa_family)
-       {
+       switch (sa->sa_family) {
                case AF_UNIX:
                        {
                                struct sockaddr_un s_un;
-                               char *recv_buf = emalloc(Z_LVAL_PP(len) + 2);
                                socklen_t sun_length = sizeof(s_un);
-       
-                               if (ZEND_NUM_ARGS() != 5) {
-                                       WRONG_PARAM_COUNT;
-                               }
-                               memset(recv_buf, 0, Z_LVAL_PP(len) + 2);
+                               char *recv_buf = (char*)emalloc(Z_LVAL_PP(arg3) + 2);
 
-                               ret = recvfrom(Z_LVAL_PP(fd), recv_buf, Z_LVAL_PP(len), Z_LVAL_PP(flags),
-                                              (struct sockaddr *)&s_un, (socklen_t *) & sun_length);
+                               memset(recv_buf, 0, Z_LVAL_PP(arg3) + 2);
+                               retval = recvfrom(php_sock->socket, recv_buf, Z_LVAL_PP(arg3), Z_LVAL_PP(arg4),
+                                       (struct sockaddr *)&s_un, (socklen_t *) & sun_length);
 
-                               if (ret < 0) {
+                               if (retval < 0) {
                                        efree(recv_buf);
-                                       RETURN_LONG(-errno);
+                                       php_error(E_WARNING, "unable to recvfrom, %i", errno);
+                                       RETURN_FALSE;
                                }
-                               
-                               if (Z_STRVAL_PP(buf) != NULL) {
-                                       efree(Z_STRVAL_PP(buf));
+
+                               if (Z_STRVAL_PP(arg2) != NULL) {
+                                       efree(Z_STRVAL_PP(arg2));
                                }
                                
-                               Z_STRVAL_PP(buf) = estrndup(recv_buf, strlen(recv_buf));
-                               Z_STRLEN_PP(buf) = strlen(recv_buf);
-
-                               if (Z_STRLEN_PP(name) > 0) {
-                                       efree(Z_STRVAL_PP(name));
+                               Z_STRVAL_PP(arg2) = estrndup(recv_buf, strlen(recv_buf));
+                               Z_STRLEN_PP(arg2) = strlen(recv_buf);
+                               
+                               if (Z_STRLEN_PP(arg5) > 0) {
+                                       efree(Z_STRVAL_PP(arg5));
                                }
                                
-                               Z_STRVAL_PP(name) = estrdup(s_un.sun_path);
-                               Z_STRLEN_PP(name) = strlen(s_un.sun_path);
-
+                               Z_STRVAL_PP(arg5) = estrdup(s_un.sun_path);
+                               Z_STRLEN_PP(arg5) = strlen(s_un.sun_path);
                                efree(recv_buf);
-
-                               RETURN_LONG(ret);
                        }
-                       break;
+       
+                                               
                case AF_INET:
                        {
                                struct sockaddr_in sin;
-                               char *recv_buf = emalloc(Z_LVAL_PP(len) + 2);
+                               char *recv_buf = (char*)emalloc(Z_LVAL_PP(arg3) + 2);
                                socklen_t sin_length = sizeof(sin);
                                char *address;
 
-                               if (ZEND_NUM_ARGS() != 6) {
+                               if (argc != 6) {
                                        WRONG_PARAM_COUNT;
                                }
-                               memset(recv_buf, 0, Z_LVAL_PP(len) + 2);
-
-                               ret = recvfrom(Z_LVAL_PP(fd), recv_buf, Z_LVAL_PP(len), Z_LVAL_PP(flags),
-                                              (struct sockaddr *)&sin, (socklen_t *) & sin_length);
-       
-                               if (ret < 0) {
+                               
+                               memset(recv_buf, 0, Z_LVAL_PP(arg3) + 2);
+                               retval = recvfrom(php_sock->socket, recv_buf, Z_LVAL_PP(arg3), Z_LVAL_PP(arg4),
+                                       (struct sockaddr *)&sin, (socklen_t *) & sin_length);
+                               
+                               if (retval < 0) {
                                        efree(recv_buf);
-                                       RETURN_LONG(-errno);
+                                       php_error(E_WARNING, "unable to recvfrom, %i", errno);
+                                       RETURN_FALSE;
                                }
                                
-                               if (Z_STRLEN_PP(buf) > 0) {
-                                       efree(Z_STRVAL_PP(buf));
+                               if (Z_STRLEN_PP(arg2) > 0) {
+                                       efree(Z_STRVAL_PP(arg2));
                                }
+
+                               Z_STRVAL_PP(arg2) = estrdup(recv_buf);
+                               Z_STRLEN_PP(arg2) = strlen(recv_buf);
                                
-                               if (Z_STRLEN_PP(name) > 0) {
-                                       efree(Z_STRVAL_PP(name));
+                               if (Z_STRLEN_PP(arg5) > 0) {
+                                       efree(Z_STRVAL_PP(arg5));
                                }
                                
-                               Z_STRVAL_PP(buf) = estrdup(recv_buf);
-                               Z_STRLEN_PP(buf) = strlen(recv_buf);
-
                                address = inet_ntoa(sin.sin_addr);
                                if (address == NULL) {
-                                       Z_STRVAL_PP(name) = estrdup("0.0.0.0");
-                                       Z_STRLEN_PP(name) = strlen(Z_STRVAL_PP(name));
+                                       Z_STRVAL_PP(arg5) = estrdup("0.0.0.0");
+                                       Z_STRLEN_PP(arg5) = strlen(Z_STRVAL_PP(arg5));
                                } else {
-                                       Z_STRVAL_PP(name) = estrdup(address);
-                                       Z_STRLEN_PP(name) = strlen(address);
+                                       Z_STRVAL_PP(arg5) = estrdup(address);
+                                       Z_STRLEN_PP(arg5) = strlen(address);
                                }
                                
-                               Z_LVAL_PP(port) = ntohs(sin.sin_port);;
-       
+                               Z_LVAL_PP(arg6) = ntohs(sin.sin_port);
                                efree(recv_buf);
-                               RETURN_LONG(ret);
                        }
-                       break;
+
                default:
-                       RETURN_LONG(-EPROTONOSUPPORT);
+                       RETURN_FALSE;
        }
+
+       RETURN_LONG(retval);
 }
 /* }}} */
 
-/* {{{ proto int sendto(int fd, string buf, int len, int flags, string addr [, int port])
+/* {{{ 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(sendto)
+PHP_FUNCTION(socket_sendto)
 {
-       zval **fd, **buf, **len, **flags, **addr, **port;
+       zval **arg1, **arg2, **arg3, **arg4, **arg5, **arg6;
        php_sockaddr_storage sa_storage;
+       php_socket *php_sock;
        struct sockaddr *sa = (struct sockaddr *) &sa_storage;
        socklen_t salen = sizeof(sa_storage);
-       int ret;
-
-       switch (ZEND_NUM_ARGS())
-       {
-               case 5:
-                       ret = zend_get_parameters_ex(5, &fd, &buf, &len, &flags, &addr);
-                       break;
-               case 6:
-                       ret = zend_get_parameters_ex(6, &fd, &buf, &len, &flags, &addr, &port);
-                       break;
-               default:
-                       ret = FAILURE;
-       }
+       int retval, argc = ZEND_NUM_ARGS();
 
-       if (ret == FAILURE) {
+       if(argc < 5 || argc > 6 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(3, fd, len, flags);
-       convert_to_string_ex(buf);
 
-       if (ZEND_NUM_ARGS() == 6) {
-               convert_to_long_ex(port);
+       switch (argc) {
+               case 6:
+                       convert_to_long_ex(arg6);
+               case 5:
+                       convert_to_string_ex(arg5);
+                       convert_to_long_ex(arg4);
+                       convert_to_long_ex(arg3);
+                       convert_to_string_ex(arg2);
+                       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+                       break;
        }
 
-       ret = getsockname(Z_LVAL_PP(fd), sa, &salen);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+
+       if (getsockname(php_sock->socket, sa, &salen) != 0) {
+               php_error(E_WARNING, "unable to sendto, %i", errno);
+               RETURN_LONG(0);
        }
 
-       switch (sa->sa_family)
-       {
+       switch (sa->sa_family) {
                case AF_UNIX:
                        {
                                struct sockaddr_un s_un;
-       
-                               if (ZEND_NUM_ARGS() != 5) {
-                                       WRONG_PARAM_COUNT;
-                               }
+                               int which;
+
                                memset(&s_un, 0, sizeof(s_un));
                                s_un.sun_family = AF_UNIX;
-                               snprintf(s_un.sun_path, 108, "%s", Z_STRVAL_PP(addr));
-                               ret = sendto(Z_LVAL_PP(fd), Z_STRVAL_PP(buf),
-                                            (Z_STRLEN_PP(buf) > Z_LVAL_PP(len) ? Z_LVAL_PP(len) : Z_STRLEN_PP(buf)),
-                                            Z_LVAL_PP(flags), (struct sockaddr *) &s_un, SUN_LEN(&s_un));
-
-                               RETURN_LONG(((ret < 0) ? -errno : ret));
+                               snprintf(s_un.sun_path, 108, "%s", Z_STRVAL_PP(arg5));
+                               
+                               which = (Z_STRLEN_PP(arg2) > Z_LVAL_PP(arg3)) ? 1 : 0;
+                               retval = sendto(php_sock->socket, Z_STRVAL_PP(arg2), (which ? Z_LVAL_PP(arg3) : Z_STRLEN_PP(arg2)),
+                                       Z_LVAL_PP(arg4), (struct sockaddr *) &s_un, SUN_LEN(&s_un));
                        }
-                       break;
+
                case AF_INET:
                        {
                                struct sockaddr_in sin;
                                struct in_addr addr_buf;
+                               int which;
 
-                               if (ZEND_NUM_ARGS() != 6) {
+                               if (argc != 6) {
                                        WRONG_PARAM_COUNT;
                                }
+
                                memset(&sin, 0, sizeof(sin));
                                sin.sin_family = AF_INET;
        
-                               if (inet_aton(Z_STRVAL_PP(addr), &addr_buf) == 0) {
+                               if (inet_aton(Z_STRVAL_PP(arg5), &addr_buf) == 0) {
                                        sin.sin_addr.s_addr = addr_buf.s_addr;
                                } else {
                                        struct hostent *he;
 
-                                       he = gethostbyname(Z_STRVAL_PP(addr));
+                                       he = gethostbyname(Z_STRVAL_PP(arg4));
+
                                        if (he == NULL) {
-                                               RETURN_LONG(-(h_errno) - 10000);
+                                               php_error(E_WARNING, "unable to sendto, %i", h_errno);
+                                               RETURN_FALSE;
                                        }
+
                                        sin.sin_addr.s_addr = *(int *) (he->h_addr_list[0]);
                                }
-                               sin.sin_port = htons(Z_LVAL_PP(port));
-                               ret = sendto(Z_LVAL_PP(fd), Z_STRVAL_PP(buf),
-                                            (Z_STRLEN_PP(buf) > Z_LVAL_PP(len) ? Z_LVAL_PP(len) : Z_STRLEN_PP(buf)),
-                                            Z_LVAL_PP(flags), (struct sockaddr *) &sin, sizeof(sin));
-                               
-                               RETURN_LONG(((ret < 0) ? -errno : ret));
+
+                               sin.sin_port = htons((unsigned short)Z_LVAL_PP(arg6));
+                               which = (Z_STRLEN_PP(arg2) > Z_LVAL_PP(arg3)) ? 1 : 0;
+                               retval = sendto(php_sock->socket, Z_STRVAL_PP(arg2), (which ? Z_LVAL_PP(arg3) : Z_STRLEN_PP(arg2)),
+                                       Z_LVAL_PP(arg4), (struct sockaddr *) &sin, sizeof(sin));
                        }
-                       break;
+
                default:
-                       RETURN_LONG(-EPROTONOSUPPORT);
-                       break;
+                       RETURN_LONG(0);
        }
+
+       RETURN_LONG(retval);
 }
 /* }}} */
 
-/* {{{ proto int recvmsg(int fd, resource iovec, array &control, int &controllen, int &flags, string &addr [, int &port])
+/* {{{ proto bool socket_recvmsg(resource socket, resource iovec, array &control, int &controllen, int &flags, string &addr [, int &port])
    Used to receive messages on a socket, whether connection-oriented or not */
-PHP_FUNCTION(recvmsg)
+PHP_FUNCTION(socket_recvmsg)
 {
-       zval **fd, **iovec, **control, **controllen, **flags, **addr, **port;
+       zval **arg1, **arg2, **arg3, **arg4, **arg5, **arg6, **arg7;
        zval *control_array = NULL;
        php_iovec_t *iov;
        struct msghdr hdr;
        php_sockaddr_storage sa_storage;
+       php_socket *php_sock;
        struct sockaddr *sa = (struct sockaddr *) &sa_storage;
        struct sockaddr_in *sin = (struct sockaddr_in *) sa;
        struct sockaddr_un *s_un = (struct sockaddr_un *) sa;
        struct cmsghdr *ctl_buf;
        socklen_t salen = sizeof(sa_storage);
-       int ret;
-
-       switch (ZEND_NUM_ARGS())
-       {
-               case 6:
-                       ret = zend_get_parameters_ex(6, &fd, &iovec, &control, &controllen, &flags, &addr);
-                       break;
-               case 7:
-                       ret = zend_get_parameters_ex(7, &fd, &iovec, &control, &controllen, &flags, &addr, &port);
-                       break;
-               default:
-                       WRONG_PARAM_COUNT;
-       }
+       int argc = ZEND_NUM_ARGS();
 
-       if (ret == FAILURE) {
+       if(argc < 6 || argc > 7 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
-       multi_convert_to_long_ex(3, fd, controllen, flags);
-       convert_to_string_ex(control);
-       convert_to_string_ex(addr);
-       if (ZEND_NUM_ARGS() == 7) {
-               convert_to_long_ex(port);
+       switch (argc) {
+               case 7:
+                       convert_to_long_ex(arg7);
+               case 6:
+                       convert_to_string_ex(arg6);
+                       convert_to_long_ex(arg5);
+                       convert_to_long_ex(arg4);
+                       convert_to_array_ex(arg3);
+                       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);                      
+                       ZEND_FETCH_RESOURCE(iov, php_iovec_t *, arg2, -1, "IO vector table", le_iov);
+                       break;
        }
 
-       ZEND_FETCH_RESOURCE(iov, php_iovec_t *, iovec, -1, "IO vector table", le_iov);
-
-       ret = getsockname(Z_LVAL_PP(fd), sa, &salen);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+       if (getsockname(php_sock->socket, sa, &salen) != 0) {
+               php_error(E_WARNING, "unable to recvms, %i", errno);
+               RETURN_FALSE;
        }
        
-       if (Z_LVAL_PP(controllen) > sizeof(struct cmsghdr)) {
-               ctl_buf = emalloc(Z_LVAL_PP(controllen));
-       } else {
-               ctl_buf = NULL;
-       }
+       ctl_buf = (Z_LVAL_PP(arg4) > sizeof(struct cmsghdr)) ? (struct cmsghdr*)emalloc(Z_LVAL_PP(arg4)) : NULL;
+       MAKE_STD_ZVAL(control_array);
 
-       switch (sa->sa_family)
-       {
+       switch (sa->sa_family) {
                case AF_INET:
-                       {
-                               if (ZEND_NUM_ARGS() != 7) {
-                                       efree(ctl_buf);
-                                       WRONG_PARAM_COUNT;
-                               }
-                               memset(sa, 0, sizeof(sa_storage));
-                               hdr.msg_name = sin;
-                               hdr.msg_namelen = sizeof(sa_storage);
-                               hdr.msg_iov = iov->iov_array;
-                               hdr.msg_iovlen = iov->count;
-
-                               if (ctl_buf) {
-                                       hdr.msg_control = ctl_buf;
-                                       hdr.msg_controllen = Z_LVAL_PP(controllen);
-                               } else {
-                                       hdr.msg_control = NULL;
-                                       hdr.msg_controllen = 0;
-                               }
-
-                               hdr.msg_flags = 0;
-       
-                               ret = recvmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags));
-                               if (ret < 0) {
-                                       RETURN_LONG(-errno);
-                               } else {
-                                       struct cmsghdr *mhdr = (struct cmsghdr *) hdr.msg_control;
-
-                                       /* copy values as appropriate... */
-                                       if (array_init(control_array) == FAILURE) {
-                                               php_error(E_WARNING, "Cannot intialize array");
-                                               RETURN_FALSE;
-                                       }
-                                       add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level);
-                                       add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type);
-                                       add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1);
-                                       *control = control_array;
-                                       zval_copy_ctor(*control);
-                                       
-                                       Z_LVAL_PP(controllen) = hdr.msg_controllen;
-                                       Z_LVAL_PP(flags)      = hdr.msg_flags;
-                                       if (Z_STRLEN_PP(addr) > 0) {
-                                               efree(Z_STRVAL_PP(addr));
-                                       } 
-                                       {
-                                               char *tmp = inet_ntoa(sin->sin_addr);
-       
-                                               if (tmp == NULL) {
-                                                       Z_STRVAL_PP(addr) = estrdup("0.0.0.0");
-                                               } else {
-                                                       Z_STRVAL_PP(addr) = estrdup(tmp);
-                                               }
-                                       }
-                                       Z_STRLEN_PP(addr) = strlen(Z_STRVAL_PP(addr));
-                                       Z_LVAL_PP(port)   = ntohs(sin->sin_port);
-                                       RETURN_LONG(ret);
-                               }
-                       }
-                       break;
-       case AF_UNIX:
-               {
-                       if (ZEND_NUM_ARGS() != 6) {
+                       
+                       if (ZEND_NUM_ARGS() != 7) {
                                efree(ctl_buf);
                                WRONG_PARAM_COUNT;
                        }
+                       
                        memset(sa, 0, sizeof(sa_storage));
-                       hdr.msg_name = s_un;
-                       hdr.msg_namelen = sizeof(struct sockaddr_un);
+                       hdr.msg_name = sin;
+                       hdr.msg_namelen = sizeof(sa_storage);
                        hdr.msg_iov = iov->iov_array;
                        hdr.msg_iovlen = iov->count;
 
-                       if (ctl_buf) {
-                               hdr.msg_control = ctl_buf;
-                               hdr.msg_controllen = Z_LVAL_PP(controllen);
-                       } else {
-                               hdr.msg_control = NULL;
-                               hdr.msg_controllen = 0;
-                       }
-
+                       hdr.msg_control = ctl_buf ? ctl_buf : NULL;
+                       hdr.msg_controllen = ctl_buf ? Z_LVAL_PP(arg4) : 0;
                        hdr.msg_flags = 0;
-
-                       ret = recvmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags));
-                       if (ret < 0) {
-                               RETURN_LONG(-errno);
+       
+                       if (recvmsg(php_sock->socket, &hdr, Z_LVAL_PP(arg5)) != 0) {
+                               php_error(E_WARNING, "unable to recvmsg, %i", errno);
+                               RETURN_FALSE;
                        } else {
                                struct cmsghdr *mhdr = (struct cmsghdr *) hdr.msg_control;
+                               
+                               /* copy values as appropriate... */
+                               if (array_init(control_array) == FAILURE) {
+                                       php_error(E_WARNING, "Cannot intialize array");
+                                       RETURN_FALSE;
+                               }
+                               
+                               add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level);
+                               add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type);
+                               add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1);
+                               *arg3 = control_array;
+                               zval_copy_ctor(*arg3);
+                                       
+                               Z_LVAL_PP(arg4) = hdr.msg_controllen;
+                               Z_LVAL_PP(arg5) = hdr.msg_flags;
 
-                               if (mhdr != NULL) {
-                                       /* copy values as appropriate... */
-                                       if (array_init(control_array) == FAILURE) {
-                                               php_error(E_WARNING, "Cannot initialize return value from recvmsg()");
-                                               RETURN_FALSE;
+                               if (Z_STRLEN_PP(arg6) > 0) {
+                                       efree(Z_STRVAL_PP(arg6));
+                               }
+                               
+                               {
+                                       char *tmp = inet_ntoa(sin->sin_addr);
+                                       if (tmp == NULL) {
+                                               Z_STRVAL_PP(arg6) = estrdup("0.0.0.0");
+                                       } else {
+                                               Z_STRVAL_PP(arg6) = estrdup(tmp);
                                        }
-                                       add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level);
-                                       add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type);
-                                       add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1);
-                                       *control = control_array;
-                                       Z_LVAL_PP(controllen) = hdr.msg_controllen;
                                }
-                               Z_LVAL_PP(flags)      = hdr.msg_flags;
-                               if (Z_STRVAL_PP(addr) != NULL) {
-                                       efree(Z_STRVAL_PP(addr));
+
+                               Z_STRLEN_PP(arg6) = strlen(Z_STRVAL_PP(arg6));
+                               Z_LVAL_PP(arg7)   = ntohs(sin->sin_port);
+                               RETURN_TRUE;
+                       }
+
+       case AF_UNIX:
+               memset(sa, 0, sizeof(sa_storage));
+               hdr.msg_name = s_un;
+               hdr.msg_namelen = sizeof(struct sockaddr_un);
+               hdr.msg_iov = iov->iov_array;
+               hdr.msg_iovlen = iov->count;
+               
+               if (ctl_buf) {
+                       hdr.msg_control = ctl_buf;
+                       hdr.msg_controllen = Z_LVAL_PP(arg4);
+               } else {
+                       hdr.msg_control = NULL;
+                       hdr.msg_controllen = 0;
+               }
+
+               hdr.msg_flags = 0;
+       
+               if (recvmsg(php_sock->socket, &hdr, Z_LVAL_PP(arg5)) != 0) {
+                       php_error(E_WARNING, "unable to recvmsg, %i", errno);
+                       RETURN_FALSE;
+               } else {
+                       struct cmsghdr *mhdr = (struct cmsghdr *) hdr.msg_control;
+                       
+                       if (mhdr != NULL) {
+                               /* copy values as appropriate... */
+                               if (array_init(control_array) == FAILURE) {
+                                       php_error(E_WARNING, "Cannot initialize return value from recvmsg()");
+                                       RETURN_FALSE;
                                }
-                               Z_STRVAL_PP(addr) = estrdup(s_un->sun_path);
-                               RETURN_LONG(ret);
+                               
+                               add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level);
+                               add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type);
+                               add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1);
+                               *arg3 = control_array;
+                               Z_LVAL_PP(arg4) = hdr.msg_controllen;
+                       }
+
+                       Z_LVAL_PP(arg5)      = hdr.msg_flags;
+                       
+                       if (Z_STRVAL_PP(arg6) != NULL) {
+                               efree(Z_STRVAL_PP(arg6));
                        }
+
+                       Z_STRVAL_PP(arg6) = estrdup(s_un->sun_path);
+                       RETURN_TRUE;
                }
-               break;
        default:
-               RETURN_LONG(-EPROTONOSUPPORT);
+               RETURN_FALSE;
        }
 }
 /* }}} */
 
-/* {{{ proto int sendmsg(int fd, resource iovec, int flags, string addr [, int port])
+/* {{{ proto bool socket_sendmsg(resource socket, resource iovec, int flags, string addr [, int port])
    Sends a message to a socket, regardless of whether it is connection-oriented or not */
-PHP_FUNCTION(sendmsg)
+PHP_FUNCTION(socket_sendmsg)
 {
-       zval **fd, **iovec, **flags, **addr, **port;
+       zval **arg1, **arg2, **arg3, **arg4, **arg5;
        php_iovec_t *iov;
-       int ret, argc = ZEND_NUM_ARGS();
+       php_socket *php_sock;
+       int argc = ZEND_NUM_ARGS();
        struct sockaddr sa;
        int salen;
 
-       if (argc < 4 || argc > 5 ||
-           zend_get_parameters_ex(argc, &fd, &iovec, &flags, &addr, &port) == FAILURE) {
+       if (argc < 4 || argc > 5 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3, &arg4, &arg5) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
-       salen = sizeof(sa);
-       ret = getsockname(Z_LVAL_PP(fd), &sa, &salen);
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+       switch (argc) {
+               case 5:
+                       convert_to_long_ex(arg5);
+               case 4:
+                       convert_to_string_ex(arg4);
+                       convert_to_long_ex(arg3);
+                       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+                       ZEND_FETCH_RESOURCE(iov, php_iovec_t *, arg2, -1, "IO vector table", le_iov);
+                       break;
        }
 
-       ZEND_FETCH_RESOURCE(iov, php_iovec_t *, iovec, -1, "IO vector table", le_iov);
+       salen = sizeof(sa);
+       if (getsockname(php_sock->socket, &sa, &salen) != 0) {
+               php_error(E_WARNING, "unable to sendmsg, %i", errno);
+               RETURN_FALSE;
+       }
 
-       switch(sa.sa_family)
-       {
+       switch(sa.sa_family) {
                case AF_INET:
                        {
                                struct msghdr hdr;
                                struct sockaddr_in *sin = (struct sockaddr_in *) &sa;
-                               h_errno = 0;
-                               errno = 0;
+
+                               set_h_errno(0);
+                               set_errno(0);
+
                                memset(&hdr, 0, sizeof(hdr));
                                hdr.msg_name = &sa;
                                hdr.msg_namelen = sizeof(sa);
                                hdr.msg_iov = iov->iov_array;
                                hdr.msg_iovlen = iov->count;
                                
-                               if (inet_aton(Z_STRVAL_PP(addr), &sin->sin_addr) != 0) {
-                                       struct hostent *he = gethostbyname(Z_STRVAL_PP(addr));
+                               if (inet_aton(Z_STRVAL_PP(arg4), &sin->sin_addr) != 0) {
+                                       struct hostent *he = gethostbyname(Z_STRVAL_PP(arg4));
                                        if (!he) {
-                                               RETURN_LONG(h_errno > 0 ? -(h_errno) - 10000 : -errno)
+                                               php_error(E_WARNING, "unable to sendmsg, %i", h_errno);
+                                               RETURN_FALSE;
                                        }
                                        sin->sin_addr.s_addr = *(int *)(he->h_addr_list[0]);
                                }
 
-                               sin->sin_port = htons(Z_LVAL_PP(port));
-                               ret = sendmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags));
+                               sin->sin_port = htons((unsigned short)Z_LVAL_PP(arg5));
                                
-                               RETURN_LONG(((ret < 0) ? -errno : ret));
+                               if(sendmsg(php_sock->socket, &hdr, Z_LVAL_PP(arg3)) != 0) {
+                                       php_error(E_WARNING, "unable to sendmsg, %i", errno);
+                               }
+
+                               RETURN_TRUE;
                        }
-                       break;
+
                case AF_UNIX:
                        {
                                struct msghdr hdr;
                                struct sockaddr_un *s_un = (struct sockaddr_un *) &sa;
-                               errno = 0;
+
+                               set_errno(0);
+
                                hdr.msg_name = s_un;
                                hdr.msg_iov = iov->iov_array;
                                hdr.msg_iovlen = iov->count;
 
-                               snprintf(s_un->sun_path, 108, "%s", Z_STRVAL_PP(addr));
+                               snprintf(s_un->sun_path, 108, "%s", Z_STRVAL_PP(arg4));
 
                                hdr.msg_namelen = SUN_LEN(s_un);
 
-                               ret = sendmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags));
+                               if(sendmsg(php_sock->socket, &hdr, Z_LVAL_PP(arg3)) != 0) {
+                                       php_error(E_WARNING, "unable to sendmsg, %i", errno);
+                                       RETURN_FALSE;
+                               }
                                
-                               RETURN_LONG(((ret < 0) ? -errno : ret));
+                               RETURN_TRUE;
                        }
-                       break;
+
                default:
-                       RETURN_LONG(-EPROTONOSUPPORT);
+                       RETURN_FALSE;
        }
 }
 /* }}} */
 
-/* {{{ proto int getsockopt(int fd, int level, int optname, array|int &optval)
+/* {{{ proto mixed socket_getopt(resource socket, int level, int optname)
    Gets socket options for the socket */
-/* If optname is SO_LINGER, optval is returned as an array with members 
-   "l_onoff" and "l_linger", otherwise it is an integer.
-*/
-PHP_FUNCTION(getsockopt)
+PHP_FUNCTION(socket_getopt)
 {
-       zval **fd, **level, **optname, **optval;
+       zval **arg1, **arg2, **arg3;
        struct linger linger_val;
        int other_val;
        socklen_t optlen;
-       int ret;
+       php_socket *php_sock;
 
-       fd = level = optname = optval = NULL;
-
-       if (ZEND_NUM_ARGS() != 4 || 
-           zend_get_parameters_ex(4, &fd, &level, &optname, &optval) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
 
-       multi_convert_to_long_ex(3, fd, level, optname);
-       /* optname is set on the way out .. */
-
-       if (Z_LVAL_PP(level) == SO_LINGER) {
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_long_ex(arg2);
+       convert_to_long_ex(arg3);
+       
+       if (Z_LVAL_PP(arg2) == SO_LINGER) {
                zval *optval_array = NULL;
                optlen = sizeof(struct linger);
-               ret = getsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &linger_val, &optlen);
 
-               if (ret < 0) {
-                       RETURN_LONG(-errno);
+               if (getsockopt(php_sock->socket, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3), (char*)&linger_val, &optlen) != 0) {
+                       php_error(E_WARNING, "unable to retrieve socket option, %i", errno);
+                       RETURN_FALSE;
                }
 
-               if (array_init(optval_array) == FAILURE) {
-                       php_error(E_WARNING, "Cannot initialize array from getsockopt()");
+               if (array_init(return_value) == FAILURE) {
                        RETURN_FALSE;
                }
-               add_assoc_long(optval_array, "l_onoff", linger_val.l_onoff);
-               add_assoc_long(optval_array, "l_linger", linger_val.l_linger);
+               add_assoc_long(return_value, "l_onoff", linger_val.l_onoff);
+               add_assoc_long(return_value, "l_linger", linger_val.l_linger);
 
-               *optval = optval_array;
-               RETURN_LONG(ret);
        } else {
                optlen = sizeof(other_val);
-               ret = getsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &other_val, &optlen);
-               if (ret < 0) {
-                       RETURN_LONG(-errno);
+               
+               if (getsockopt(php_sock->socket, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3), (char*)&other_val, &optlen) != 0) {
+                       php_error(E_WARNING, "unable to retrieve socket option, %i", errno);
+                       RETURN_FALSE;
                }
 
-               Z_LVAL_PP(optval) = other_val;
-               RETURN_LONG(ret);
+               RETURN_LONG(other_val);
        }
 }
 /* }}} */
 
-/* {{{ proto int setsockopt(int fd, int level, int optname, int|array optval)
+/* {{{ proto bool socket_setopt(resource socket, int level, int optname, int|array optval)
    Sets socket options for the socket */
-/* If optname is SO_LINGER, optval is expected to be an array
-   with members "l_onoff" and "l_linger", otherwise it should be an integer. */
-PHP_FUNCTION(setsockopt)
+PHP_FUNCTION(socket_setopt)
 {
-       zval **fd, **level, **optname, **optval;
-       int ret;
+       zval **arg1, **arg2, **arg3, **arg4;
        struct linger lv;
-       int ov;
-       int optlen;
-       errno = 0;
+       int ov, optlen, retval;
+       php_socket *php_sock;
 
-       if (ZEND_NUM_ARGS() != 4 || 
-           zend_get_parameters_ex(4, &fd, &level, &optname, &optval) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
+       
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
+       convert_to_long_ex(arg2);
+       convert_to_long_ex(arg3);
 
-       multi_convert_to_long_ex(3, fd, level, optname);
+       set_errno(0);
 
-       if (Z_LVAL_PP(optname) == SO_LINGER) {
+       if (Z_LVAL_PP(arg3) == SO_LINGER) {
                HashTable *ht;
                zval **l_onoff;
                zval **l_linger;
 
-               convert_to_array_ex(optval);
-               ht = HASH_OF(*optval);
+               convert_to_array_ex(arg4);
+               ht = HASH_OF(*arg4);
 
                if (zend_hash_find(ht, "l_onoff", strlen("l_onoff") + 1, (void **)&l_onoff) == FAILURE) {
                        php_error(E_WARNING, "No key \"l_onoff\" passed in optval");
                        RETURN_FALSE;
                }
-               if (zend_hash_find(ht, "l_linger", strlen("l_linger") + 1, (void **) &l_linger) == FAILURE) {
+               if (zend_hash_find(ht, "l_linger", strlen("l_linger") + 1, (void **)&l_linger) == FAILURE) {
                        php_error(E_WARNING, "No key \"l_linger\" passed in optval");
                        RETURN_FALSE;
                }
@@ -2014,98 +1864,128 @@ PHP_FUNCTION(setsockopt)
                convert_to_long_ex(l_onoff);
                convert_to_long_ex(l_linger);
 
-               lv.l_onoff Z_LVAL_PP(l_onoff);
-               lv.l_linger = Z_LVAL_PP(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);
-               ret = setsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &lv, optlen);
+               
+               retval = setsockopt(php_sock->socket, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3), (char*)&lv, optlen);
+
        } else {
-               convert_to_long_ex(optval);
+               convert_to_long_ex(arg4);
 
                optlen = sizeof(ov);
-               ov = Z_LVAL_PP(optval);
+               ov = Z_LVAL_PP(arg3);
+
+               retval = setsockopt(php_sock->socket, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3), (char*)&ov, optlen);
+       }
 
-               ret = setsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &ov, optlen);
+       if(retval != 0) {
+               php_error(E_WARNING, "unable to set socket option, %i", errno);
+               RETURN_FALSE;
        }
 
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto int socketpair(int domain, int type, int protocol, array &fds)
+/* {{{ proto bool socket_create_pair(int domain, int type, int protocol, array &fd)
    Creates a pair of indistinguishable sockets and stores them in fds. */
-PHP_FUNCTION(socketpair)
+PHP_FUNCTION(socket_create_pair)
 {
-       zval **domain, **type, **protocol, **fds;
-       int ret, fds_ar[2];
+       zval **arg1, **arg2, **arg3, **arg4;
+       zval *retval[2];
+       php_socket *php_sock[2];
+
+#ifndef PHP_WIN32
+       int fds_array[2];
+#else
+       SOCKET fds_array[2];
+#endif
        
-       if (ZEND_NUM_ARGS() != 4 ||
-           zend_get_parameters_ex(4, &domain, &type, &protocol, &fds) == FAILURE) {
+       if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       multi_convert_to_long_ex(3, domain, type, protocol);
+       
+       convert_to_long_ex(arg1);
+       convert_to_long_ex(arg2);
+       convert_to_long_ex(arg3);
+       convert_to_array_ex(arg4);
+
+       php_sock[0]= (php_socket*)emalloc(sizeof(php_socket));
+       php_sock[1]= (php_socket*)emalloc(sizeof(php_socket));
 
-       if (Z_LVAL_PP(domain) != AF_INET && Z_LVAL_PP(domain) != AF_UNIX) {
-               php_error(E_WARNING, "invalid socket domain specified -- assuming AF_INET");
-               Z_LVAL_PP(domain) = AF_INET;
+       if (Z_LVAL_PP(arg1) != AF_INET && Z_LVAL_PP(arg2) != AF_UNIX) {
+               php_error(E_WARNING, "invalid socket domain specified, assuming AF_INET");
+               Z_LVAL_PP(arg1) = AF_INET;
        }
        
-       if (Z_LVAL_PP(type) > 10) {
-               php_error(E_WARNING, "Invalid socket type specified - assuming SOCK_STREAM");
-               Z_LVAL_PP(type) = SOCK_STREAM;
+       if (Z_LVAL_PP(arg2) > 10) {
+               php_error(E_WARNING, "Invalid socket type specified, assuming SOCK_STREAM");
+               Z_LVAL_PP(arg2) = SOCK_STREAM;
        }
        
-       /* Initialize the array */
-       if (array_init(*fds) == FAILURE) {
+       if (array_init(*arg4) == FAILURE) {
                php_error(E_WARNING, "Can't initialize fds array");
                RETURN_FALSE;
        }
-       
-       /* Get the sockets */
-       ret = socketpair(Z_LVAL_PP(domain), Z_LVAL_PP(type), Z_LVAL_PP(protocol), fds_ar);
-       
-       if (ret < 0) {
-               RETURN_LONG(-errno);
+
+       if (socketpair(Z_LVAL_PP(arg1), Z_LVAL_PP(arg2), Z_LVAL_PP(arg3), fds_array) != 0) {
+               php_error(E_WARNING, "unable to create socket pair, %i", errno);
+               RETURN_FALSE;
        }
 
-       /* Put them into the array */
-       add_index_long(*fds, 0, fds_ar[0]);
-       add_index_long(*fds, 1, fds_ar[1]);
+       MAKE_STD_ZVAL(retval[0]);
+       MAKE_STD_ZVAL(retval[1]);
+
+       php_sock[0]->socket = fds_array[0];
+       php_sock[1]->socket = fds_array[1];
+       php_sock[0]->type = Z_LVAL_PP(arg1);
+       php_sock[1]->type = Z_LVAL_PP(arg1);    
+
+       ZEND_REGISTER_RESOURCE(retval[0], php_sock[0], le_socket);
+       ZEND_REGISTER_RESOURCE(retval[1], php_sock[1], le_socket);
 
-       /* ... and return */
-       RETURN_LONG(ret);
+       add_index_zval(*arg4, 0, retval[0]);
+       add_index_zval(*arg4, 1, retval[1]);
+
+       RETURN_TRUE;
 }
 /* }}} */
 
-/* {{{ proto int shutdown(int fd, int how)
+/* {{{ proto bool socket_shutdown(resource socket[, int how])
    Shuts down a socket for receiving, sending, or both. */
-PHP_FUNCTION(shutdown)
+PHP_FUNCTION(socket_shutdown)
 {
-       zval **fd, **how;
-       int how_shutdown = 0, argc = ZEND_NUM_ARGS(), ret;
+       zval **arg1, **arg2;
+       int how_shutdown = 0, argc = ZEND_NUM_ARGS();
+       php_socket *php_sock;
        
-       if (argc < 1 || argc > 2 ||
-           zend_get_parameters_ex(argc, &fd, &how) == FAILURE) {
+       if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &arg1, &arg2) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
-       convert_to_long_ex(fd);
+
+       ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
        
        if (argc > 1) {
-               convert_to_long_ex(how);
-               how_shutdown = Z_LVAL_PP(how);
+               convert_to_long_ex(arg2);
+               how_shutdown = Z_LVAL_PP(arg2);
        }
        
-       ret = shutdown(Z_LVAL_PP(fd), how_shutdown);
+       if(shutdown(php_sock->socket, how_shutdown) != 0) {
+               php_error(E_WARNING, "unable to shutdown socket, %i", errno);
+               RETURN_FALSE;
+       }
        
-       RETURN_LONG(((ret < 0) ? -errno : ret));
+       RETURN_TRUE;
 }
 /* }}} */
 
-#endif                         /* HAVE_SOCKETS */
+#endif
 
 /*
  * Local variables:
  * tab-width: 4
  * c-basic-offset: 4
  * End:
- */
+ */
\ No newline at end of file
diff --git a/ext/sockets/sockets.dsp b/ext/sockets/sockets.dsp
new file mode 100644 (file)
index 0000000..a909c8d
--- /dev/null
@@ -0,0 +1,116 @@
+# Microsoft Developer Studio Project File - Name="sockets" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=sockets - Win32 Debug_TS\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SOCKETS.MAK".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "SOCKETS.MAK" CFG="sockets - Win32 Debug_TS"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "sockets - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "sockets - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "sockets - Win32 Release_TS"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release_TS"\r
+# PROP BASE Intermediate_Dir "Release_TS"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release_TS"\r
+# PROP Intermediate_Dir "Release_TS"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOCKETS_EXPORTS" /YX /FD /c\r
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /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\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x407 /d "NDEBUG"\r
+# ADD RSC /l 0x407 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 php4ts.lib Ws2_32.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"\r
+\r
+!ELSEIF  "$(CFG)" == "sockets - Win32 Debug_TS"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug_TS"\r
+# PROP BASE Intermediate_Dir "Debug_TS"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug_TS"\r
+# PROP Intermediate_Dir "Debug_TS"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# 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\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x407 /d "_DEBUG"\r
+# ADD RSC /l 0x407 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# 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\r
+# ADD LINK32 php4ts_debug.lib Ws2_32.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"\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "sockets - Win32 Release_TS"\r
+# Name "sockets - Win32 Debug_TS"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\php_sockets_win.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sockets.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\php_sockets.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\php_sockets_win.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r