]> granicus.if.org Git - php/commitdiff
Added ability to set timeout on socket read operations. New function
authorAndrei Zmievski <andrei@php.net>
Sat, 15 Jan 2000 19:41:17 +0000 (19:41 +0000)
committerAndrei Zmievski <andrei@php.net>
Sat, 15 Jan 2000 19:41:17 +0000 (19:41 +0000)
set_socket_timeout(socket, seconds, microseconds) sets the timeout.
@- Added ability to set timeout on socket read operations through
@ set_socket_timeout() function. (Andrei)

ext/standard/file.c
ext/standard/fsock.c
ext/standard/fsock.h

index f40a80caef4ef2010697e60a232f0071a0f186a5..1bc29b2f877bc6652c2eca08f65f2c6ed3db9910 100644 (file)
@@ -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, &microseconds)==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)
index 28eafef6e64375432b69ea5c82746b95097d922e..13ce0e72f3ef45ce6f9af85b8d4fb290b5daf4a7 100644 (file)
@@ -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)
index d1ef5482d526856ba21712c8935ec688cbfb2840..4bebecb09ca3053b60aff676cb0b28b0069064d6 100644 (file)
@@ -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);