From: Wez Furlong Date: Fri, 27 Sep 2002 23:42:38 +0000 (+0000) Subject: Implement stream_select() which works just like socket_select, but only on X-Git-Tag: MODERN_SYMMETRIC_SESSION_BEHAVIOUR_20021003~124 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=315e0a599ba994d25ae31e1c628e496cc2ae25c1;p=php Implement stream_select() which works just like socket_select, but only on streams. @ - Added stream_select() which works like socket_select but only works on @ streams returned by fopen(), fsockopen() and pfsockopen(). (Wez) --- diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 999e9f2de2..765b9300e1 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -99,6 +99,9 @@ static unsigned char second_and_third_args_force_ref[] = { 3, BYREF_NONE, BYREF_ static unsigned char second_args_force_ref[] = { 2, BYREF_NONE, BYREF_FORCE }; static unsigned char third_and_fourth_args_force_ref[] = { 4, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE }; static unsigned char third_and_rest_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE_REST }; +static unsigned char first_through_third_args_force_ref[] = +{3, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE}; + typedef struct _php_shutdown_function_entry { zval **arguments; @@ -617,6 +620,7 @@ function_entry basic_functions[] = { PHP_STATIC_FE("tmpfile", php_if_tmpfile, NULL) PHP_FE(file, NULL) PHP_FE(file_get_contents, NULL) + PHP_FE(stream_select, first_through_third_args_force_ref) PHP_FE(stream_context_create, NULL) PHP_FE(stream_context_set_params, NULL) PHP_FE(stream_context_set_option, NULL) @@ -628,11 +632,9 @@ function_entry basic_functions[] = { PHP_FE(get_meta_tags, NULL) PHP_FE(set_file_buffer, NULL) - /* set_socket_blocking() is deprecated, - use socket_set_blocking() instead - */ PHP_FE(set_socket_blocking, NULL) - PHP_FE(socket_set_blocking, NULL) + PHP_FE(stream_set_blocking, NULL) + PHP_FALIAS(socket_set_blocking, stream_set_blocking, NULL) PHP_FE(file_get_meta_data, NULL) PHP_FE(file_register_wrapper, NULL) diff --git a/ext/standard/file.c b/ext/standard/file.c index 38497a4a71..419cab56dd 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -639,6 +639,130 @@ PHP_FUNCTION(file_get_meta_data) } /* }}} */ +static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, int *max_fd TSRMLS_DC) +{ + zval **elem; + php_stream *stream; + int this_fd; + + if (Z_TYPE_P(stream_array) != IS_ARRAY) + return 0; + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array)); + zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(stream_array))) { + + php_stream_from_zval_no_verify(stream, elem); + if (stream == NULL) + continue; + + /* get the fd */ + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&this_fd, 1)) { + FD_SET(this_fd, fds); + if (this_fd > *max_fd) { + *max_fd = this_fd; + } + } + } + + return 1; + +} + +static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC) +{ + zval **elem, **dest_elem; + php_stream *stream; + HashTable *new_hash; + int this_fd; + + if (Z_TYPE_P(stream_array) != IS_ARRAY) + return 0; + + ALLOC_HASHTABLE(new_hash); + zend_hash_init(new_hash, 0, NULL, ZVAL_PTR_DTOR, 0); + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array)); + zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(stream_array))) { + + php_stream_from_zval_no_verify(stream, elem); + if (stream == NULL) + continue; + + /* get the fd */ + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&this_fd, 1)) { + if (FD_ISSET(this_fd, fds)) { + zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem); + if (dest_elem) + zval_add_ref(dest_elem); + } + } + } + + /* destroy old array and add new one */ + zend_hash_destroy(Z_ARRVAL_P(stream_array)); + efree(Z_ARRVAL_P(stream_array)); + + zend_hash_internal_pointer_reset(new_hash); + Z_ARRVAL_P(stream_array) = new_hash; + + return 1; + +} + + +/* {{{ proto int stream_select(array &read_streams, array &write_streams, array &except_streams, int tv_sec[, int tv_usec]) + Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec */ +PHP_FUNCTION(stream_select) +{ + zval *r_array, *w_array, *e_array, *sec; + struct timeval tv; + struct timeval *tv_p = NULL; + fd_set rfds, wfds, efds; + int max_fd = 0; + int retval, sets = 0, usec = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE) + return; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + if (r_array != NULL) sets += stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC); + if (w_array != NULL) sets += stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC); + if (e_array != NULL) sets += stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC); + + if (!sets) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed"); + RETURN_FALSE; + } + + /* If seconds is not set to null, build the timeval, else we wait indefinitely */ + if (sec != NULL) { + convert_to_long_ex(&sec); + tv.tv_sec = Z_LVAL_P(sec); + tv.tv_usec = usec; + tv_p = &tv; + } + + retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p); + + if (retval == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s", + errno, strerror(errno)); + RETURN_FALSE; + } + + if (r_array != NULL) stream_array_from_fd_set(r_array, &rfds TSRMLS_CC); + if (w_array != NULL) stream_array_from_fd_set(w_array, &wfds TSRMLS_CC); + if (e_array != NULL) stream_array_from_fd_set(e_array, &efds TSRMLS_CC); + + RETURN_LONG(retval); +} + + /* {{{ stream_context related functions */ static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity, char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) @@ -846,6 +970,7 @@ PHP_FUNCTION(stream_context_create) } /* }}} */ +/* {{{ streams filter functions */ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) { zval *zstream; @@ -888,6 +1013,7 @@ PHP_FUNCTION(stream_filter_append) apply_filter_to_stream(1, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ +/* }}} */ /* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]]) Open a file or a URL and return a file pointer */ @@ -1045,9 +1171,9 @@ PHPAPI PHP_FUNCTION(feof) } /* }}} */ -/* {{{ proto bool socket_set_blocking(resource socket, int mode) +/* {{{ proto bool stream_set_blocking(resource socket, int mode) Set blocking/non-blocking mode on a socket or stream */ -PHP_FUNCTION(socket_set_blocking) +PHP_FUNCTION(stream_set_blocking) { zval **arg1, **arg2; int block; @@ -1073,8 +1199,8 @@ PHP_FUNCTION(socket_set_blocking) Set blocking/non-blocking mode on a socket */ PHP_FUNCTION(set_socket_blocking) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, use socket_set_blocking() instead"); - PHP_FN(socket_set_blocking)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, use stream_set_blocking() instead"); + PHP_FN(stream_set_blocking)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ diff --git a/ext/standard/file.h b/ext/standard/file.h index 4e5eba55dd..d8eb1aa301 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -55,7 +55,8 @@ PHP_FUNCTION(copy); PHP_FUNCTION(file); PHP_FUNCTION(file_get_contents); PHP_FUNCTION(set_socket_blocking); /* deprecated */ -PHP_FUNCTION(socket_set_blocking); +PHP_FUNCTION(stream_set_blocking); +PHP_FUNCTION(stream_select); PHP_FUNCTION(socket_set_timeout); PHP_FUNCTION(set_file_buffer); PHP_FUNCTION(get_meta_tags);