diff options
-rw-r--r-- | ext/standard/file.c | 40 | ||||
-rw-r--r-- | ext/standard/fsock.c | 28 | ||||
-rw-r--r-- | ext/standard/fsock.h | 1 |
3 files changed, 51 insertions, 18 deletions
diff --git a/ext/standard/file.c b/ext/standard/file.c index f40a80caef..1bc29b2f87 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -240,7 +240,7 @@ function_entry file_functions[] = { PHP_FE(flock, NULL) PHP_FE(get_meta_tags, NULL) PHP_FE(set_socket_blocking, NULL) -#if (0 && defined(HAVE_SYS_TIME_H) && HAVE_SETSOCKOPT && defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)) +#if HAVE_SYS_TIME_H PHP_FE(set_socket_timeout, NULL) #endif #if 0 /* needs to be rethought 991221 thies@digicol.de */ @@ -879,32 +879,40 @@ PHP_FUNCTION(set_socket_blocking) /* {{{ proto int set_socket_timeout(int socket descriptor, int timeout ) NYI */ -#if (0 && defined(HAVE_SYS_TIME_H) && HAVE_SETSOCKOPT && defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)) +#if HAVE_SYS_TIME_H /* this doesn't work, as it appears those properties are read-only :( */ PHP_FUNCTION(set_socket_timeout) { - pval *socket,*timeout; - int type, *sock; + zval **socket, **seconds, **microseconds; + int type; + void *what; + int socketd = 0; struct timeval t; - if (ARG_COUNT(ht)!=2 || zend_get_parameters(ht, 2, &socket, &timeout)==FAILURE) { + if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3 || + zend_get_parameters_ex(ZEND_NUM_ARGS(), &socket, &seconds, µseconds)==FAILURE) { WRONG_PARAM_COUNT; } - convert_to_long(socket); - convert_to_long(timeout); + + what = zend_fetch_resource(socket, -1, "File-Handle", &type, 1, le_socket); + ZEND_VERIFY_RESOURCE(what); + socketd = *(int *)what; - sock = zend_list_find(socket->value.lval, &type); - if (type!=le_socket) { - php_error(E_WARNING,"%d is not a socket id",socket->value.lval); - RETURN_FALSE; + convert_to_long_ex(seconds); + t.tv_sec = (*seconds)->value.lval; + + if (ZEND_NUM_ARGS() == 3) { + convert_to_long_ex(microseconds); + t.tv_usec = (*microseconds)->value.lval % 1000000; + t.tv_sec += (*microseconds)->value.lval / 1000000; } - t.tv_sec = timeout->value.lval; - t.tv_usec = 0; - setsockopt(*sock,SOL_SOCKET,SO_SNDTIMEO,(void *) &t,sizeof(struct timeval)); - setsockopt(*sock,SOL_SOCKET,SO_RCVTIMEO,(void *) &t,sizeof(struct timeval)); + else + t.tv_usec = 0; + + php_sockset_timeout(socketd, &t); RETURN_TRUE; } -#endif +#endif /* HAVE_SYS_TIME_H */ /* }}} */ /* {{{ proto string fgets(int fp, int length) diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index 28eafef6e6..13ce0e72f3 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -116,6 +116,8 @@ struct php_sockbuf { char persistent; char is_blocked; size_t chunk_size; + struct timeval timeout; + int timeout_event; }; typedef struct php_sockbuf php_sockbuf; @@ -459,6 +461,7 @@ static php_sockbuf *php_sockcreate(int socket FLS_DC) sock->persistent = persistent; sock->is_blocked = 1; sock->chunk_size = FG(def_chunk_size); + sock->timeout.tv_sec = -1; FG(phpsockbuf) = sock; return sock; @@ -528,13 +531,25 @@ int php_sock_close(int socket) static void php_sockwait_for_data(php_sockbuf *sock) { fd_set fdr, tfdr; + int retval; + struct timeval timeout; FD_ZERO(&fdr); FD_SET(sock->socket, &fdr); + sock->timeout_event = 0; while(1) { tfdr = fdr; - if(select(sock->socket + 1, &tfdr, NULL, NULL, NULL) == 1) + timeout = sock->timeout; + if (timeout.tv_sec == -1) + retval = select(sock->socket + 1, &tfdr, NULL, NULL, NULL); + else { + retval = select(sock->socket + 1, &tfdr, NULL, NULL, &timeout); + if (retval == 0) + sock->timeout_event = 1; + } + + if(retval == 1 || retval == 0) break; } } @@ -555,6 +570,8 @@ static size_t php_sockread_internal(php_sockbuf *sock) if(sock->is_blocked) { php_sockwait_for_data(sock); + if (sock->timeout_event) + return 0; } /* read at a maximum sock->chunk_size */ @@ -577,7 +594,7 @@ static size_t php_sockread_internal(php_sockbuf *sock) static void php_sockread_total(php_sockbuf *sock, size_t maxread) { - while(!sock->eof && TOREAD(sock) < maxread) { + while(!sock->eof && TOREAD(sock) < maxread && !sock->timeout_event) { php_sockread_internal(sock); } } @@ -609,6 +626,13 @@ int php_sockset_blocking(int socket, int mode) return old; } +void php_sockset_timeout(int socket, struct timeval *timeout) +{ + SOCK_FIND(sock, socket); + + sock->timeout = *timeout; +} + #define SOCK_FIND_AND_READ_MAX(max) \ SOCK_FIND(sock, socket); \ if(sock->is_blocked) php_sockread_total(sock, max); else php_sockread(sock) diff --git a/ext/standard/fsock.h b/ext/standard/fsock.h index d1ef5482d5..4bebecb09c 100644 --- a/ext/standard/fsock.h +++ b/ext/standard/fsock.h @@ -67,6 +67,7 @@ int php_sock_feof(int socket); int php_sock_fgetc(int socket); int php_is_persistent_sock(int); int php_sockset_blocking(int socket, int mode); +void php_sockset_timeout(int socket, struct timeval *timeout); int php_sockdestroy(int socket); int php_sock_close(int socket); size_t php_sock_set_def_chunk_size(size_t size); |