From f92779198d07abb18e8a5c4dd3a2e1b7c4c8726a Mon Sep 17 00:00:00 2001 From: Nick Zitzmann Date: Mon, 16 Jul 2012 20:20:57 -0600 Subject: [PATCH] darwinssl: fixed freeze involving the multi interface Previously the curl_multi interface would freeze if darwinssl was enabled and at least one of the handles tried to connect to a Web site using HTTPS. Removed the "wouldblock" state darwinssl was using because I figured out a solution for our "would block but in which direction?" dilemma. --- lib/curl_darwinssl.c | 38 ++++++++++++++++++++------------------ lib/http.c | 7 ++++--- lib/urldata.h | 4 +--- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/lib/curl_darwinssl.c b/lib/curl_darwinssl.c index 893a6fc..c848be7 100644 --- a/lib/curl_darwinssl.c +++ b/lib/curl_darwinssl.c @@ -71,7 +71,9 @@ static OSStatus SocketRead(SSLConnectionRef connection, UInt32 bytesToGo = *dataLength; UInt32 initLen = bytesToGo; UInt8 *currData = (UInt8 *)data; - int sock = *(int *)connection; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = connssl->ssl_sockfd; OSStatus rtn = noErr; UInt32 bytesRead; int rrtn; @@ -100,6 +102,7 @@ static OSStatus SocketRead(SSLConnectionRef connection, break; case EAGAIN: rtn = errSSLWouldBlock; + connssl->ssl_direction = false; break; default: rtn = ioErr; @@ -128,7 +131,9 @@ static OSStatus SocketWrite(SSLConnectionRef connection, size_t *dataLength) /* IN/OUT */ { UInt32 bytesSent = 0; - int sock = *(int *)connection; + /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + int sock = connssl->ssl_sockfd; int length; UInt32 dataLen = *dataLength; const UInt8 *dataPtr = (UInt8 *)data; @@ -148,6 +153,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection, theErr = errno; if(theErr == EAGAIN) { ortn = errSSLWouldBlock; + connssl->ssl_direction = true; } else { ortn = ioErr; @@ -388,7 +394,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #else struct in_addr addr; #endif - SSLConnectionRef ssl_connection; + /*SSLConnectionRef ssl_connection;*/ OSStatus err = noErr; if(connssl->ssl_ctx) @@ -467,8 +473,9 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, * SSLSetConnection() will not copy that address. I've found that * conn->sock[sockindex] may change on its own. */ connssl->ssl_sockfd = sockfd; - ssl_connection = &(connssl->ssl_sockfd); - err = SSLSetConnection(connssl->ssl_ctx, ssl_connection); + /*ssl_connection = &(connssl->ssl_sockfd); + err = SSLSetConnection(connssl->ssl_ctx, ssl_connection);*/ + err = SSLSetConnection(connssl->ssl_ctx, connssl); if(err != noErr) { failf(data, "SSL: SSLSetConnection() failed: %d", err); return CURLE_SSL_CONNECT_ERROR; @@ -488,8 +495,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state - || ssl_connect_2_writing == connssl->connecting_state - || ssl_connect_2_wouldblock == connssl->connecting_state); + || ssl_connect_2_writing == connssl->connecting_state); /* Here goes nothing: */ err = SSLHandshake(connssl->ssl_ctx); @@ -497,7 +503,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) if(err != noErr) { switch (err) { case errSSLWouldBlock: /* they're not done with us yet */ - connssl->connecting_state = ssl_connect_2_wouldblock; + connssl->connecting_state = connssl->ssl_direction ? + ssl_connect_2_writing : ssl_connect_2_reading; return CURLE_OK; break; @@ -609,8 +616,7 @@ darwinssl_connect_common(struct connectdata *conn, while(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state || - ssl_connect_2_wouldblock == connssl->connecting_state) { + ssl_connect_2_writing == connssl->connecting_state) { /* check allowed time left */ timeout_ms = Curl_timeleft(data, NULL, TRUE); @@ -623,14 +629,11 @@ darwinssl_connect_common(struct connectdata *conn, /* if ssl is expecting something, check if it's available. */ if(connssl->connecting_state == ssl_connect_2_reading - || connssl->connecting_state == ssl_connect_2_writing - || connssl->connecting_state == ssl_connect_2_wouldblock) { + || connssl->connecting_state == ssl_connect_2_writing) { - curl_socket_t writefd = ssl_connect_2_writing - || ssl_connect_2_wouldblock == + curl_socket_t writefd = ssl_connect_2_writing == connssl->connecting_state?sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = ssl_connect_2_reading - || ssl_connect_2_wouldblock == + curl_socket_t readfd = ssl_connect_2_reading == connssl->connecting_state?sockfd:CURL_SOCKET_BAD; what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); @@ -663,8 +666,7 @@ darwinssl_connect_common(struct connectdata *conn, if(retcode || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || - ssl_connect_2_writing == connssl->connecting_state || - ssl_connect_2_wouldblock == connssl->connecting_state))) + ssl_connect_2_writing == connssl->connecting_state))) return retcode; } /* repeat step2 until all transactions are done. */ diff --git a/lib/http.c b/lib/http.c index 06bdf61..0c12d18 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1371,9 +1371,10 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) } #endif -#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) -/* This function is for OpenSSL, GnuTLS and schannel only. It should be - made to query the generic SSL layer instead. */ +#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) +/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. + It should be made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) diff --git a/lib/urldata.h b/lib/urldata.h index 5ad07c5..fddfc0d 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -248,9 +248,6 @@ typedef enum { ssl_connect_2, ssl_connect_2_reading, ssl_connect_2_writing, -#ifdef USE_DARWINSSL - ssl_connect_2_wouldblock, -#endif /* USE_DARWINSSL */ ssl_connect_3, ssl_connect_done } ssl_connect_state; @@ -327,6 +324,7 @@ struct ssl_connect_data { SSLContextRef ssl_ctx; curl_socket_t ssl_sockfd; ssl_connect_state connecting_state; + bool ssl_direction; /* true if writing, false if reading */ #endif /* USE_DARWINSSL */ }; -- 2.7.4