summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/file.c40
-rw-r--r--ext/standard/fsock.c28
-rw-r--r--ext/standard/fsock.h1
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, &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)
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);