cataphract Thu, 23 Dec 2010 01:44:54 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=306581
Log:
- Fixed bug #53592 (stream_socket_enable_crypto() busy-waits in client mode).
- Fixed stream_socket_enable_crypto() not honoring the socket timeout in
server mode.
Bug: http://bugs.php.net/53592 (Assigned) stream_socket_enable_crypto() uses
NONBLOCK
Changed paths:
U php/php-src/branches/PHP_5_3/NEWS
U php/php-src/branches/PHP_5_3/ext/openssl/xp_ssl.c
U php/php-src/trunk/ext/openssl/xp_ssl.c
Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS 2010-12-23 00:17:51 UTC (rev 306580)
+++ php/php-src/branches/PHP_5_3/NEWS 2010-12-23 01:44:54 UTC (rev 306581)
@@ -49,6 +49,10 @@
. Implemented FR #53447 (Cannot disable SessionTicket extension for servers
that do not support it) by adding a no_ticket SSL context option. (Adam,
Tony)
+ . Fixed bug #53592 (stream_socket_enable_crypto() busy-waits in client mode).
+ (Gustavo)
+ . Fixed stream_socket_enable_crypto() not honoring the socket timeout in
+ server mode. (Gustavo)
- PDO Oracle driver:
. Fixed bug #39199 (Cannot load Lob data with more than 4000 bytes on
Modified: php/php-src/branches/PHP_5_3/ext/openssl/xp_ssl.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/openssl/xp_ssl.c 2010-12-23 00:17:51 UTC (rev 306580)
+++ php/php-src/branches/PHP_5_3/ext/openssl/xp_ssl.c 2010-12-23 01:44:54 UTC (rev 306581)
@@ -411,8 +411,10 @@
int n, retry = 1;
if (cparam->inputs.activate && !sslsock->ssl_active) {
- float timeout = sslsock->connect_timeout.tv_sec + sslsock->connect_timeout.tv_usec / 1000000;
- int blocked = sslsock->s.is_blocked;
+ struct timeval start_time,
+ *timeout;
+ int blocked = sslsock->s.is_blocked,
+ has_timeout = 0;
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
if (sslsock->is_client && sslsock->sni) {
@@ -429,36 +431,70 @@
sslsock->state_set = 1;
}
- if (sslsock->is_client && SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
- sslsock->s.is_blocked = 0;
+ if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
+ sslsock->s.is_blocked = 0;
}
+
+ timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
+ has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
+ /* gettimeofday is not monotonic; using it here is not strictly correct */
+ if (has_timeout) {
+ gettimeofday(&start_time, NULL);
+ }
+
do {
+ struct timeval cur_time,
+ elapsed_time;
+
if (sslsock->is_client) {
- struct timeval tvs, tve;
- struct timezone tz;
-
- gettimeofday(&tvs, &tz);
n = SSL_connect(sslsock->ssl_handle);
- gettimeofday(&tve, &tz);
+ } else {
+ n = SSL_accept(sslsock->ssl_handle);
+ }
- timeout -= (tve.tv_sec + (float) tve.tv_usec / 1000000) - (tvs.tv_sec + (float) tvs.tv_usec / 1000000);
- if (timeout < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: connection timeout");
+ if (has_timeout) {
+ gettimeofday(&cur_time, NULL);
+ elapsed_time.tv_sec = cur_time.tv_sec - start_time.tv_sec;
+ elapsed_time.tv_usec = cur_time.tv_usec - start_time.tv_usec;
+ if (cur_time.tv_usec < start_time.tv_usec) {
+ elapsed_time.tv_sec -= 1L;
+ elapsed_time.tv_usec += 1000000L;
+ }
+
+ if (elapsed_time.tv_sec > timeout->tv_sec ||
+ (elapsed_time.tv_sec == timeout->tv_sec &&
+ elapsed_time.tv_usec > timeout->tv_usec)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: crypto enabling timeout");
return -1;
}
- } else {
- n = SSL_accept(sslsock->ssl_handle);
}
if (n <= 0) {
- retry = handle_ssl_error(stream, n, sslsock->is_client || sslsock->s.is_blocked TSRMLS_CC);
-
+ /* in case of SSL_ERROR_WANT_READ/WRITE, do not retry in non-blocking mode */
+ retry = handle_ssl_error(stream, n, blocked TSRMLS_CC);
+ if (retry) {
+ /* wait until something interesting happens in the socket. It may be a
+ * timeout. Also consider the unlikely of possibility of a write block */
+ int err = SSL_get_error(sslsock->ssl_handle, n);
+ struct timeval left_time;
+
+ if (has_timeout) {
+ left_time.tv_sec = timeout->tv_sec - elapsed_time.tv_sec;
+ left_time.tv_usec = timeout->tv_usec - elapsed_time.tv_usec;
+ if (timeout->tv_usec < elapsed_time.tv_usec) {
+ left_time.tv_sec -= 1L;
+ left_time.tv_usec += 1000000L;
+ }
+ }
+ php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
+ (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);
+ }
} else {
- break;
+ retry = 0;
}
} while (retry);
- if (sslsock->is_client && sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) {
+ if (sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) {
sslsock->s.is_blocked = blocked;
}
Modified: php/php-src/trunk/ext/openssl/xp_ssl.c
===================================================================
--- php/php-src/trunk/ext/openssl/xp_ssl.c 2010-12-23 00:17:51 UTC (rev 306580)
+++ php/php-src/trunk/ext/openssl/xp_ssl.c 2010-12-23 01:44:54 UTC (rev 306581)
@@ -411,8 +411,10 @@
int n, retry = 1;
if (cparam->inputs.activate && !sslsock->ssl_active) {
- float timeout = sslsock->connect_timeout.tv_sec + sslsock->connect_timeout.tv_usec / 1000000;
- int blocked = sslsock->s.is_blocked;
+ struct timeval start_time,
+ *timeout;
+ int blocked = sslsock->s.is_blocked,
+ has_timeout = 0;
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
if (sslsock->is_client && sslsock->sni) {
@@ -429,36 +431,70 @@
sslsock->state_set = 1;
}
- if (sslsock->is_client && SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
- sslsock->s.is_blocked = 0;
+ if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
+ sslsock->s.is_blocked = 0;
}
+
+ timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
+ has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
+ /* gettimeofday is not monotonic; using it here is not strictly correct */
+ if (has_timeout) {
+ gettimeofday(&start_time, NULL);
+ }
+
do {
+ struct timeval cur_time,
+ elapsed_time;
+
if (sslsock->is_client) {
- struct timeval tvs, tve;
- struct timezone tz;
-
- gettimeofday(&tvs, &tz);
n = SSL_connect(sslsock->ssl_handle);
- gettimeofday(&tve, &tz);
+ } else {
+ n = SSL_accept(sslsock->ssl_handle);
+ }
- timeout -= (tve.tv_sec + (float) tve.tv_usec / 1000000) - (tvs.tv_sec + (float) tvs.tv_usec / 1000000);
- if (timeout < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: connection timeout");
+ if (has_timeout) {
+ gettimeofday(&cur_time, NULL);
+ elapsed_time.tv_sec = cur_time.tv_sec - start_time.tv_sec;
+ elapsed_time.tv_usec = cur_time.tv_usec - start_time.tv_usec;
+ if (cur_time.tv_usec < start_time.tv_usec) {
+ elapsed_time.tv_sec -= 1L;
+ elapsed_time.tv_usec += 1000000L;
+ }
+
+ if (elapsed_time.tv_sec > timeout->tv_sec ||
+ (elapsed_time.tv_sec == timeout->tv_sec &&
+ elapsed_time.tv_usec > timeout->tv_usec)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: crypto enabling timeout");
return -1;
}
- } else {
- n = SSL_accept(sslsock->ssl_handle);
}
if (n <= 0) {
- retry = handle_ssl_error(stream, n, sslsock->is_client || sslsock->s.is_blocked TSRMLS_CC);
-
+ /* in case of SSL_ERROR_WANT_READ/WRITE, do not retry in non-blocking mode */
+ retry = handle_ssl_error(stream, n, blocked TSRMLS_CC);
+ if (retry) {
+ /* wait until something interesting happens in the socket. It may be a
+ * timeout. Also consider the unlikely of possibility of a write block */
+ int err = SSL_get_error(sslsock->ssl_handle, n);
+ struct timeval left_time;
+
+ if (has_timeout) {
+ left_time.tv_sec = timeout->tv_sec - elapsed_time.tv_sec;
+ left_time.tv_usec = timeout->tv_usec - elapsed_time.tv_usec;
+ if (timeout->tv_usec < elapsed_time.tv_usec) {
+ left_time.tv_sec -= 1L;
+ left_time.tv_usec += 1000000L;
+ }
+ }
+ php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
+ (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);
+ }
} else {
- break;
+ retry = 0;
}
} while (retry);
- if (sslsock->is_client && sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) {
+ if (sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) {
sslsock->s.is_blocked = blocked;
}
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php