if (sslsock->ssl_active) {
int retry = 1;
struct timeval start_time;
- struct timeval *timeout;
- int blocked = sslsock->s.is_blocked;
+ struct timeval *timeout = NULL;
+ int began_blocked = sslsock->s.is_blocked;
int has_timeout = 0;
+ int nr_bytes = 0;
+
+ /* prevent overflow in openssl */
+ if (count > INT_MAX) {
+ count = INT_MAX;
+ }
- /* Begin by making the socket non-blocking. This allows us to check the timeout. */
- if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0)) {
- sslsock->s.is_blocked = 0;
+ /* never use a timeout with non-blocking sockets */
+ if (began_blocked && &sslsock->s.timeout) {
+ timeout = &sslsock->s.timeout;
}
- /* Get the timeout value (and make sure we are to check it. */
- timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
- has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
+ if (timeout && php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC) == SUCCESS) {
+ sslsock->s.is_blocked = 0;
+ }
- /* gettimeofday is not monotonic; using it here is not strictly correct */
- if (has_timeout) {
+ if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec || timeout->tv_usec)) {
+ has_timeout = 1;
+ /* gettimeofday is not monotonic; using it here is not strictly correct */
gettimeofday(&start_time, NULL);
}
gettimeofday(&cur_time, NULL);
/* Determine how much time we've taken so far. */
- elapsed_time = subtract_timeval( cur_time, start_time );
+ elapsed_time = subtract_timeval(cur_time, start_time);
/* and return an error if we've taken too long. */
- if (compare_timeval( elapsed_time, *timeout) > 0 ) {
+ if (compare_timeval(elapsed_time, *timeout) > 0 ) {
/* If the socket was originally blocking, set it back. */
- if (blocked) {
+ if (began_blocked) {
- php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
+ php_set_sock_blocking(sslsock->s.socket, 1);
sslsock->s.is_blocked = 1;
}
+ sslsock->s.timeout_event = 1;
return -1;
}
}
int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
/* If we didn't get any error, then let's return it to PHP. */
- if (err == SSL_ERROR_NONE)
- break;
+ if (err == SSL_ERROR_NONE) {
+ break;
+ }
/* Otherwise, we need to wait again (up to time_left or we get an error) */
- if (blocked) {
+ if (began_blocked) {
if (read) {
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
(POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
}
/* And if we were originally supposed to be blocking, let's reset the socket to that. */
- if (blocked) {
- php_set_sock_blocking(sslsock->s.socket, 1);
- if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC) == SUCCESS) {
++ if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1) == SUCCESS) {
sslsock->s.is_blocked = 1;
}
+
+ return 0 > nr_bytes ? 0 : nr_bytes;
} else {
+ size_t nr_bytes = 0;
+
/*
- * This block is if we had no timeout... We will just sit and wait forever on the IO operation.
+ * This block is if we had no timeout... We will just sit and wait forever on the IO operation.
*/
if (read) {
- nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
+ nr_bytes = php_stream_socket_ops.read(stream, buf, count);
} else {
- nr_bytes = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
+ nr_bytes = php_stream_socket_ops.write(stream, buf, count);
}
- }
- /* PHP doesn't expect a negative return. */
- if (nr_bytes < 0) {
- nr_bytes = 0;
+ return nr_bytes;
}
-
- return nr_bytes;
}
/* }}} */