mirror of https://github.com/moparisthebest/curl
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.
This commit is contained in:
parent
9ac5cdfc2f
commit
f92779198d
|
@ -71,7 +71,9 @@ static OSStatus SocketRead(SSLConnectionRef connection,
|
||||||
UInt32 bytesToGo = *dataLength;
|
UInt32 bytesToGo = *dataLength;
|
||||||
UInt32 initLen = bytesToGo;
|
UInt32 initLen = bytesToGo;
|
||||||
UInt8 *currData = (UInt8 *)data;
|
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;
|
OSStatus rtn = noErr;
|
||||||
UInt32 bytesRead;
|
UInt32 bytesRead;
|
||||||
int rrtn;
|
int rrtn;
|
||||||
|
@ -100,6 +102,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
|
||||||
break;
|
break;
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
rtn = errSSLWouldBlock;
|
rtn = errSSLWouldBlock;
|
||||||
|
connssl->ssl_direction = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rtn = ioErr;
|
rtn = ioErr;
|
||||||
|
@ -128,7 +131,9 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
|
||||||
size_t *dataLength) /* IN/OUT */
|
size_t *dataLength) /* IN/OUT */
|
||||||
{
|
{
|
||||||
UInt32 bytesSent = 0;
|
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;
|
int length;
|
||||||
UInt32 dataLen = *dataLength;
|
UInt32 dataLen = *dataLength;
|
||||||
const UInt8 *dataPtr = (UInt8 *)data;
|
const UInt8 *dataPtr = (UInt8 *)data;
|
||||||
|
@ -148,6 +153,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
|
||||||
theErr = errno;
|
theErr = errno;
|
||||||
if(theErr == EAGAIN) {
|
if(theErr == EAGAIN) {
|
||||||
ortn = errSSLWouldBlock;
|
ortn = errSSLWouldBlock;
|
||||||
|
connssl->ssl_direction = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ortn = ioErr;
|
ortn = ioErr;
|
||||||
|
@ -388,7 +394,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||||
#else
|
#else
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#endif
|
#endif
|
||||||
SSLConnectionRef ssl_connection;
|
/*SSLConnectionRef ssl_connection;*/
|
||||||
OSStatus err = noErr;
|
OSStatus err = noErr;
|
||||||
|
|
||||||
if(connssl->ssl_ctx)
|
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
|
* SSLSetConnection() will not copy that address. I've found that
|
||||||
* conn->sock[sockindex] may change on its own. */
|
* conn->sock[sockindex] may change on its own. */
|
||||||
connssl->ssl_sockfd = sockfd;
|
connssl->ssl_sockfd = sockfd;
|
||||||
ssl_connection = &(connssl->ssl_sockfd);
|
/*ssl_connection = &(connssl->ssl_sockfd);
|
||||||
err = SSLSetConnection(connssl->ssl_ctx, ssl_connection);
|
err = SSLSetConnection(connssl->ssl_ctx, ssl_connection);*/
|
||||||
|
err = SSLSetConnection(connssl->ssl_ctx, connssl);
|
||||||
if(err != noErr) {
|
if(err != noErr) {
|
||||||
failf(data, "SSL: SSLSetConnection() failed: %d", err);
|
failf(data, "SSL: SSLSetConnection() failed: %d", err);
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
@ -488,8 +495,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
||||||
|
|
||||||
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
||||||
|| ssl_connect_2_reading == connssl->connecting_state
|
|| ssl_connect_2_reading == connssl->connecting_state
|
||||||
|| ssl_connect_2_writing == connssl->connecting_state
|
|| ssl_connect_2_writing == connssl->connecting_state);
|
||||||
|| ssl_connect_2_wouldblock == connssl->connecting_state);
|
|
||||||
|
|
||||||
/* Here goes nothing: */
|
/* Here goes nothing: */
|
||||||
err = SSLHandshake(connssl->ssl_ctx);
|
err = SSLHandshake(connssl->ssl_ctx);
|
||||||
|
@ -497,7 +503,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
||||||
if(err != noErr) {
|
if(err != noErr) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case errSSLWouldBlock: /* they're not done with us yet */
|
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;
|
return CURLE_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -609,8 +616,7 @@ darwinssl_connect_common(struct connectdata *conn,
|
||||||
|
|
||||||
while(ssl_connect_2 == connssl->connecting_state ||
|
while(ssl_connect_2 == connssl->connecting_state ||
|
||||||
ssl_connect_2_reading == connssl->connecting_state ||
|
ssl_connect_2_reading == connssl->connecting_state ||
|
||||||
ssl_connect_2_writing == connssl->connecting_state ||
|
ssl_connect_2_writing == connssl->connecting_state) {
|
||||||
ssl_connect_2_wouldblock == connssl->connecting_state) {
|
|
||||||
|
|
||||||
/* check allowed time left */
|
/* check allowed time left */
|
||||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
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 ssl is expecting something, check if it's available. */
|
||||||
if(connssl->connecting_state == ssl_connect_2_reading
|
if(connssl->connecting_state == ssl_connect_2_reading
|
||||||
|| connssl->connecting_state == ssl_connect_2_writing
|
|| connssl->connecting_state == ssl_connect_2_writing) {
|
||||||
|| connssl->connecting_state == ssl_connect_2_wouldblock) {
|
|
||||||
|
|
||||||
curl_socket_t writefd = ssl_connect_2_writing
|
curl_socket_t writefd = ssl_connect_2_writing ==
|
||||||
|| ssl_connect_2_wouldblock ==
|
|
||||||
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
||||||
curl_socket_t readfd = ssl_connect_2_reading
|
curl_socket_t readfd = ssl_connect_2_reading ==
|
||||||
|| ssl_connect_2_wouldblock ==
|
|
||||||
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
|
||||||
|
|
||||||
what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
|
what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
|
||||||
|
@ -663,8 +666,7 @@ darwinssl_connect_common(struct connectdata *conn,
|
||||||
if(retcode || (nonblocking &&
|
if(retcode || (nonblocking &&
|
||||||
(ssl_connect_2 == connssl->connecting_state ||
|
(ssl_connect_2 == connssl->connecting_state ||
|
||||||
ssl_connect_2_reading == connssl->connecting_state ||
|
ssl_connect_2_reading == connssl->connecting_state ||
|
||||||
ssl_connect_2_writing == connssl->connecting_state ||
|
ssl_connect_2_writing == connssl->connecting_state)))
|
||||||
ssl_connect_2_wouldblock == connssl->connecting_state)))
|
|
||||||
return retcode;
|
return retcode;
|
||||||
|
|
||||||
} /* repeat step2 until all transactions are done. */
|
} /* repeat step2 until all transactions are done. */
|
||||||
|
|
|
@ -1371,9 +1371,10 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL)
|
#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
|
||||||
/* This function is for OpenSSL, GnuTLS and schannel only. It should be
|
defined(USE_DARWINSSL)
|
||||||
made to query the generic SSL layer instead. */
|
/* 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,
|
static int https_getsock(struct connectdata *conn,
|
||||||
curl_socket_t *socks,
|
curl_socket_t *socks,
|
||||||
int numsocks)
|
int numsocks)
|
||||||
|
|
|
@ -248,9 +248,6 @@ typedef enum {
|
||||||
ssl_connect_2,
|
ssl_connect_2,
|
||||||
ssl_connect_2_reading,
|
ssl_connect_2_reading,
|
||||||
ssl_connect_2_writing,
|
ssl_connect_2_writing,
|
||||||
#ifdef USE_DARWINSSL
|
|
||||||
ssl_connect_2_wouldblock,
|
|
||||||
#endif /* USE_DARWINSSL */
|
|
||||||
ssl_connect_3,
|
ssl_connect_3,
|
||||||
ssl_connect_done
|
ssl_connect_done
|
||||||
} ssl_connect_state;
|
} ssl_connect_state;
|
||||||
|
@ -327,6 +324,7 @@ struct ssl_connect_data {
|
||||||
SSLContextRef ssl_ctx;
|
SSLContextRef ssl_ctx;
|
||||||
curl_socket_t ssl_sockfd;
|
curl_socket_t ssl_sockfd;
|
||||||
ssl_connect_state connecting_state;
|
ssl_connect_state connecting_state;
|
||||||
|
bool ssl_direction; /* true if writing, false if reading */
|
||||||
#endif /* USE_DARWINSSL */
|
#endif /* USE_DARWINSSL */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue