Bunch of fixes, tested a bit, folks, please test with your scripts. changes

include nuking unnecessary extra copies, fixing handling of optional args,
adding an additional argument.

also, fix  socket_read() which used the php_read function by
default (by default, reading 4k would cause 4k calls to the read() function),
now it uses the system's built-in read() function, only uses php_read()
when its explicitly specified.
This commit is contained in:
Sterling Hughes 2001-06-26 04:19:39 +00:00
parent 333b1bf9c8
commit c01ab20f01

View file

@ -83,6 +83,11 @@ php_sockets_globals sockets_globals;
#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 #endif
#ifndef PF_INET
#define PF_INET AF_INET
#endif
#define PHP_NORMAL_READ 0x0001 #define PHP_NORMAL_READ 0x0001
#define PHP_BINARY_READ 0x0002 #define PHP_BINARY_READ 0x0002
#define PHP_SYSTEM_READ 0x0004 #define PHP_SYSTEM_READ 0x0004
@ -92,7 +97,12 @@ typedef struct {
} php_sockaddr_storage; } php_sockaddr_storage;
static int le_iov, le_destroy, le_socket; static int le_iov;
#define le_iov_name "Socket I/O vector"
static int le_destroy;
#define le_destroy_name "Socket file descriptor set"
static int le_socket;
#define le_socket_name "Socket"
static unsigned char second_and_third_args_force_ref[] = static unsigned char second_and_third_args_force_ref[] =
{3, BYREF_NONE, BYREF_FORCE, BYREF_FORCE}; {3, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
@ -169,14 +179,14 @@ int inet_ntoa_lock = 0;
static void destroy_fd_sets(zend_rsrc_list_entry *rsrc) 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); efree(set);
} }
static void destroy_iovec(zend_rsrc_list_entry *rsrc) static void destroy_iovec(zend_rsrc_list_entry *rsrc)
{ {
unsigned int i; unsigned int i;
php_iovec_t *iov = (php_iovec_t*)rsrc->ptr; php_iovec_t *iov = (php_iovec_t *) rsrc->ptr;
if (iov->count && iov->iov_array) { if (iov->count && iov->iov_array) {
for (i = 0; i < iov->count; i++) { for (i = 0; i < iov->count; i++) {
@ -190,17 +200,19 @@ static void destroy_iovec(zend_rsrc_list_entry *rsrc)
static void destroy_socket(zend_rsrc_list_entry *rsrc) static void destroy_socket(zend_rsrc_list_entry *rsrc)
{ {
php_socket *php_sock = (php_socket*)rsrc->ptr; php_socket *php_sock = (php_socket *) rsrc->ptr;
close(php_sock->socket); close(php_sock->socket);
efree(php_sock); efree(php_sock);
} }
static php_socket *open_listen_sock(int port) static php_socket *open_listen_sock(int port, int backlog)
{ {
struct sockaddr_in la; struct sockaddr_in la;
struct hostent *hp; struct hostent *hp;
php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket)); php_socket *php_sock;
php_sock = emalloc(sizeof(php_socket));
#ifndef PHP_WIN32 #ifndef PHP_WIN32
if ((hp = gethostbyname("0.0.0.0")) == NULL) { if ((hp = gethostbyname("0.0.0.0")) == NULL) {
@ -211,36 +223,51 @@ static php_socket *open_listen_sock(int port)
return NULL; return NULL;
} }
memcpy((char *)&la.sin_addr, hp->h_addr, hp->h_length); memcpy((char *) &la.sin_addr, hp->h_addr, hp->h_length);
la.sin_family = hp->h_addrtype; la.sin_family = hp->h_addrtype;
la.sin_port = htons((unsigned short)port); la.sin_port = htons((unsigned short) port);
php_sock->socket = socket(AF_INET, SOCK_STREAM, 0); php_sock->socket = socket(PF_INET, SOCK_STREAM, 0);
php_sock->type = AF_INET; php_sock->type = PF_INET;
if (IS_INVALID_SOCKET(php_sock)) { if (IS_INVALID_SOCKET(php_sock)) {
php_error(E_WARNING, "Couldn't allocate a new socket from open_listen_sock()");
efree(php_sock); efree(php_sock);
return NULL; return NULL;
} }
if ((bind(php_sock->socket, (struct sockaddr *)&la, sizeof(la)) != 0)) {
if (bind(php_sock->socket, (struct sockaddr *)&la, sizeof(la)) < 0) {
php_error(E_WARNING, "Couldn't bind socket to given address from open_listen_sock()");
close(php_sock->socket);
efree(php_sock); efree(php_sock);
return NULL; return NULL;
} }
listen(php_sock->socket, 128);
if (listen(php_sock->socket, backlog) < 0) {
php_error(E_WARNING, "Couldn't listen on socket %d from open_listen_sock()", php_sock->socket);
close(php_sock->socket);
efree(php_sock);
return NULL;
}
return php_sock; return php_sock;
} }
static php_socket *accept_connect(php_socket *php_sock, struct sockaddr *la) static php_socket *accept_connect(php_socket *php_sock, struct sockaddr *la)
{ {
int m; int m;
php_socket *retval = (php_socket*)emalloc(sizeof(php_socket)); php_socket *retval;
retval = emalloc(sizeof(php_socket));
m = sizeof(*la); m = sizeof(*la);
retval->socket = accept(php_sock->socket, la, &m); retval->socket = accept(php_sock->socket, la, &m);
if (IS_INVALID_SOCKET(retval)) { if (IS_INVALID_SOCKET(retval)) {
php_error(E_WARNING, "Couldn't accept incoming connection in accept_connect()");
efree(retval); efree(retval);
return NULL; return NULL;
} }
return retval; return retval;
} }
@ -311,9 +338,9 @@ PHP_MINIT_FUNCTION(sockets)
{ {
struct protoent *pe; struct protoent *pe;
le_socket = zend_register_list_destructors_ex(destroy_socket, NULL, "Socket", module_number); le_socket = zend_register_list_destructors_ex(destroy_socket, NULL, le_socket_name, module_number);
le_destroy = zend_register_list_destructors_ex(destroy_fd_sets,NULL, "Socket file descriptor set", module_number); le_destroy = zend_register_list_destructors_ex(destroy_fd_sets,NULL, le_destroy_name, module_number);
le_iov = zend_register_list_destructors_ex(destroy_iovec, NULL, "Socket I/O vector", module_number); le_iov = zend_register_list_destructors_ex(destroy_iovec, NULL, le_iov_name, module_number);
REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT); 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("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT);
@ -393,7 +420,7 @@ PHP_FUNCTION(socket_fd_free)
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(the_set, fd_set *, arg1, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(the_set, fd_set *, arg1, -1, le_destroy_name, le_destroy);
zend_list_delete(Z_RESVAL_PP(arg1)); zend_list_delete(Z_RESVAL_PP(arg1));
RETURN_TRUE; RETURN_TRUE;
@ -412,8 +439,8 @@ PHP_FUNCTION(socket_fd_set)
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, le_socket_name, le_socket);
ZEND_FETCH_RESOURCE(the_set, fd_set*, arg2, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(the_set, fd_set*, arg2, -1, le_destroy_name, le_destroy);
FD_SET(php_sock->socket, the_set); FD_SET(php_sock->socket, the_set);
RETURN_TRUE; RETURN_TRUE;
@ -432,8 +459,8 @@ PHP_FUNCTION(socket_fd_clear)
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, le_socket_name, le_socket);
ZEND_FETCH_RESOURCE(the_set, fd_set *, arg2, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(the_set, fd_set *, arg2, -1, le_destroy_name, le_destroy);
FD_CLR(php_sock->socket, the_set); FD_CLR(php_sock->socket, the_set);
RETURN_TRUE; RETURN_TRUE;
@ -452,12 +479,13 @@ PHP_FUNCTION(socket_fd_isset)
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, le_socket_name, le_socket);
ZEND_FETCH_RESOURCE(the_set, fd_set *, arg2, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(the_set, fd_set *, arg2, -1, le_destroy_name, le_destroy);
if (FD_ISSET(php_sock->socket, the_set)) { if (FD_ISSET(php_sock->socket, the_set)) {
RETURN_TRUE; RETURN_TRUE;
} }
RETURN_FALSE; RETURN_FALSE;
} }
/* }}} */ /* }}} */
@ -473,9 +501,10 @@ PHP_FUNCTION(socket_fd_zero)
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(the_set, fd_set *, arg1, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(the_set, fd_set *, arg1, -1, le_destroy_name, le_destroy);
FD_ZERO(the_set); FD_ZERO(the_set);
RETURN_TRUE; RETURN_TRUE;
} }
/* }}} */ /* }}} */
@ -495,9 +524,9 @@ PHP_FUNCTION(socket_select)
convert_to_long_ex(arg1); convert_to_long_ex(arg1);
convert_to_long_ex(arg5); convert_to_long_ex(arg5);
convert_to_long_ex(arg6); convert_to_long_ex(arg6);
ZEND_FETCH_RESOURCE(rfds, fd_set *, arg2, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(rfds, fd_set *, arg2, -1, le_destroy_name, le_destroy);
ZEND_FETCH_RESOURCE(wfds, fd_set *, arg3, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(wfds, fd_set *, arg3, -1, le_destroy_name, le_destroy);
ZEND_FETCH_RESOURCE(xfds, fd_set *, arg4, -1, "File descriptor set", le_destroy); ZEND_FETCH_RESOURCE(xfds, fd_set *, arg4, -1, le_destroy_name, le_destroy);
tv.tv_sec = Z_LVAL_PP(arg5); tv.tv_sec = Z_LVAL_PP(arg5);
tv.tv_usec = Z_LVAL_PP(arg6); tv.tv_usec = Z_LVAL_PP(arg6);
@ -505,22 +534,30 @@ PHP_FUNCTION(socket_select)
} }
/* }}} */ /* }}} */
/* {{{ proto mixed socket_create_listen(int port) /* {{{ proto resource socket_create_listen(int port[, int backlog])
Opens a socket on port to accept connections */ Opens a socket on port to accept connections */
PHP_FUNCTION(socket_create_listen) PHP_FUNCTION(socket_create_listen)
{ {
zval **port; zval **arg1;
php_socket *php_sock; zval **arg2;
php_socket *php_sock;
int backlog = 128;
int argc = ZEND_NUM_ARGS();
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &port) == FAILURE) { if (argc < 1 || argc > 2 ||
zend_get_parameters_ex(argc, &arg1, &arg2) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
convert_to_long_ex(port); convert_to_long_ex(arg1);
php_sock = open_listen_sock(Z_LVAL_PP(port)); if (argc > 1) {
convert_to_long_ex(arg2);
backlog = Z_LVAL_PP(arg2);
}
php_sock = open_listen_sock(Z_LVAL_PP(arg1), backlog);
if(php_sock == NULL) { if(php_sock == NULL) {
php_error(E_WARNING, "unable to create listening socket, %i", errno); php_error(E_WARNING, "unable to create listening socket [%d]: %s", errno, strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} }
@ -528,24 +565,24 @@ PHP_FUNCTION(socket_create_listen)
} }
/* }}} */ /* }}} */
/* {{{ proto socket socket_accept(resource socket) /* {{{ proto resource socket_accept(resource socket)
Accepts a connection on the listening socket fd */ Accepts a connection on the listening socket fd */
PHP_FUNCTION(socket_accept) PHP_FUNCTION(socket_accept)
{ {
zval **arg1; zval **arg1;
php_socket *php_sock, *new_sock; php_socket *php_sock;
struct sockaddr_in sa; php_socket *new_sock;
struct sockaddr_in sa;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
new_sock = accept_connect(php_sock, (struct sockaddr*)&sa);
new_sock = accept_connect(php_sock, (struct sockaddr *) &sa);
if(new_sock == NULL) { if(new_sock == NULL) {
php_error(E_WARNING, "unable to accept connection, %i", errno); php_error(E_WARNING, "unable to accept connection [%d]: %s", errno, strerror(errno));
RETURN_FALSE RETURN_FALSE
} }
@ -557,14 +594,14 @@ PHP_FUNCTION(socket_accept)
Sets nonblocking mode for file descriptor fd */ Sets nonblocking mode for file descriptor fd */
PHP_FUNCTION(socket_set_nonblock) PHP_FUNCTION(socket_set_nonblock)
{ {
zval **arg1; zval **arg1;
php_socket *php_sock; php_socket *php_sock;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
if (fcntl(php_sock->socket, F_SETFL, O_NONBLOCK) == 0) { if (fcntl(php_sock->socket, F_SETFL, O_NONBLOCK) == 0) {
RETURN_TRUE; RETURN_TRUE;
@ -574,21 +611,28 @@ PHP_FUNCTION(socket_set_nonblock)
} }
/* }}} */ /* }}} */
/* {{{ proto bool socket_listen(resource socket, 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 */ Sets the maximum number of connections allowed to be waited for on the socket specified by fd */
PHP_FUNCTION(socket_listen) PHP_FUNCTION(socket_listen)
{ {
zval **arg1, **arg2; zval **arg1;
php_socket *php_sock; zval **arg2;
php_socket *php_sock;
int backlog = 0;
int argc = ZEND_NUM_ARGS();
if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { if (argc < 1 || argc > 2 ||
zend_get_parameters_ex(argc, &arg1, &arg2) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
convert_to_long_ex(arg2); if (argc > 1) {
convert_to_long_ex(arg2);
backlog = Z_LVAL_PP(arg2);
}
if (listen(php_sock->socket, Z_LVAL_PP(arg2)) == 0) { if (listen(php_sock->socket, backlog) == 0) {
RETURN_FALSE; RETURN_FALSE;
} }
@ -600,14 +644,14 @@ PHP_FUNCTION(socket_listen)
Closes a file descriptor */ Closes a file descriptor */
PHP_FUNCTION(socket_close) PHP_FUNCTION(socket_close)
{ {
zval **arg1; zval **arg1;
php_socket *php_sock; php_socket *php_sock;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
zend_list_delete(Z_RESVAL_PP(arg1)); zend_list_delete(Z_RESVAL_PP(arg1));
} }
/* }}} */ /* }}} */
@ -616,32 +660,38 @@ PHP_FUNCTION(socket_close)
Writes the buffer to the file descriptor fd, length is optional */ Writes the buffer to the file descriptor fd, length is optional */
PHP_FUNCTION(socket_write) PHP_FUNCTION(socket_write)
{ {
zval **arg1, **arg2, **arg3; zval **arg1;
php_socket *php_sock; zval **arg2;
int retval, which, argc = ZEND_NUM_ARGS(); zval **arg3;
php_socket *php_sock;
int retval;
int length;
int argc = ZEND_NUM_ARGS();
if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) { if (argc < 2 || argc > 3 ||
zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
convert_to_string_ex(arg2); convert_to_string_ex(arg2);
if (argc == 3) {
if (argc > 2) {
convert_to_long_ex(arg3); convert_to_long_ex(arg3);
which = (Z_STRLEN_PP(arg2) < Z_LVAL_PP(arg3)) ? 1 : 0; length = Z_LVAL_PP(arg3);
} else { }
which = 1; else {
length = Z_STRLEN_PP(arg2);
} }
#ifndef PHP_WIN32 #ifndef PHP_WIN32
retval = write(php_sock->socket, (void *)Z_STRVAL_PP(arg2), (which ? Z_STRLEN_PP(arg2) : Z_LVAL_PP(arg3))); retval = write(php_sock->socket, Z_STRVAL_PP(arg2), length);
#else #else
retval = send(php_sock->socket, Z_STRVAL_PP(arg2), (which ? Z_STRLEN_PP(arg2) : Z_LVAL_PP(arg3)), 0); retval = send(php_sock->socket, Z_STRVAL_PP(arg2), length, 0);
#endif #endif
if (!retval) { if (retval <= 0) {
php_error(E_WARNING, "unable to write, %i", errno); php_error(E_WARNING, "Unable to write to socket %d [%d]: %s", php_sock->socket, errno, strerror(errno));
RETURN_LONG(0); RETURN_FALSE;
} }
RETURN_LONG(retval); RETURN_LONG(retval);
@ -650,31 +700,30 @@ PHP_FUNCTION(socket_write)
typedef int (*read_func)(int, void *, int); typedef int (*read_func)(int, void *, int);
/* {{{ proto mixed socket_read(resource socket, int length [, int type]) /* {{{ proto string socket_read(resource socket, int length [, int type])
Reads length bytes from socket */ Reads length bytes from socket */
PHP_FUNCTION(socket_read) PHP_FUNCTION(socket_read)
{ {
zval **arg1, **arg2, **arg3; zval **arg1;
char *tmpbuf; zval **arg2;
php_socket *php_sock; zval **arg3;
read_func read_function = php_read; php_socket *php_sock;
int retval, argc = ZEND_NUM_ARGS(); read_func read_function = (read_func) read;
char *tmpbuf;
int retval;
int argc = ZEND_NUM_ARGS();
if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) { if (argc < 2 || argc > 3 ||
zend_get_parameters_ex(argc, &arg1, &arg2, &arg3) == FAILURE) {
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket);
convert_to_long_ex(arg2); convert_to_long_ex(arg2);
if (argc == 3) { if (argc > 2) {
convert_to_long_ex(arg3); convert_to_long_ex(arg3);
switch (Z_LVAL_PP(arg3)) { if (Z_LVAL_PP(arg3) == PHP_NORMAL_READ)
case PHP_SYSTEM_READ: read_function = (read_func) php_read;
case PHP_BINARY_READ:
read_function = (read_func) read;
break;
}
} }
tmpbuf = emalloc(Z_LVAL_PP(arg2) + 1); tmpbuf = emalloc(Z_LVAL_PP(arg2) + 1);
@ -686,12 +735,14 @@ PHP_FUNCTION(socket_read)
#endif #endif
if (retval <= 0) { if (retval <= 0) {
php_error(E_WARNING, "Couldn't read %d bytes from socket %d [%d]: %s",
Z_LVAL_PP(arg2), php_sock->socket, errno, strerror(errno));
efree(tmpbuf); efree(tmpbuf);
RETURN_FALSE; RETURN_FALSE;
} }
tmpbuf[retval] = '\0'; tmpbuf[retval] = 0;
RETURN_STRING(tmpbuf, 0); RETURN_STRINGL(tmpbuf, retval, 0);
} }
/* }}} */ /* }}} */
@ -700,7 +751,6 @@ PHP_FUNCTION(socket_read)
PHP_FUNCTION(socket_getsockname) PHP_FUNCTION(socket_getsockname)
{ {
zval **arg1, **addr, **port; zval **arg1, **addr, **port;
char *tmp;
php_sockaddr_storage sa_storage; php_sockaddr_storage sa_storage;
php_socket *php_sock; php_socket *php_sock;
struct sockaddr *sa; struct sockaddr *sa;
@ -726,36 +776,29 @@ PHP_FUNCTION(socket_getsockname)
char *addr_string; char *addr_string;
switch (sa->sa_family) { switch (sa->sa_family) {
case AF_INET: case AF_INET:
sin = (struct sockaddr_in *) sa; sin = (struct sockaddr_in *) sa;
while (inet_ntoa_lock == 1); while (inet_ntoa_lock == 1);
inet_ntoa_lock = 1; inet_ntoa_lock = 1;
addr_string = inet_ntoa(sin->sin_addr); addr_string = inet_ntoa(sin->sin_addr);
tmp = (char*)emalloc(strlen(addr_string) + 1); inet_ntoa_lock = 0;
memset(tmp, 0, strlen(addr_string) + 1);
strncpy(tmp, addr_string, strlen(addr_string));
inet_ntoa_lock = 0;
if (Z_STRLEN_PP(addr) > 0) { if (Z_STRLEN_PP(addr) > 0) {
efree(Z_STRVAL_PP(addr)); efree(Z_STRVAL_PP(addr));
} }
Z_STRVAL_PP(addr) = tmp; ZVAL_STRING(*addr, addr_string, 1);
Z_STRLEN_PP(addr) = strlen(tmp); Z_LVAL_PP(port) = htons(sin->sin_port);
Z_LVAL_PP(port) = htons(sin->sin_port); RETURN_TRUE;
RETURN_TRUE; case AF_UNIX:
if (Z_STRLEN_PP(addr) > 0) {
case AF_UNIX: efree(Z_STRVAL_PP(addr));
if (Z_STRLEN_PP(addr) > 0) { }
efree(Z_STRVAL_PP(addr)); s_un = (struct sockaddr_un *) sa;
} ZVAL_STRING(*addr, s_un->sun_path, 1);
s_un = (struct sockaddr_un *) sa; RETURN_TRUE;
Z_STRVAL_PP(addr) = estrndup(s_un->sun_path,strlen(s_un->sun_path)); default:
Z_STRLEN_PP(addr) = strlen(s_un->sun_path); RETURN_FALSE;
RETURN_TRUE;
default:
RETURN_FALSE;
} }
} }
} }
@ -766,12 +809,12 @@ PHP_FUNCTION(socket_getsockname)
PHP_FUNCTION(socket_getpeername) PHP_FUNCTION(socket_getpeername)
{ {
zval **arg1, **arg2, **arg3; zval **arg1, **arg2, **arg3;
char *tmp;
php_sockaddr_storage sa_storage; php_sockaddr_storage sa_storage;
php_socket *php_sock; php_socket *php_sock;
struct sockaddr *sa; struct sockaddr *sa;
struct sockaddr_in *sin; struct sockaddr_in *sin;
struct sockaddr_un *s_un; struct sockaddr_un *s_un;
char *addr_string;
int salen = sizeof(php_sockaddr_storage); int salen = sizeof(php_sockaddr_storage);
int argc = ZEND_NUM_ARGS(); int argc = ZEND_NUM_ARGS();
@ -785,48 +828,39 @@ PHP_FUNCTION(socket_getpeername)
sa = (struct sockaddr *) &sa_storage; sa = (struct sockaddr *) &sa_storage;
if (getpeername(php_sock->socket, sa, &salen) != 0) { if (getpeername(php_sock->socket, sa, &salen) < 0) {
php_error(E_WARNING, "unable to retrieve peername, %i", errno); php_error(E_WARNING, "Unable to retrieve peername [%d]: %s", errno, strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} else { }
char *addr_string;
switch (sa->sa_family) { switch (sa->sa_family) {
case AF_INET: case AF_INET:
sin = (struct sockaddr_in *) sa; sin = (struct sockaddr_in *) sa;
while (inet_ntoa_lock == 1); while (inet_ntoa_lock == 1);
inet_ntoa_lock = 1; inet_ntoa_lock = 1;
addr_string = inet_ntoa(sin->sin_addr); addr_string = inet_ntoa(sin->sin_addr);
tmp = (char*)emalloc(strlen(addr_string) + 1); inet_ntoa_lock = 0;
memset(tmp, 0, strlen(addr_string) + 1);
strncpy(tmp, addr_string, strlen(addr_string));
inet_ntoa_lock = 0;
if (Z_STRLEN_PP(arg2) > 0) { if (Z_STRLEN_PP(arg2) > 0) {
efree(Z_STRVAL_PP(arg2)); efree(Z_STRVAL_PP(arg2));
}
Z_STRVAL_PP(arg2) = tmp;
Z_STRLEN_PP(arg2) = strlen(tmp);
if (argc > 2) {
Z_LVAL_PP(arg3) = htons(sin->sin_port);
}
RETURN_TRUE;
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;
default:
RETURN_FALSE;
} }
ZVAL_STRING(*arg2, addr_string, 1);
if (argc > 2) {
Z_LVAL_PP(arg3) = htons(sin->sin_port);
}
RETURN_TRUE;
case AF_UNIX:
if (Z_STRLEN_PP(arg2) > 0) {
efree(Z_STRVAL_PP(arg2));
}
s_un = (struct sockaddr_un *) sa;
ZVAL_STRING(*arg2, s_un->sun_path, 1);
RETURN_TRUE;
default:
RETURN_FALSE;
} }
} }
/* }}} */ /* }}} */
@ -847,18 +881,17 @@ PHP_FUNCTION(socket_create)
convert_to_long_ex(arg3); convert_to_long_ex(arg3);
if (Z_LVAL_PP(arg1) != AF_UNIX && Z_LVAL_PP(arg1) != AF_INET) { 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)); php_error(E_WARNING, "invalid socket domain [%d] specified, assuming AF_INET", Z_LVAL_PP(arg1));
Z_LVAL_PP(arg1) = AF_INET; Z_LVAL_PP(arg1) = AF_INET;
} }
if (Z_LVAL_PP(arg2) > 10) { if (Z_LVAL_PP(arg2) > 10) {
php_error(E_WARNING, "invalid socket type [%i] specified, assuming SOCK_STREAM", Z_LVAL_PP(arg2)); php_error(E_WARNING, "invalid socket type [%d] specified, assuming SOCK_STREAM", Z_LVAL_PP(arg2));
Z_LVAL_PP(arg2) = SOCK_STREAM; Z_LVAL_PP(arg2) = SOCK_STREAM;
} }
php_sock->socket = socket(Z_LVAL_PP(arg1), Z_LVAL_PP(arg2), Z_LVAL_PP(arg3)); php_sock->socket = socket(Z_LVAL_PP(arg1), Z_LVAL_PP(arg2), Z_LVAL_PP(arg3));
php_sock->type = Z_LVAL_PP(arg1); php_sock->type = Z_LVAL_PP(arg1);
if(IS_INVALID_SOCKET(php_sock)) { if(IS_INVALID_SOCKET(php_sock)) {
RETURN_FALSE; RETURN_FALSE;
} }
@ -884,7 +917,7 @@ PHP_FUNCTION(socket_connect)
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
convert_to_string_ex(arg2); convert_to_string_ex(arg2);
if (argc == 3) { if (argc == 3) {
@ -892,45 +925,43 @@ PHP_FUNCTION(socket_connect)
} }
switch( php_sock->type ) { switch(php_sock->type) {
case AF_INET: case AF_INET:
if (argc != 3) {
WRONG_PARAM_COUNT;
}
if (argc != 3) { sin.sin_family = AF_INET;
WRONG_PARAM_COUNT; sin.sin_port = htons((unsigned short int)Z_LVAL_PP(arg3));
if (inet_aton(Z_STRVAL_PP(arg2), &addr_buf)) {
sin.sin_addr.s_addr = addr_buf.s_addr;
} else {
char *q = (char *) &(sin.sin_addr.s_addr);
host_struct = gethostbyname(Z_STRVAL_PP(arg2));
if (host_struct->h_addrtype != AF_INET) {
RETURN_FALSE;
} }
sin.sin_family = AF_INET; q[0] = host_struct->h_addr_list[0][0];
sin.sin_port = htons((unsigned short int)Z_LVAL_PP(arg3)); q[1] = host_struct->h_addr_list[0][1];
q[2] = host_struct->h_addr_list[0][2];
q[3] = host_struct->h_addr_list[0][3];
}
if (inet_aton(Z_STRVAL_PP(arg2), &addr_buf)) { retval = connect(php_sock->socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
sin.sin_addr.s_addr = addr_buf.s_addr; break;
} else { case AF_UNIX:
char *q = (char *) &(sin.sin_addr.s_addr); s_un.sun_family = AF_UNIX;
host_struct = gethostbyname(Z_STRVAL_PP(arg2)); snprintf(s_un.sun_path, 108, "%s", Z_STRVAL_PP(arg2));
if (host_struct->h_addrtype != AF_INET) { retval = connect(php_sock->socket, (struct sockaddr *) &s_un, SUN_LEN(&s_un));
RETURN_FALSE; break;
} default:
q[0] = host_struct->h_addr_list[0][0]; RETURN_FALSE;
q[1] = host_struct->h_addr_list[0][1];
q[2] = host_struct->h_addr_list[0][2];
q[3] = host_struct->h_addr_list[0][3];
}
retval = connect(php_sock->socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
break;
case AF_UNIX:
s_un.sun_family = AF_UNIX;
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) { if (retval != 0) {
php_error(E_WARNING, "unable to connect, %i", errno); php_error(E_WARNING, "unable to connect [%d]: %s", errno, strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} }
@ -957,7 +988,7 @@ PHP_FUNCTION(socket_strerror)
#else #else
{ {
static char buf[100]; static char buf[100];
sprintf (buf, "Host lookup error %d", -(Z_LVAL_PP(arg1))); sprintf(buf, "Host lookup error %d", -(Z_LVAL_PP(arg1)));
} }
#endif #endif
} else { } else {
@ -975,7 +1006,7 @@ PHP_FUNCTION(socket_strerror)
NULL NULL
); );
#endif #endif
RETURN_STRING(buf?(char*)buf:"", 1); RETURN_STRING(buf ? (char *) buf : "", 1);
} }
/* }}} */ /* }}} */
@ -1012,9 +1043,7 @@ PHP_FUNCTION(socket_bind)
sa->sun_family = AF_UNIX; sa->sun_family = AF_UNIX;
snprintf(sa->sun_path, 108, "%s", Z_STRVAL_PP(arg2)); snprintf(sa->sun_path, 108, "%s", Z_STRVAL_PP(arg2));
retval = bind(php_sock->socket, (struct sockaddr *) sa, SUN_LEN(sa)); retval = bind(php_sock->socket, (struct sockaddr *) sa, SUN_LEN(sa));
} else if (php_sock->type == AF_INET) { } else if (php_sock->type == AF_INET) {
struct sockaddr_in sa; struct sockaddr_in sa;
struct hostent *hp; struct hostent *hp;
@ -1058,7 +1087,7 @@ PHP_FUNCTION(socket_iovec_alloc)
struct iovec *vector_array; struct iovec *vector_array;
int i, j, num_vectors, argc = ZEND_NUM_ARGS(); int i, j, num_vectors, argc = ZEND_NUM_ARGS();
args = (zval***)emalloc(argc*sizeof(zval**)); args = emalloc(argc*sizeof(zval**));
if (argc < 1 || zend_get_parameters_array_ex(argc, args) == FAILURE) { if (argc < 1 || zend_get_parameters_array_ex(argc, args) == FAILURE) {
efree(args); efree(args);
@ -1068,7 +1097,7 @@ PHP_FUNCTION(socket_iovec_alloc)
convert_to_long_ex(args[0]); convert_to_long_ex(args[0]);
num_vectors = Z_LVAL_PP(args[0]); num_vectors = Z_LVAL_PP(args[0]);
vector_array = (struct iovec*)emalloc(sizeof(struct iovec)*(num_vectors+1)); vector_array = emalloc(sizeof(struct iovec)*(num_vectors+1));
for (i = 0, j = 1; i < num_vectors; i++, j++) { for (i = 0, j = 1; i < num_vectors; i++, j++) {
convert_to_long_ex(args[j]); convert_to_long_ex(args[j]);
@ -1077,7 +1106,7 @@ PHP_FUNCTION(socket_iovec_alloc)
vector_array[i].iov_len = Z_LVAL_PP(args[j]); vector_array[i].iov_len = Z_LVAL_PP(args[j]);
} }
vector = (php_iovec_t*)emalloc(sizeof(php_iovec_t)); vector = emalloc(sizeof(php_iovec_t));
vector->iov_array = vector_array; vector->iov_array = vector_array;
vector->count = num_vectors; vector->count = num_vectors;
@ -1184,7 +1213,7 @@ PHP_FUNCTION(socket_iovec_delete)
php_error(E_WARNING, "Can't delete an IO vector that is out of array bounds"); php_error(E_WARNING, "Can't delete an IO vector that is out of array bounds");
RETURN_FALSE; RETURN_FALSE;
} }
vector_array = (struct iovec*)emalloc(vector->count * sizeof(struct iovec)); vector_array = emalloc(vector->count * sizeof(struct iovec));
for (i = 0; i < vector->count; i++) { for (i = 0; i < vector->count; i++) {
if (i < Z_LVAL_PP(iov_pos)) { if (i < Z_LVAL_PP(iov_pos)) {
@ -1286,7 +1315,7 @@ PHP_FUNCTION(socket_recv)
convert_to_long_ex(arg2); convert_to_long_ex(arg2);
convert_to_long_ex(arg3); convert_to_long_ex(arg3);
recv_buf = (char*)emalloc(Z_LVAL_PP(arg2) + 2); recv_buf = emalloc(Z_LVAL_PP(arg2) + 2);
memset(recv_buf, 0, Z_LVAL_PP(arg2) + 2); memset(recv_buf, 0, Z_LVAL_PP(arg2) + 2);
retval = recv(php_sock->socket, recv_buf, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3)); retval = recv(php_sock->socket, recv_buf, Z_LVAL_PP(arg2), Z_LVAL_PP(arg3));
@ -1353,79 +1382,65 @@ PHP_FUNCTION(socket_recvfrom)
break; break;
} }
recv_buf = (char*)emalloc(Z_LVAL_PP(arg3) + 2); recv_buf = emalloc(Z_LVAL_PP(arg3) + 2);
memset(recv_buf, 0, Z_LVAL_PP(arg3) + 2); memset(recv_buf, 0, Z_LVAL_PP(arg3) + 2);
switch ( php_sock->type ) { switch (php_sock->type) {
case AF_UNIX: case AF_UNIX:
slen = sizeof(s_un); slen = sizeof(s_un);
s_un.sun_family = AF_UNIX; s_un.sun_family = AF_UNIX;
retval = recvfrom(php_sock->socket, recv_buf, Z_LVAL_PP(arg3), Z_LVAL_PP(arg4), retval = recvfrom(php_sock->socket, recv_buf, Z_LVAL_PP(arg3), Z_LVAL_PP(arg4),
(struct sockaddr *)&s_un, (socklen_t *)&slen); (struct sockaddr *)&s_un, (socklen_t *)&slen);
if (retval < 0) { if (retval < 0) {
efree(recv_buf);
php_error(E_WARNING, "unable to recvfrom, %i", errno);
RETURN_FALSE;
}
if (Z_STRVAL_PP(arg2) != NULL) {
efree(Z_STRVAL_PP(arg2));
}
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(arg5) = estrdup(s_un.sun_path);
Z_STRLEN_PP(arg5) = strlen(s_un.sun_path);
efree(recv_buf); efree(recv_buf);
php_error(E_WARNING, "unable to recvfrom, %i", errno);
case AF_INET:
slen = sizeof(sin);
sin.sin_family = AF_INET;
if (argc != 6) {
WRONG_PARAM_COUNT;
}
retval = recvfrom(php_sock->socket, recv_buf, Z_LVAL_PP(arg3), Z_LVAL_PP(arg4),
(struct sockaddr *)&sin, (socklen_t *)&slen);
if (retval < 0) {
efree(recv_buf);
php_error(E_WARNING, "unable to recvfrom, %i", errno);
RETURN_FALSE;
}
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(arg5) > 0) {
efree(Z_STRVAL_PP(arg5));
}
address = inet_ntoa(sin.sin_addr);
if (address == NULL) {
Z_STRVAL_PP(arg5) = estrdup("0.0.0.0");
Z_STRLEN_PP(arg5) = strlen(Z_STRVAL_PP(arg5));
} else {
Z_STRVAL_PP(arg5) = estrdup(address);
Z_STRLEN_PP(arg5) = strlen(address);
}
Z_LVAL_PP(arg6) = ntohs(sin.sin_port);
efree(recv_buf);
default:
RETURN_FALSE; RETURN_FALSE;
}
if (Z_STRVAL_PP(arg2) != NULL) {
efree(Z_STRVAL_PP(arg2));
}
ZVAL_STRING(*arg2, recv_buf, 0);
if (Z_STRLEN_PP(arg5) > 0) {
efree(Z_STRVAL_PP(arg5));
}
ZVAL_STRING(*arg5, s_un.sun_path, 1);
break;
case AF_INET:
slen = sizeof(sin);
sin.sin_family = AF_INET;
if (argc != 6) {
WRONG_PARAM_COUNT;
}
retval = recvfrom(php_sock->socket, recv_buf, Z_LVAL_PP(arg3), Z_LVAL_PP(arg4),
(struct sockaddr *)&sin, (socklen_t *)&slen);
if (retval < 0) {
efree(recv_buf);
php_error(E_WARNING, "unable to recvfrom, %i", errno);
RETURN_FALSE;
}
if (Z_STRLEN_PP(arg2) > 0) {
efree(Z_STRVAL_PP(arg2));
}
ZVAL_STRING(*arg2, recv_buf, 0);
if (Z_STRLEN_PP(arg5) > 0) {
efree(Z_STRVAL_PP(arg5));
}
address = inet_ntoa(sin.sin_addr);
ZVAL_STRING(*arg5, address ? address : "0.0.0.0", 1);
ZVAL_LONG(*arg6, ntohs(sin.sin_port));
default:
RETURN_FALSE;
} }
RETURN_LONG(retval); RETURN_LONG(retval);
@ -1455,7 +1470,7 @@ PHP_FUNCTION(socket_sendto)
convert_to_long_ex(arg4); convert_to_long_ex(arg4);
convert_to_long_ex(arg3); convert_to_long_ex(arg3);
convert_to_string_ex(arg2); convert_to_string_ex(arg2);
ZEND_FETCH_RESOURCE(php_sock, php_socket*, arg1, -1, "Socket", le_socket); ZEND_FETCH_RESOURCE(php_sock, php_socket *, arg1, -1, le_socket_name, le_socket);
break; break;
} }