diff options
-rw-r--r-- | lib/connect.c | 8 | ||||
-rw-r--r-- | lib/ssluse.c | 74 |
2 files changed, 75 insertions, 7 deletions
diff --git a/lib/connect.c b/lib/connect.c index d7add1067..61e45689e 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -448,8 +448,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ return CURLE_COULDNT_CONNECT; } - /* now disable the non-blocking mode again */ - Curl_nonblock(sockfd, FALSE); + /* leave the socket in non-blocking mode */ if(addr) *addr = ai; /* the address we ended up connected to */ @@ -554,9 +553,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ failf(data, "Couldn't connect to host"); return CURLE_COULDNT_CONNECT; } - - /* now disable the non-blocking mode again */ - Curl_nonblock(sockfd, FALSE); + + /* leave the socket in non-blocking mode */ if(addr) /* this is the address we've connected to */ diff --git a/lib/ssluse.c b/lib/ssluse.c index 55b0a2e09..3c4728ab6 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -736,8 +736,78 @@ Curl_SSLConnect(struct connectdata *conn) } /* pass the raw socket into the SSL layers */ - SSL_set_fd (conn->ssl.handle, conn->firstsocket); - err = SSL_connect (conn->ssl.handle); + SSL_set_fd(conn->ssl.handle, conn->firstsocket); + + do { + int what; + fd_set writefd; + fd_set readfd; + struct timeval interval; + long timeout_ms; + + err = SSL_connect(conn->ssl.handle); + + what = SSL_get_error(conn->ssl.handle, err); + + FD_ZERO(&writefd); + FD_ZERO(&readfd); + + if(SSL_ERROR_WANT_READ == what) + FD_SET(conn->firstsocket, &readfd); + else if(SSL_ERROR_WANT_WRITE == what) + FD_SET(conn->firstsocket, &writefd); + else + break; /* untreated error */ + + /* Find out if any timeout is set. If not, use 300 seconds. + Otherwise, figure out the most strict timeout of the two possible one + and then how much time that has elapsed to know how much time we + allow for the connect call */ + if(data->set.timeout || data->set.connecttimeout) { + double has_passed; + + /* Evaluate in milliseconds how much time that has passed */ + has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + + /* get the most strict timeout of the ones converted to milliseconds */ + if(data->set.timeout && + (data->set.timeout>data->set.connecttimeout)) + timeout_ms = data->set.timeout*1000; + else + timeout_ms = data->set.connecttimeout*1000; + + /* subtract the passed time */ + timeout_ms -= (long)has_passed; + + if(timeout_ms < 0) + /* a precaution, no need to continue if time already is up */ + return CURLE_OPERATION_TIMEOUTED; + } + else + /* no particular time-out has been set */ + timeout_ms=300000; /* milliseconds, default to five minutes */ + + interval.tv_sec = timeout_ms/1000; + timeout_ms -= interval.tv_sec*1000; + + interval.tv_usec = timeout_ms*1000; + + what = select(conn->firstsocket+1, &readfd, &writefd, NULL, &interval); + if(what > 0) + /* reabable or writable, go loop yourself */ + continue; + else if(0 == what) { + /* timeout */ + failf(data, "SSL connection timeout"); + return CURLE_OPERATION_TIMEOUTED; + } + else + break; /* get out of loop */ + } while(1); /* 1 is fine 0 is "not successful but was shut down controlled" |