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 */
/* {{{ 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)
char persistent;
char is_blocked;
size_t chunk_size;
+ struct timeval timeout;
+ int timeout_event;
};
typedef struct php_sockbuf php_sockbuf;
sock->persistent = persistent;
sock->is_blocked = 1;
sock->chunk_size = FG(def_chunk_size);
+ sock->timeout.tv_sec = -1;
FG(phpsockbuf) = sock;
return sock;
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;
}
}
if(sock->is_blocked) {
php_sockwait_for_data(sock);
+ if (sock->timeout_event)
+ return 0;
}
/* read at a maximum sock->chunk_size */
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);
}
}
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)