Skip to content

Commit 165a97c

Browse files
author
Jason Greene
committed
Sockets Rework Patch 3 of 3
Nuked all fd code Rewrote socket_select to use arrays instead of the fd code (This has the side-effect of fixing quite a few bugs)
1 parent d716e02 commit 165a97c

File tree

2 files changed

+67
-191
lines changed

2 files changed

+67
-191
lines changed

ext/sockets/php_sockets.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ extern zend_module_entry sockets_module_entry;
4242
PHP_MINIT_FUNCTION(sockets);
4343
PHP_MINFO_FUNCTION(sockets);
4444

45-
PHP_FUNCTION(socket_fd_alloc);
46-
PHP_FUNCTION(socket_fd_free);
47-
PHP_FUNCTION(socket_fd_set);
48-
PHP_FUNCTION(socket_fd_isset);
49-
PHP_FUNCTION(socket_fd_clear);
50-
PHP_FUNCTION(socket_fd_zero);
5145
PHP_FUNCTION(socket_iovec_alloc);
5246
PHP_FUNCTION(socket_iovec_free);
5347
PHP_FUNCTION(socket_iovec_set);
@@ -99,11 +93,6 @@ typedef struct {
9993
int error;
10094
} php_socket;
10195

102-
typedef struct {
103-
fd_set set;
104-
SOCKET max_fd;
105-
} php_fd_set;
106-
10796
typedef struct {
10897
zend_bool use_system_read;
10998
} php_sockets_globals;

ext/sockets/sockets.c

Lines changed: 67 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ php_sockets_globals sockets_globals;
9494

9595
static int le_iov;
9696
#define le_iov_name "Socket I/O vector"
97-
static int le_destroy;
98-
#define le_destroy_name "Socket file descriptor set"
9997
static int le_socket;
10098
#define le_socket_name "Socket"
10199

@@ -111,12 +109,6 @@ static unsigned char third_through_seventh_args_force_ref[] =
111109
/* {{{ sockets_functions[]
112110
*/
113111
function_entry sockets_functions[] = {
114-
PHP_FE(socket_fd_alloc, NULL)
115-
PHP_FE(socket_fd_free, NULL)
116-
PHP_FE(socket_fd_set, NULL)
117-
PHP_FE(socket_fd_isset, NULL)
118-
PHP_FE(socket_fd_clear, NULL)
119-
PHP_FE(socket_fd_zero, NULL)
120112
PHP_FE(socket_iovec_alloc, NULL)
121113
PHP_FE(socket_iovec_free, NULL)
122114
PHP_FE(socket_iovec_set, NULL)
@@ -177,13 +169,6 @@ ZEND_GET_MODULE(sockets)
177169
/* inet_ntop should be used instead of inet_ntoa */
178170
int inet_ntoa_lock = 0;
179171

180-
static void destroy_fd_sets(zend_rsrc_list_entry *rsrc TSRMLS_DC)
181-
{
182-
php_fd_set *php_fd = (php_fd_set*)rsrc->ptr;
183-
184-
efree(php_fd);
185-
}
186-
187172
static void destroy_iovec(zend_rsrc_list_entry *rsrc TSRMLS_DC)
188173
{
189174
unsigned int i;
@@ -393,7 +378,6 @@ PHP_MINIT_FUNCTION(sockets)
393378
struct protoent *pe;
394379

395380
le_socket = zend_register_list_destructors_ex(destroy_socket, NULL, le_socket_name, module_number);
396-
le_destroy = zend_register_list_destructors_ex(destroy_fd_sets, NULL, le_destroy_name, module_number);
397381
le_iov = zend_register_list_destructors_ex(destroy_iovec, NULL, le_iov_name, module_number);
398382

399383
REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT);
@@ -448,193 +432,96 @@ PHP_MINFO_FUNCTION(sockets)
448432
}
449433
/* }}} */
450434

451-
/* {{{ proto resource socket_fd_alloc(void)
452-
Allocates a new file descriptor set */
453-
PHP_FUNCTION(socket_fd_alloc)
454-
{
455-
php_fd_set *php_fd = (php_fd_set*)emalloc(sizeof(php_fd_set));
456-
457-
FD_ZERO(&(php_fd->set));
458-
459-
php_fd->max_fd = 0;
460-
461-
ZEND_REGISTER_RESOURCE(return_value, php_fd, le_destroy);
462-
}
463-
/* }}} */
464-
465-
/* {{{ proto bool socket_fd_free(resource set)
466-
Deallocates a file descriptor set */
467-
PHP_FUNCTION(socket_fd_free)
468-
{
469-
zval *arg1;
470-
php_fd_set *php_fd;
471-
472-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE)
473-
return;
474-
475-
ZEND_FETCH_RESOURCE(php_fd, php_fd_set*, &arg1, -1, le_destroy_name, le_destroy);
476-
477-
zend_list_delete(Z_RESVAL_P(arg1));
478-
RETURN_TRUE;
479-
}
480-
/* }}} */
481-
482-
/* {{{ proto bool socket_fd_set(resource set, mixed socket)
483-
Adds (a) file descriptor(s) to a set */
484-
PHP_FUNCTION(socket_fd_set)
485-
{
486-
zval *arg1, *arg2, **tmp;
487-
php_fd_set *php_fd;
435+
int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, int *max_fd TSRMLS_DC) {
436+
zval **element;
488437
php_socket *php_sock;
489-
SOCKET max_fd = 0;
490-
491-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &arg1, &arg2) == FAILURE)
492-
return;
493-
494-
ZEND_FETCH_RESOURCE(php_fd, php_fd_set*, &arg1, -1, le_destroy_name, le_destroy);
438+
439+
if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
440+
441+
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));
442+
zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;
443+
zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {
444+
445+
php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
446+
if (!php_sock) continue; /* If element is not a resource, skip it */
495447

496-
if (Z_TYPE_P(arg2) == IS_ARRAY) {
497-
zend_hash_internal_pointer_reset(Z_ARRVAL_P(arg2));
498-
while (zend_hash_get_current_data(Z_ARRVAL_P(arg2), (void**)&tmp) == SUCCESS) {
499-
ZEND_FETCH_RESOURCE(php_sock, php_socket*, tmp, -1, le_socket_name, le_socket);
500-
FD_SET(php_sock->bsd_socket, &(php_fd->set));
501-
max_fd = (php_sock->bsd_socket > max_fd) ? php_sock->bsd_socket : max_fd;
502-
zend_hash_move_forward(Z_ARRVAL_P(arg2));
503-
}
504-
} else if (Z_TYPE_P(arg2) == IS_RESOURCE) {
505-
ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg2, -1, le_socket_name, le_socket);
506-
FD_SET(php_sock->bsd_socket, &(php_fd->set));
507-
max_fd = php_sock->bsd_socket;
508-
} else {
509-
php_error(E_ERROR, "%s() expecting argument 2 of type resource or array of resources", get_active_function_name(TSRMLS_C));
510-
RETURN_FALSE;
448+
FD_SET(php_sock->bsd_socket, fds);
449+
if (php_sock->bsd_socket > *max_fd) *max_fd=php_sock->bsd_socket;
511450
}
512-
513-
php_fd->max_fd = max_fd;
514-
RETURN_TRUE;
451+
452+
return 1;
515453
}
516-
/* }}} */
517454

518-
/* {{{ proto bool socket_fd_clear(resource set, mixed socket)
519-
Clears (a) file descriptor(s) from a set */
520-
PHP_FUNCTION(socket_fd_clear)
521-
{
522-
zval *arg1, *arg2, **tmp;
523-
php_fd_set *php_fd;
455+
int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds TSRMLS_DC) {
456+
zval **element;
457+
zval **dest_element;
524458
php_socket *php_sock;
525-
526-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &arg1, &arg2) == FAILURE)
527-
return;
528-
529-
ZEND_FETCH_RESOURCE(php_fd, php_fd_set*, &arg1, -1, le_destroy_name, le_destroy);
530-
531-
if (Z_TYPE_P(arg2) == IS_ARRAY) {
532-
zend_hash_internal_pointer_reset(Z_ARRVAL_P(arg2));
533-
while (zend_hash_get_current_data(Z_ARRVAL_P(arg2), (void**)&tmp) == SUCCESS) {
534-
ZEND_FETCH_RESOURCE(php_sock, php_socket*, tmp, -1, le_socket_name, le_socket);
535-
FD_CLR(php_sock->bsd_socket, &(php_fd->set));
536-
zend_hash_move_forward(Z_ARRVAL_P(arg2));
459+
HashTable *new_hash;
460+
if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
461+
462+
ALLOC_HASHTABLE(new_hash);
463+
zend_hash_init(new_hash, 0, NULL, ZVAL_PTR_DTOR, 0);
464+
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));
465+
zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;
466+
zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {
467+
468+
php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);
469+
if (!php_sock) continue; /* If element is not a resource, skip it */
470+
471+
if (FD_ISSET(php_sock->bsd_socket, fds)) {
472+
/* Add fd to new array */
473+
zend_hash_next_index_insert(new_hash, (void *)element, sizeof(zval *), (void **)&dest_element);
474+
if (dest_element) zval_add_ref(dest_element);
537475
}
538-
} else if (Z_TYPE_P(arg2) == IS_RESOURCE) {
539-
ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg2, -1, le_socket_name, le_socket);
540-
FD_CLR(php_sock->bsd_socket, &(php_fd->set));
541-
} else {
542-
php_error(E_ERROR, "%s() expecting argument 2 of type resource or array of resources", get_active_function_name(TSRMLS_C));
543-
RETURN_FALSE;
544476
}
545-
546-
php_fd->max_fd = 0;
547-
RETURN_TRUE;
548-
}
549-
/* }}} */
550-
551-
/* {{{ proto bool socket_fd_isset(resource set, resource socket)
552-
Checks to see if a file descriptor is set within the file descrirptor set */
553-
PHP_FUNCTION(socket_fd_isset)
554-
{
555-
zval *arg1, *arg2;
556-
php_fd_set *php_fd;
557-
php_socket *php_sock;
558-
559-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &arg1, &arg2) == FAILURE)
560-
return;
561-
562-
ZEND_FETCH_RESOURCE(php_fd, php_fd_set*, &arg1, -1, le_destroy_name, le_destroy);
563-
ZEND_FETCH_RESOURCE(php_sock, php_socket*, &arg2, -1, le_socket_name, le_socket);
564-
565-
if (FD_ISSET(php_sock->bsd_socket, &(php_fd->set))) {
566-
RETURN_TRUE;
567-
}
568-
569-
RETURN_FALSE;
570-
}
571-
/* }}} */
572-
573-
/* {{{ proto bool socket_fd_zero(resource set)
574-
Clears a file descriptor set */
575-
PHP_FUNCTION(socket_fd_zero)
576-
{
577-
zval *arg1;
578-
php_fd_set *php_fd;
579-
580-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE)
581-
return;
582-
583-
ZEND_FETCH_RESOURCE(php_fd, php_fd_set*, &arg1, -1, le_destroy_name, le_destroy);
584-
585-
FD_ZERO(&(php_fd->set));
586477

587-
php_fd->max_fd = 0;
588-
589-
RETURN_TRUE;
478+
/* Destroy old array, add new one */
479+
zend_hash_destroy(Z_ARRVAL_P(sock_array));
480+
481+
zend_hash_internal_pointer_reset(new_hash);
482+
Z_ARRVAL_P(sock_array) = new_hash;
483+
484+
return 1;
590485
}
591-
/* }}} */
592-
593-
/* {{{ proto int socket_select(resource read_fd, resource write_fd, resource except_fd, int tv_sec[, int tv_usec])
486+
487+
488+
/* {{{ proto int socket_select(array &read_fds, array &write_fds, &array except_fds, int tv_sec[, int tv_usec])
594489
Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec */
595490
PHP_FUNCTION(socket_select)
596491
{
597-
zval *arg1, *arg2, *arg3, *arg4;
492+
zval *r_array, *w_array, *e_array;
598493
struct timeval tv;
599-
php_fd_set *rfds = NULL, *wfds = NULL, *xfds = NULL;
494+
fd_set rfds, wfds, efds;
600495
SOCKET max_fd = 0;
601-
int sets = 0, usec = 0;
496+
int retval, sets = 0, usec = 0, sec=0;
602497

603-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r!r!r!z|l", &arg1, &arg2, &arg3, &arg4, &usec) == FAILURE)
498+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!l|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE)
604499
return;
605500

606-
if (arg1 != NULL) {
607-
ZEND_FETCH_RESOURCE(rfds, php_fd_set*, &arg1, -1, le_destroy_name, le_destroy);
608-
max_fd = rfds->max_fd;
609-
sets++;
610-
}
611-
612-
if (arg2 != NULL) {
613-
ZEND_FETCH_RESOURCE(wfds, php_fd_set*, &arg2, -1, le_destroy_name, le_destroy);
614-
max_fd = (max_fd > wfds->max_fd) ? max_fd : wfds->max_fd;
615-
sets++;
616-
}
617-
618-
if (arg3 != NULL) {
619-
ZEND_FETCH_RESOURCE(xfds, php_fd_set*, &arg3, -1, le_destroy_name, le_destroy);
620-
max_fd = (max_fd > xfds->max_fd) ? max_fd : xfds->max_fd;
621-
sets++;
622-
}
623-
501+
FD_ZERO(&rfds);
502+
FD_ZERO(&wfds);
503+
FD_ZERO(&efds);
504+
505+
if (r_array != NULL) sets += php_sock_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
506+
if (w_array != NULL) sets += php_sock_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
507+
if (e_array != NULL) sets += php_sock_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
508+
624509
if (!sets) {
625-
php_error(E_ERROR, "%s() expecting at least one %s", get_active_function_name(TSRMLS_C), le_destroy_name);
510+
php_error(E_WARNING, "%s() no resource arrays were passed to select", get_active_function_name(TSRMLS_C));
626511
RETURN_FALSE;
627512
}
628513

629-
if (Z_TYPE_P(arg4) != IS_NULL) {
630-
tv.tv_sec = Z_LVAL_P(arg4);
631-
tv.tv_usec = usec;
632-
}
514+
tv.tv_sec = sec;
515+
tv.tv_usec = usec;
516+
517+
retval = select(max_fd+1, &rfds, &wfds, &efds, &tv);
518+
519+
if (r_array != NULL) php_sock_array_from_fd_set(r_array, &rfds TSRMLS_CC);
520+
if (w_array != NULL) php_sock_array_from_fd_set(w_array, &wfds TSRMLS_CC);
521+
if (e_array != NULL) php_sock_array_from_fd_set(e_array, &efds TSRMLS_CC);
522+
523+
RETURN_LONG(retval);
633524

634-
RETURN_LONG(select(max_fd+1, rfds ? &(rfds->set) : NULL,
635-
wfds ? &(wfds->set) : NULL,
636-
xfds ? &(xfds->set) : NULL,
637-
(Z_TYPE_P(arg4) != IS_NULL) ? &tv : NULL));
638525
}
639526
/* }}} */
640527

0 commit comments

Comments
 (0)