cfilter: remove 'blocking' connect handling

Remove `blocking` argument from cfilter's connect method.

Implement blocking behaviour in Curl_conn_connect() instead for all
filter chains.

Update filters implementations. Several of which did never use the
paramter (QUIC for example). Simplifies connect handling in TLS filters
that no longer need to loop

Fixed a blocking connect call in FTP when waiting on a socket accept()
which only worked because the filter did not implement it.

Closes #16397
This commit is contained in:
Stefan Eissing 2025-02-19 16:49:31 +01:00 committed by Daniel Stenberg
parent 654f8cb5f3
commit a1850ad7de
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
29 changed files with 250 additions and 850 deletions

View File

@ -598,7 +598,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
infof(data, "Connect me again please"); infof(data, "Connect me again please");
Curl_conn_cf_close(cf, data); Curl_conn_cf_close(cf, data);
connkeep(conn, "HTTP proxy CONNECT"); connkeep(conn, "HTTP proxy CONNECT");
result = Curl_conn_cf_connect(cf->next, data, FALSE, &done); result = Curl_conn_cf_connect(cf->next, data, &done);
goto out; goto out;
} }
else { else {
@ -638,7 +638,7 @@ out:
static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf, static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
CURLcode result; CURLcode result;
struct h1_tunnel_state *ts = cf->ctx; struct h1_tunnel_state *ts = cf->ctx;
@ -649,7 +649,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
} }
CURL_TRC_CF(data, cf, "connect"); CURL_TRC_CF(data, cf, "connect");
result = cf->next->cft->do_connect(cf->next, data, blocking, done); result = cf->next->cft->do_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;

View File

@ -1090,7 +1090,7 @@ out:
static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf, static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_h2_proxy_ctx *ctx = cf->ctx; struct cf_h2_proxy_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1105,7 +1105,7 @@ static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
/* Connect the lower filters first */ /* Connect the lower filters first */
if(!cf->next->connected) { if(!cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, blocking, done); result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }

View File

@ -105,7 +105,7 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf, static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_haproxy_ctx *ctx = cf->ctx; struct cf_haproxy_ctx *ctx = cf->ctx;
CURLcode result; CURLcode result;
@ -117,7 +117,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
result = cf->next->cft->do_connect(cf->next, data, blocking, done); result = cf->next->cft->do_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;

View File

@ -175,7 +175,7 @@ static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
struct Curl_cfilter *save = cf->next; struct Curl_cfilter *save = cf->next;
cf->next = b->cf; cf->next = b->cf;
b->result = Curl_conn_cf_connect(cf->next, data, FALSE, done); b->result = Curl_conn_cf_connect(cf->next, data, done);
b->cf = cf->next; /* it might mutate */ b->cf = cf->next; /* it might mutate */
cf->next = save; cf->next = save;
return b->result; return b->result;
@ -291,14 +291,13 @@ static bool time_to_start_next(struct Curl_cfilter *cf,
static CURLcode cf_hc_connect(struct Curl_cfilter *cf, static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_hc_ctx *ctx = cf->ctx; struct cf_hc_ctx *ctx = cf->ctx;
struct curltime now; struct curltime now;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
size_t i, failed_ballers; size_t i, failed_ballers;
(void)blocking;
if(cf->connected) { if(cf->connected) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;

View File

@ -1304,7 +1304,7 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_socket_ctx *ctx = cf->ctx; struct cf_socket_ctx *ctx = cf->ctx;
CURLcode result = CURLE_COULDNT_CONNECT; CURLcode result = CURLE_COULDNT_CONNECT;
@ -1316,9 +1316,6 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
if(blocking)
return CURLE_UNSUPPORTED_PROTOCOL;
*done = FALSE; /* a negative world view is best */ *done = FALSE; /* a negative world view is best */
if(ctx->sock == CURL_SOCKET_BAD) { if(ctx->sock == CURL_SOCKET_BAD) {
int error; int error;
@ -1889,12 +1886,11 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
static CURLcode cf_udp_connect(struct Curl_cfilter *cf, static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_socket_ctx *ctx = cf->ctx; struct cf_socket_ctx *ctx = cf->ctx;
CURLcode result = CURLE_COULDNT_CONNECT; CURLcode result = CURLE_COULDNT_CONNECT;
(void)blocking;
if(cf->connected) { if(cf->connected) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
@ -2099,7 +2095,7 @@ static void cf_tcp_set_accepted_remote_ip(struct Curl_cfilter *cf,
static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf, static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_socket_ctx *ctx = cf->ctx; struct cf_socket_ctx *ctx = cf->ctx;
#ifdef USE_IPV6 #ifdef USE_IPV6
@ -2115,7 +2111,6 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
/* we start accepted, if we ever close, we cannot go on */ /* we start accepted, if we ever close, we cannot go on */
(void)data; (void)data;
(void)blocking;
if(cf->connected) { if(cf->connected) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;

View File

@ -368,10 +368,10 @@ bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf, CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
if(cf) if(cf)
return cf->cft->do_connect(cf, data, blocking, done); return cf->cft->do_connect(cf, data, done);
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
} }
@ -405,6 +405,9 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
bool blocking, bool blocking,
bool *done) bool *done)
{ {
#define CF_CONN_NUM_POLLS_ON_STACK 5
struct pollfd a_few_on_stack[CF_CONN_NUM_POLLS_ON_STACK];
struct curl_pollfds cpfds;
struct Curl_cfilter *cf; struct Curl_cfilter *cf;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -419,7 +422,11 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
} }
*done = cf->connected; *done = cf->connected;
if(!*done) { if(*done)
return CURLE_OK;
Curl_pollfds_init(&cpfds, a_few_on_stack, CF_CONN_NUM_POLLS_ON_STACK);
while(!*done) {
if(Curl_conn_needs_flush(data, sockindex)) { if(Curl_conn_needs_flush(data, sockindex)) {
DEBUGF(infof(data, "Curl_conn_connect(index=%d), flush", sockindex)); DEBUGF(infof(data, "Curl_conn_connect(index=%d), flush", sockindex));
result = Curl_conn_flush(data, sockindex); result = Curl_conn_flush(data, sockindex);
@ -427,7 +434,9 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
return result; return result;
} }
result = cf->cft->do_connect(cf, data, blocking, done); result = cf->cft->do_connect(cf, data, done);
CURL_TRC_CF(data, cf, "Curl_conn_connect(block=%d) -> %d, done=%d",
blocking, result, *done);
if(!result && *done) { if(!result && *done) {
/* Now that the complete filter chain is connected, let all filters /* Now that the complete filter chain is connected, let all filters
* persist information at the connection. E.g. cf-socket sets the * persist information at the connection. E.g. cf-socket sets the
@ -436,12 +445,56 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
conn_report_connect_stats(data, data->conn); conn_report_connect_stats(data, data->conn);
data->conn->keepalive = Curl_now(); data->conn->keepalive = Curl_now();
Curl_verboseconnect(data, data->conn, sockindex); Curl_verboseconnect(data, data->conn, sockindex);
goto out;
} }
else if(result) { else if(result) {
CURL_TRC_CF(data, cf, "Curl_conn_connect(), filter returned %d",
result);
conn_report_connect_stats(data, data->conn); conn_report_connect_stats(data, data->conn);
goto out;
}
if(!blocking)
goto out;
else {
/* check allowed time left */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
struct easy_pollset ps;
int rc;
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "connect timeout");
result = CURLE_OPERATION_TIMEDOUT;
goto out;
}
CURL_TRC_CF(data, cf, "Curl_conn_connect(block=1), do poll");
Curl_pollfds_reset(&cpfds);
memset(&ps, 0, sizeof(ps));
/* In general, we want to send after connect, wait on that. */
if(sockfd != CURL_SOCKET_BAD)
Curl_pollset_set_out_only(data, &ps, sockfd);
Curl_conn_adjust_pollset(data, &ps);
result = Curl_pollfds_add_ps(&cpfds, &ps);
if(result)
goto out;
rc = Curl_poll(cpfds.pfds, cpfds.n,
CURLMIN(timeout_ms, (cpfds.n ? 1000 : 10)));
CURL_TRC_CF(data, cf, "Curl_conn_connect(block=1), Curl_poll() -> %d",
rc);
if(rc < 0) {
result = CURLE_COULDNT_CONNECT;
goto out;
}
/* continue iterating */
} }
} }
out:
Curl_pollfds_cleanup(&cpfds);
return result; return result;
} }

View File

@ -51,7 +51,7 @@ typedef CURLcode Curl_cft_shutdown(struct Curl_cfilter *cf,
typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf, typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done); bool *done);
/* Return the hostname and port the connection goes to. /* Return the hostname and port the connection goes to.
* This may change with the connection state of filters when tunneling * This may change with the connection state of filters when tunneling
@ -324,7 +324,7 @@ void Curl_conn_cf_discard_all(struct Curl_easy *data,
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf, CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done); bool *done);
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data); void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, bool eos, const void *buf, size_t len, bool eos,

View File

@ -593,7 +593,7 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
*connected = baller->connected; *connected = baller->connected;
if(!baller->result && !*connected) { if(!baller->result && !*connected) {
/* evaluate again */ /* evaluate again */
baller->result = Curl_conn_cf_connect(baller->cf, data, 0, connected); baller->result = Curl_conn_cf_connect(baller->cf, data, connected);
if(!baller->result) { if(!baller->result) {
if(*connected) { if(*connected) {
@ -948,7 +948,7 @@ static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
static CURLcode cf_he_connect(struct Curl_cfilter *cf, static CURLcode cf_he_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_he_ctx *ctx = cf->ctx; struct cf_he_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -958,7 +958,6 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
(void)blocking;
DEBUGASSERT(ctx); DEBUGASSERT(ctx);
*done = FALSE; *done = FALSE;
@ -1263,7 +1262,7 @@ struct cf_setup_ctx {
static CURLcode cf_setup_connect(struct Curl_cfilter *cf, static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_setup_ctx *ctx = cf->ctx; struct cf_setup_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1276,7 +1275,7 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
/* connect current sub-chain */ /* connect current sub-chain */
connect_sub_chain: connect_sub_chain:
if(cf->next && !cf->next->connected) { if(cf->next && !cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, blocking, done); result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }

View File

@ -3603,7 +3603,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
if(ftpc->wait_data_conn) { if(ftpc->wait_data_conn) {
bool serv_conned; bool serv_conned;
result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &serv_conned); result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &serv_conned);
if(result) if(result)
return result; /* Failed to accept data connection */ return result; /* Failed to accept data connection */

View File

@ -2441,7 +2441,7 @@ static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
static CURLcode cf_h2_connect(struct Curl_cfilter *cf, static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_h2_ctx *ctx = cf->ctx; struct cf_h2_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -2455,7 +2455,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
/* Connect the lower filters first */ /* Connect the lower filters first */
if(!cf->next->connected) { if(!cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, blocking, done); result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }
@ -2827,7 +2827,7 @@ CURLcode Curl_http2_switch(struct Curl_easy *data)
if(cf->next) { if(cf->next) {
bool done; bool done;
return Curl_conn_cf_connect(cf, data, FALSE, &done); return Curl_conn_cf_connect(cf, data, &done);
} }
return CURLE_OK; return CURLE_OK;
} }
@ -2849,7 +2849,7 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
if(cf_h2->next) { if(cf_h2->next) {
bool done; bool done;
return Curl_conn_cf_connect(cf_h2, data, FALSE, &done); return Curl_conn_cf_connect(cf_h2, data, &done);
} }
return CURLE_OK; return CURLE_OK;
} }
@ -2900,7 +2900,7 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
if(cf->next) { if(cf->next) {
bool done; bool done;
return Curl_conn_cf_connect(cf, data, FALSE, &done); return Curl_conn_cf_connect(cf, data, &done);
} }
return CURLE_OK; return CURLE_OK;
} }

View File

@ -307,7 +307,7 @@ out:
static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf, static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_proxy_ctx *ctx = cf->ctx; struct cf_proxy_ctx *ctx = cf->ctx;
CURLcode result; CURLcode result;
@ -319,7 +319,7 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
CURL_TRC_CF(data, cf, "connect"); CURL_TRC_CF(data, cf, "connect");
connect_sub: connect_sub:
result = cf->next->cft->do_connect(cf->next, data, blocking, done); result = cf->next->cft->do_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;

View File

@ -410,6 +410,11 @@ void Curl_pollfds_init(struct curl_pollfds *cpfds,
} }
} }
void Curl_pollfds_reset(struct curl_pollfds *cpfds)
{
cpfds->n = 0;
}
void Curl_pollfds_cleanup(struct curl_pollfds *cpfds) void Curl_pollfds_cleanup(struct curl_pollfds *cpfds)
{ {
DEBUGASSERT(cpfds); DEBUGASSERT(cpfds);

View File

@ -122,6 +122,8 @@ void Curl_pollfds_init(struct curl_pollfds *cpfds,
struct pollfd *static_pfds, struct pollfd *static_pfds,
unsigned int static_count); unsigned int static_count);
void Curl_pollfds_reset(struct curl_pollfds *cpfds);
void Curl_pollfds_cleanup(struct curl_pollfds *cpfds); void Curl_pollfds_cleanup(struct curl_pollfds *cpfds);
CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds, CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds,

View File

@ -1128,7 +1128,7 @@ static void socks_proxy_cf_free(struct Curl_cfilter *cf)
*/ */
static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
CURLcode result; CURLcode result;
struct connectdata *conn = cf->conn; struct connectdata *conn = cf->conn;
@ -1140,7 +1140,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
result = cf->next->cft->do_connect(cf->next, data, blocking, done); result = cf->next->cft->do_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;

View File

@ -877,13 +877,12 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
static CURLcode cf_msh3_connect(struct Curl_cfilter *cf, static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_msh3_ctx *ctx = cf->ctx; struct cf_msh3_ctx *ctx = cf->ctx;
struct cf_call_data save; struct cf_call_data save;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
(void)blocking;
if(cf->connected) { if(cf->connected) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;

View File

@ -2453,7 +2453,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_ngtcp2_ctx *ctx = cf->ctx; struct cf_ngtcp2_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -2468,7 +2468,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
/* Connect the UDP filter first */ /* Connect the UDP filter first */
if(!cf->next->connected) { if(!cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, blocking, done); result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }

View File

@ -1718,7 +1718,7 @@ out:
static CURLcode cf_osslq_connect(struct Curl_cfilter *cf, static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_osslq_ctx *ctx = cf->ctx; struct cf_osslq_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1733,7 +1733,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
/* Connect the UDP filter first */ /* Connect the UDP filter first */
if(!cf->next->connected) { if(!cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, blocking, done); result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }

View File

@ -1378,7 +1378,7 @@ static CURLcode cf_quiche_verify_peer(struct Curl_cfilter *cf,
static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_quiche_ctx *ctx = cf->ctx; struct cf_quiche_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -1390,7 +1390,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
/* Connect the UDP filter first */ /* Connect the UDP filter first */
if(!cf->next->connected) { if(!cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, blocking, done); result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }

View File

@ -911,18 +911,14 @@ static ssize_t bearssl_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
return applen; return applen;
} }
static CURLcode bearssl_connect_common(struct Curl_cfilter *cf, static CURLcode bearssl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking,
bool *done) bool *done)
{ {
CURLcode ret; CURLcode ret;
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
CURL_TRC_CF(data, cf, "connect_common(blocking=%d)", !nonblocking); CURL_TRC_CF(data, cf, "connect()");
/* check if the connection has already been established */ /* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) { if(ssl_connection_complete == connssl->state) {
CURL_TRC_CF(data, cf, "connect_common, connected"); CURL_TRC_CF(data, cf, "connect_common, connected");
@ -930,61 +926,18 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
*done = FALSE;
connssl->io_need = CURL_SSL_IO_NEED_NONE;
if(ssl_connect_1 == connssl->connecting_state) { if(ssl_connect_1 == connssl->connecting_state) {
ret = bearssl_connect_step1(cf, data); ret = bearssl_connect_step1(cf, data);
if(ret) if(ret)
return ret; return ret;
} }
while(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
/* check allowed time left */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
/* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
CURL_TRC_CF(data, cf, "connect_common, check socket");
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 : timeout_ms);
CURL_TRC_CF(data, cf, "connect_common, check socket -> %d", what);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking) {
*done = FALSE;
return CURLE_OK;
}
else {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
/* Run transaction, and return to the caller if it failed or if this
* connection is done nonblocking and this loop would execute again. This
* permits the owner of a multi handle to abort a connection attempt
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
connssl->io_need = CURL_SSL_IO_NEED_NONE;
ret = bearssl_connect_step2(cf, data); ret = bearssl_connect_step2(cf, data);
if(ret || (nonblocking && (ssl_connect_2 == connssl->connecting_state))) if(ret)
return ret; return ret;
} }
@ -998,11 +951,6 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
*done = TRUE; *done = TRUE;
} }
else
*done = FALSE;
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK; return CURLE_OK;
} }
@ -1044,28 +992,6 @@ static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode bearssl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode ret;
bool done = FALSE;
ret = bearssl_connect_common(cf, data, FALSE, &done);
if(ret)
return ret;
DEBUGASSERT(done);
return CURLE_OK;
}
static CURLcode bearssl_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
return bearssl_connect_common(cf, data, TRUE, done);
}
static void *bearssl_get_internals(struct ssl_connect_data *connssl, static void *bearssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
{ {
@ -1161,7 +1087,6 @@ const struct Curl_ssl Curl_ssl_bearssl = {
bearssl_random, /* random */ bearssl_random, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
bearssl_connect, /* connect */ bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
bearssl_get_internals, /* get_internals */ bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */ bearssl_close, /* close_one */

View File

@ -238,60 +238,16 @@ static void unload_file(gnutls_datum_t data)
/* this function does a SSL/TLS (re-)handshake */ /* this function does a SSL/TLS (re-)handshake */
static CURLcode handshake(struct Curl_cfilter *cf, static CURLcode handshake(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data)
bool duringconnect,
bool nonblocking)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct gtls_ssl_backend_data *backend = struct gtls_ssl_backend_data *backend =
(struct gtls_ssl_backend_data *)connssl->backend; (struct gtls_ssl_backend_data *)connssl->backend;
gnutls_session_t session; gnutls_session_t session;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); int rc;
DEBUGASSERT(backend); DEBUGASSERT(backend);
session = backend->gtls.session; session = backend->gtls.session;
connssl->connecting_state = ssl_connect_2;
for(;;) {
timediff_t timeout_ms;
int rc;
/* check allowed time left */
timeout_ms = Curl_timeleft(data, NULL, duringconnect);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
/* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
int what;
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 :
timeout_ms ? timeout_ms : 1000);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking)
return CURLE_AGAIN;
else if(timeout_ms) {
/* timeout */
failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
connssl->io_need = CURL_SSL_IO_NEED_NONE; connssl->io_need = CURL_SSL_IO_NEED_NONE;
backend->gtls.io_result = CURLE_OK; backend->gtls.io_result = CURLE_OK;
@ -309,7 +265,7 @@ static CURLcode handshake(struct Curl_cfilter *cf,
connssl->io_need = connssl->io_need =
gnutls_record_get_direction(session) ? gnutls_record_get_direction(session) ?
CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV; CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
continue; return CURLE_AGAIN;
} }
else if((rc < 0) && !gnutls_error_is_fatal(rc)) { else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
const char *strerr = NULL; const char *strerr = NULL;
@ -323,7 +279,7 @@ static CURLcode handshake(struct Curl_cfilter *cf,
strerr = gnutls_strerror(rc); strerr = gnutls_strerror(rc);
infof(data, "gnutls_handshake() warning: %s", strerr); infof(data, "gnutls_handshake() warning: %s", strerr);
continue; return CURLE_AGAIN;
} }
else if((rc < 0) && backend->gtls.io_result) { else if((rc < 0) && backend->gtls.io_result) {
return backend->gtls.io_result; return backend->gtls.io_result;
@ -343,10 +299,7 @@ static CURLcode handshake(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK; return CURLE_OK;
}
} }
static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type) static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type)
@ -1258,7 +1211,6 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
CURLcode result; CURLcode result;
DEBUGASSERT(backend); DEBUGASSERT(backend);
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
if(connssl->state == ssl_connection_complete) if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the /* to make us tolerant against being called more than once for the
@ -1901,10 +1853,8 @@ out:
'ssl_connect_2' (doing handshake with the server), and 'ssl_connect_2' (doing handshake with the server), and
'ssl_connect_3' (verifying and getting stats). 'ssl_connect_3' (verifying and getting stats).
*/ */
static CURLcode static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
gtls_connect_common(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking,
bool *done) { bool *done) {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct gtls_ssl_backend_data *backend = struct gtls_ssl_backend_data *backend =
@ -1912,6 +1862,13 @@ gtls_connect_common(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
DEBUGASSERT(backend); DEBUGASSERT(backend);
/* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) {
*done = TRUE;
return CURLE_OK;
}
*done = FALSE;
/* Initiate the connection, if not already done */ /* Initiate the connection, if not already done */
if(connssl->connecting_state == ssl_connect_1) { if(connssl->connecting_state == ssl_connect_1) {
@ -1936,7 +1893,7 @@ gtls_connect_common(struct Curl_cfilter *cf,
DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) || DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
(connssl->earlydata_state == ssl_earlydata_sent)); (connssl->earlydata_state == ssl_earlydata_sent));
result = handshake(cf, data, TRUE, nonblocking); result = handshake(cf, data);
if(result) if(result)
goto out; goto out;
connssl->connecting_state = ssl_connect_3; connssl->connecting_state = ssl_connect_3;
@ -1951,7 +1908,6 @@ gtls_connect_common(struct Curl_cfilter *cf,
goto out; goto out;
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
connssl->connecting_state = ssl_connect_1;
rc = gnutls_alpn_get_selected_protocol(backend->gtls.session, &proto); rc = gnutls_alpn_get_selected_protocol(backend->gtls.session, &proto);
if(rc) { /* No ALPN from server */ if(rc) { /* No ALPN from server */
@ -1982,6 +1938,12 @@ gtls_connect_common(struct Curl_cfilter *cf,
connssl->earlydata_skip = 0; connssl->earlydata_skip = 0;
} }
} }
connssl->connecting_state = ssl_connect_done;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
*done = TRUE;
} }
out: out:
@ -1994,7 +1956,7 @@ out:
return result; return result;
} }
static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf, static CURLcode gtls_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool *done) bool *done)
{ {
@ -2004,22 +1966,7 @@ static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
} }
return gtls_connect_common(cf, data, TRUE, done); return gtls_connect_common(cf, data, done);
}
static CURLcode gtls_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
result = gtls_connect_common(cf, data, FALSE, &done);
if(result)
return result;
DEBUGASSERT(done);
return CURLE_OK;
} }
static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf, static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf,
@ -2039,7 +1986,7 @@ static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf,
return result; return result;
} }
return gtls_connect_common(cf, data, TRUE, done); return gtls_connect_common(cf, data, done);
} }
static bool gtls_data_pending(struct Curl_cfilter *cf, static bool gtls_data_pending(struct Curl_cfilter *cf,
@ -2272,9 +2219,8 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
if(ret == GNUTLS_E_REHANDSHAKE) { if(ret == GNUTLS_E_REHANDSHAKE) {
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
proper way" takes a whole lot of work. */ proper way" takes a whole lot of work. */
CURLcode result = handshake(cf, data, FALSE, FALSE); CURLcode result = handshake(cf, data);
if(result) if(result)
/* handshake() writes error message on its own */
*curlcode = result; *curlcode = result;
else else
*curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */ *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
@ -2356,7 +2302,6 @@ const struct Curl_ssl Curl_ssl_gnutls = {
gtls_random, /* random */ gtls_random, /* random */
gtls_cert_status_request, /* cert_status_request */ gtls_cert_status_request, /* cert_status_request */
gtls_connect, /* connect */ gtls_connect, /* connect */
gtls_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
gtls_get_internals, /* get_internals */ gtls_get_internals, /* get_internals */
gtls_close, /* close_one */ gtls_close, /* close_one */

View File

@ -1440,16 +1440,12 @@ static CURLcode mbedtls_random(struct Curl_easy *data,
#endif #endif
} }
static CURLcode static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking,
bool *done) bool *done)
{ {
CURLcode retcode; CURLcode retcode;
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
timediff_t timeout_ms;
int what;
/* check if the connection has already been established */ /* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) { if(ssl_connection_complete == connssl->state) {
@ -1457,73 +1453,20 @@ mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
return CURLE_OK; return CURLE_OK;
} }
if(ssl_connect_1 == connssl->connecting_state) { *done = FALSE;
/* Find out how much more time we are allowed */ connssl->io_need = CURL_SSL_IO_NEED_NONE;
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) { if(ssl_connect_1 == connssl->connecting_state) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
retcode = mbed_connect_step1(cf, data); retcode = mbed_connect_step1(cf, data);
if(retcode) if(retcode)
return retcode; return retcode;
} }
while(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
/* check allowed time left */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
/* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking) {
*done = FALSE;
return CURLE_OK;
}
else {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
/* Run transaction, and return to the caller if it failed or if
* this connection is part of a multi handle and this loop would
* execute again. This permits the owner of a multi handle to
* abort a connection attempt before step2 has completed while
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
connssl->io_need = CURL_SSL_IO_NEED_NONE;
retcode = mbed_connect_step2(cf, data); retcode = mbed_connect_step2(cf, data);
if(retcode || if(retcode)
(nonblocking && (ssl_connect_2 == connssl->connecting_state)))
return retcode; return retcode;
}
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) { if(ssl_connect_3 == connssl->connecting_state) {
/* For tls1.3 we get notified about new sessions */ /* For tls1.3 we get notified about new sessions */
@ -1548,34 +1491,6 @@ mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
*done = TRUE; *done = TRUE;
} }
else
*done = FALSE;
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK;
}
static CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
return mbed_connect_common(cf, data, TRUE, done);
}
static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode retcode;
bool done = FALSE;
retcode = mbed_connect_common(cf, data, FALSE, &done);
if(retcode)
return retcode;
DEBUGASSERT(done);
return CURLE_OK; return CURLE_OK;
} }
@ -1682,7 +1597,6 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
mbedtls_random, /* random */ mbedtls_random, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
mbedtls_connect, /* connect */ mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
mbedtls_get_internals, /* get_internals */ mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */ mbedtls_close, /* close_one */

View File

@ -4919,85 +4919,33 @@ static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
return result; return result;
} }
static CURLcode ossl_connect_common(struct Curl_cfilter *cf, static CURLcode ossl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking,
bool *done) bool *done)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
connssl->io_need = CURL_SSL_IO_NEED_NONE;
/* check if the connection has already been established */ /* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) { if(ssl_connection_complete == connssl->state) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
} }
*done = FALSE;
connssl->io_need = CURL_SSL_IO_NEED_NONE;
if(ssl_connect_1 == connssl->connecting_state) { if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we are allowed */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time is already up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
result = ossl_connect_step1(cf, data); result = ossl_connect_step1(cf, data);
if(result) if(result)
goto out; goto out;
} }
while(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
/* check allowed time left */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
result = CURLE_OPERATION_TIMEDOUT;
goto out;
}
/* if ssl is expecting something, check if it is available. */
if(!nonblocking && connssl->io_need) {
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
result = CURLE_SSL_CONNECT_ERROR;
goto out;
}
if(0 == what) {
/* timeout */
failf(data, "SSL connection timeout");
result = CURLE_OPERATION_TIMEDOUT;
goto out;
}
/* socket is readable or writable */
}
/* Run transaction, and return to the caller if it failed or if this
* connection is done nonblocking and this loop would execute again. This
* permits the owner of a multi handle to abort a connection attempt
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
result = ossl_connect_step2(cf, data); result = ossl_connect_step2(cf, data);
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state))) if(result)
goto out; goto out;
}
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) { if(ssl_connect_3 == connssl->connecting_state) {
result = ossl_connect_step3(cf, data); result = ossl_connect_step3(cf, data);
@ -5009,38 +4957,11 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
*done = TRUE; *done = TRUE;
} }
else
*done = FALSE;
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
out: out:
return result; return result;
} }
static CURLcode ossl_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
return ossl_connect_common(cf, data, TRUE, done);
}
static CURLcode ossl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
result = ossl_connect_common(cf, data, FALSE, &done);
if(result)
return result;
DEBUGASSERT(done);
return CURLE_OK;
}
static bool ossl_data_pending(struct Curl_cfilter *cf, static bool ossl_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data) const struct Curl_easy *data)
{ {
@ -5500,7 +5421,6 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_random, /* random */ ossl_random, /* random */
ossl_cert_status_request, /* cert_status_request */ ossl_cert_status_request, /* cert_status_request */
ossl_connect, /* connect */ ossl_connect, /* connect */
ossl_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
ossl_get_internals, /* get_internals */ ossl_get_internals, /* get_internals */
ossl_close, /* close_one */ ossl_close, /* close_one */

View File

@ -779,48 +779,36 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
/* Given an established network connection, do a TLS handshake. /* Given an established network connection, do a TLS handshake.
* *
* If `blocking` is true, this function will block until the handshake is * This function will set `*done` to true once the handshake is complete.
* complete. Otherwise it will return as soon as I/O would block. * This function never reads the value of `*done*`.
*
* For the non-blocking I/O case, this function will set `*done` to true
* once the handshake is complete. This function never reads the value of
* `*done*`.
*/ */
static CURLcode static CURLcode
cr_connect_common(struct Curl_cfilter *cf, cr_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data, bool *done)
bool blocking,
bool *done)
{ {
struct ssl_connect_data *const connssl = cf->ctx; struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
struct rustls_ssl_backend_data *const backend = struct rustls_ssl_backend_data *const backend =
(struct rustls_ssl_backend_data *)connssl->backend; (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL; struct rustls_connection *rconn = NULL;
CURLcode tmperr = CURLE_OK; CURLcode tmperr = CURLE_OK;
int result; int result;
int what;
bool wants_read; bool wants_read;
bool wants_write; bool wants_write;
curl_socket_t writefd;
curl_socket_t readfd;
timediff_t timeout_ms;
timediff_t socket_check_timeout;
DEBUGASSERT(backend); DEBUGASSERT(backend);
CURL_TRC_CF(data, cf, "cr_connect_common, state=%d", connssl->state); CURL_TRC_CF(data, cf, "cr_connect, state=%d", connssl->state);
*done = FALSE; *done = FALSE;
if(!backend->conn) { if(!backend->conn) {
result = cr_init_backend(cf, data, result = cr_init_backend(cf, data,
(struct rustls_ssl_backend_data *)connssl->backend); (struct rustls_ssl_backend_data *)connssl->backend);
CURL_TRC_CF(data, cf, "cr_connect_common, init backend -> %d", result); CURL_TRC_CF(data, cf, "cr_connect, init backend -> %d", result);
if(result != CURLE_OK) { if(result != CURLE_OK) {
return result; return result;
} }
connssl->state = ssl_connection_negotiating; connssl->state = ssl_connection_negotiating;
} }
rconn = backend->conn; rconn = backend->conn;
/* Read/write data until the handshake is done or the socket would block. */ /* Read/write data until the handshake is done or the socket would block. */
@ -868,50 +856,14 @@ cr_connect_common(struct Curl_cfilter *cf,
wants_write = rustls_connection_wants_write(rconn) || wants_write = rustls_connection_wants_write(rconn) ||
backend->plain_out_buffered; backend->plain_out_buffered;
DEBUGASSERT(wants_read || wants_write); DEBUGASSERT(wants_read || wants_write);
writefd = wants_write ? sockfd : CURL_SOCKET_BAD;
readfd = wants_read ? sockfd : CURL_SOCKET_BAD;
/* check allowed time left */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "rustls: operation timed out before socket check");
return CURLE_OPERATION_TIMEDOUT;
}
socket_check_timeout = blocking ? timeout_ms : 0;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
socket_check_timeout);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
if(blocking && 0 == what) {
failf(data, "rustls: connection timeout after %" FMT_TIMEDIFF_T " ms",
socket_check_timeout);
return CURLE_OPERATION_TIMEDOUT;
}
if(0 == what) {
CURL_TRC_CF(data, cf, "Curl_socket_check: %s would block",
wants_read && wants_write ? "writing and reading" :
wants_write ? "writing" : "reading");
if(wants_write)
connssl->io_need |= CURL_SSL_IO_NEED_SEND;
if(wants_read)
connssl->io_need |= CURL_SSL_IO_NEED_RECV;
return CURLE_OK;
}
/* socket is readable or writable */
if(wants_write) { if(wants_write) {
CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls."); CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls.");
cr_send(cf, data, NULL, 0, &tmperr); cr_send(cf, data, NULL, 0, &tmperr);
if(tmperr == CURLE_AGAIN) { if(tmperr == CURLE_AGAIN) {
CURL_TRC_CF(data, cf, "writing would block"); CURL_TRC_CF(data, cf, "writing would block");
/* fall through */ connssl->io_need = CURL_SSL_IO_NEED_SEND;
return CURLE_OK;
} }
else if(tmperr != CURLE_OK) { else if(tmperr != CURLE_OK) {
return tmperr; return tmperr;
@ -923,7 +875,8 @@ cr_connect_common(struct Curl_cfilter *cf,
if(tls_recv_more(cf, data, &tmperr) < 0) { if(tls_recv_more(cf, data, &tmperr) < 0) {
if(tmperr == CURLE_AGAIN) { if(tmperr == CURLE_AGAIN) {
CURL_TRC_CF(data, cf, "reading would block"); CURL_TRC_CF(data, cf, "reading would block");
/* fall through */ connssl->io_need = CURL_SSL_IO_NEED_RECV;
return CURLE_OK;
} }
else if(tmperr == CURLE_RECV_ERROR) { else if(tmperr == CURLE_RECV_ERROR) {
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
@ -940,20 +893,6 @@ cr_connect_common(struct Curl_cfilter *cf,
DEBUGASSERT(FALSE); DEBUGASSERT(FALSE);
} }
static CURLcode
cr_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data, bool *done)
{
return cr_connect_common(cf, data, false, done);
}
static CURLcode
cr_connect_blocking(struct Curl_cfilter *cf, struct Curl_easy *data)
{
bool done; /* unused */
return cr_connect_common(cf, data, true, &done);
}
static void * static void *
cr_get_internals(struct ssl_connect_data *connssl, cr_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM) CURLINFO info UNUSED_PARAM)
@ -1083,8 +1022,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
cr_data_pending, /* data_pending */ cr_data_pending, /* data_pending */
cr_random, /* random */ cr_random, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
cr_connect_blocking, /* connect */ cr_connect, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
cr_get_internals, /* get_internals */ cr_get_internals, /* get_internals */
cr_close, /* close_one */ cr_close, /* close_one */

View File

@ -1648,16 +1648,12 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode static CURLcode schannel_connect(struct Curl_cfilter *cf,
schannel_connect_common(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking, bool *done) bool *done)
{ {
CURLcode result;
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); CURLcode result;
timediff_t timeout_ms;
int what;
/* check if the connection has already been established */ /* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) { if(ssl_connection_complete == connssl->state) {
@ -1665,73 +1661,19 @@ schannel_connect_common(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
*done = FALSE;
if(ssl_connect_1 == connssl->connecting_state) { if(ssl_connect_1 == connssl->connecting_state) {
/* check out how much more time we are allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL/TLS connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
result = schannel_connect_step1(cf, data); result = schannel_connect_step1(cf, data);
if(result) if(result)
return result; return result;
} }
while(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
/* check out how much more time we are allowed */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL/TLS connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
/* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking) {
*done = FALSE;
return CURLE_OK;
}
else {
/* timeout */
failf(data, "SSL/TLS connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
/* Run transaction, and return to the caller if it failed or if
* this connection is part of a multi handle and this loop would
* execute again. This permits the owner of a multi handle to
* abort a connection attempt before step2 has completed while
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
result = schannel_connect_step2(cf, data); result = schannel_connect_step2(cf, data);
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state))) if(result)
return result; return result;
}
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) { if(ssl_connect_3 == connssl->connecting_state) {
result = schannel_connect_step3(cf, data); result = schannel_connect_step3(cf, data);
@ -1758,11 +1700,6 @@ schannel_connect_common(struct Curl_cfilter *cf,
*done = TRUE; *done = TRUE;
} }
else
*done = FALSE;
/* reset our connection state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK; return CURLE_OK;
} }
@ -2135,7 +2072,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
connssl->connecting_state = ssl_connect_2; connssl->connecting_state = ssl_connect_2;
connssl->io_need = CURL_SSL_IO_NEED_SEND; connssl->io_need = CURL_SSL_IO_NEED_SEND;
backend->recv_renegotiating = TRUE; backend->recv_renegotiating = TRUE;
*err = schannel_connect_common(cf, data, FALSE, &done); *err = schannel_connect(cf, data, &done);
backend->recv_renegotiating = FALSE; backend->recv_renegotiating = FALSE;
if(*err) { if(*err) {
infof(data, "schannel: renegotiation failed"); infof(data, "schannel: renegotiation failed");
@ -2246,28 +2183,6 @@ cleanup:
return *err ? -1 : 0; return *err ? -1 : 0;
} }
static CURLcode schannel_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
return schannel_connect_common(cf, data, TRUE, done);
}
static CURLcode schannel_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
result = schannel_connect_common(cf, data, FALSE, &done);
if(result)
return result;
DEBUGASSERT(done);
return CURLE_OK;
}
static bool schannel_data_pending(struct Curl_cfilter *cf, static bool schannel_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data) const struct Curl_easy *data)
{ {
@ -2806,7 +2721,6 @@ const struct Curl_ssl Curl_ssl_schannel = {
schannel_random, /* random */ schannel_random, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
schannel_connect, /* connect */ schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
schannel_get_internals, /* get_internals */ schannel_get_internals, /* get_internals */
schannel_close, /* close_one */ schannel_close, /* close_one */

View File

@ -2287,15 +2287,12 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode static CURLcode sectransp_connect(struct Curl_cfilter *cf,
sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking,
bool *done) bool *done)
{ {
CURLcode result; CURLcode result;
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
int what;
/* check if the connection has already been established */ /* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) { if(ssl_connection_complete == connssl->state) {
@ -2303,73 +2300,20 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
return CURLE_OK; return CURLE_OK;
} }
*done = FALSE;
connssl->io_need = CURL_SSL_IO_NEED_NONE;
if(ssl_connect_1 == connssl->connecting_state) { if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we are allowed */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
result = sectransp_connect_step1(cf, data); result = sectransp_connect_step1(cf, data);
if(result) if(result)
return result; return result;
} }
while(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
/* check allowed time left */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
/* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking) {
*done = FALSE;
return CURLE_OK;
}
else {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
/* Run transaction, and return to the caller if it failed or if this
* connection is done nonblocking and this loop would execute again. This
* permits the owner of a multi handle to abort a connection attempt
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
result = sectransp_connect_step2(cf, data); result = sectransp_connect_step2(cf, data);
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state))) if(result)
return result; return result;
}
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) { if(ssl_connect_3 == connssl->connecting_state) {
result = sectransp_connect_step3(cf, data); result = sectransp_connect_step3(cf, data);
@ -2382,34 +2326,6 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
*done = TRUE; *done = TRUE;
} }
else
*done = FALSE;
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK;
}
static CURLcode sectransp_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
return sectransp_connect_common(cf, data, TRUE, done);
}
static CURLcode sectransp_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
result = sectransp_connect_common(cf, data, FALSE, &done);
if(result)
return result;
DEBUGASSERT(done);
return CURLE_OK; return CURLE_OK;
} }
@ -2754,7 +2670,6 @@ const struct Curl_ssl Curl_ssl_sectransp = {
sectransp_random, /* random */ sectransp_random, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
sectransp_connect, /* connect */ sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
sectransp_get_internals, /* get_internals */ sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */ sectransp_close, /* close_one */

View File

@ -485,29 +485,8 @@ static void cf_ctx_free(struct ssl_connect_data *ctx)
} }
} }
static CURLcode ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result;
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl-enabled from here on. */
connssl->state = ssl_connection_negotiating;
result = connssl->ssl_impl->connect_blocking(cf, data);
if(!result) {
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
return result;
}
static CURLcode static CURLcode
ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data, ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done)
bool *done)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
@ -515,7 +494,7 @@ ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */ /* mark this is being ssl requested from here on. */
return connssl->ssl_impl->connect_nonblocking(cf, data, done); return connssl->ssl_impl->do_connect(cf, data, done);
} }
CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex, CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex,
@ -923,20 +902,11 @@ static int multissl_init(void)
} }
static CURLcode multissl_connect(struct Curl_cfilter *cf, static CURLcode multissl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data) struct Curl_easy *data, bool *done)
{ {
if(multissl_setup(NULL)) if(multissl_setup(NULL))
return CURLE_FAILED_INIT; return CURLE_FAILED_INIT;
return Curl_ssl->connect_blocking(cf, data); return Curl_ssl->do_connect(cf, data, done);
}
static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
return Curl_ssl->connect_nonblocking(cf, data, done);
} }
static void multissl_adjust_pollset(struct Curl_cfilter *cf, static void multissl_adjust_pollset(struct Curl_cfilter *cf,
@ -995,7 +965,6 @@ static const struct Curl_ssl Curl_ssl_multi = {
NULL, /* random */ NULL, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
multissl_connect, /* connect */ multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
multissl_adjust_pollset, /* adjust_pollset */ multissl_adjust_pollset, /* adjust_pollset */
multissl_get_internals, /* get_internals */ multissl_get_internals, /* get_internals */
multissl_close, /* close_one */ multissl_close, /* close_one */
@ -1343,7 +1312,7 @@ static void ssl_cf_close(struct Curl_cfilter *cf,
static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save; struct cf_call_data save;
@ -1360,7 +1329,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
} }
if(!cf->next->connected) { if(!cf->next->connected) {
result = cf->next->cft->do_connect(cf->next, data, blocking, done); result = cf->next->cft->do_connect(cf->next, data, done);
if(result || !*done) if(result || !*done)
return result; return result;
} }
@ -1380,13 +1349,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out; goto out;
} }
if(blocking) { result = ssl_connect(cf, data, done);
result = ssl_connect(cf, data);
*done = (result == CURLE_OK);
}
else {
result = ssl_connect_nonblocking(cf, data, done);
}
if(!result && *done) { if(!result && *done) {
cf->connected = TRUE; cf->connected = TRUE;

View File

@ -157,10 +157,7 @@ struct Curl_ssl {
size_t length); size_t length);
bool (*cert_status_request)(void); bool (*cert_status_request)(void);
CURLcode (*connect_blocking)(struct Curl_cfilter *cf, CURLcode (*do_connect)(struct Curl_cfilter *cf, struct Curl_easy *data,
struct Curl_easy *data);
CURLcode (*connect_nonblocking)(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done); bool *done);
/* During handshake/shutdown, adjust the pollset to include the socket /* During handshake/shutdown, adjust the pollset to include the socket

View File

@ -1842,15 +1842,12 @@ static bool wolfssl_data_pending(struct Curl_cfilter *cf,
return FALSE; return FALSE;
} }
static CURLcode static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
wolfssl_connect_common(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool nonblocking,
bool *done) bool *done)
{ {
CURLcode result; CURLcode result;
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
/* check if the connection has already been established */ /* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) { if(ssl_connection_complete == connssl->state) {
@ -1858,70 +1855,20 @@ wolfssl_connect_common(struct Curl_cfilter *cf,
return CURLE_OK; return CURLE_OK;
} }
*done = FALSE;
connssl->io_need = CURL_SSL_IO_NEED_NONE;
if(ssl_connect_1 == connssl->connecting_state) { if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we are allowed */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
result = wolfssl_connect_step1(cf, data); result = wolfssl_connect_step1(cf, data);
if(result) if(result)
return result; return result;
} }
while(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
/* check allowed time left */
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
/* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
sockfd : CURL_SOCKET_BAD;
curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
sockfd : CURL_SOCKET_BAD;
int what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking) {
*done = FALSE;
return CURLE_OK;
}
else {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
/* Run transaction, and return to the caller if it failed or if
* this connection is part of a multi handle and this loop would
* execute again. This permits the owner of a multi handle to
* abort a connection attempt before step2 has completed while
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
result = wolfssl_connect_step2(cf, data); result = wolfssl_connect_step2(cf, data);
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state))) if(result)
return result; return result;
} /* repeat step2 until all transactions are done. */ }
if(ssl_connect_3 == connssl->connecting_state) { if(ssl_connect_3 == connssl->connecting_state) {
/* In other backends, this is where we verify the certificate, but /* In other backends, this is where we verify the certificate, but
@ -1933,39 +1880,11 @@ wolfssl_connect_common(struct Curl_cfilter *cf,
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
*done = TRUE; *done = TRUE;
} }
else
*done = FALSE;
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK; return CURLE_OK;
} }
static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
return wolfssl_connect_common(cf, data, TRUE, done);
}
static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
CURLcode result;
bool done = FALSE;
result = wolfssl_connect_common(cf, data, FALSE, &done);
if(result)
return result;
DEBUGASSERT(done);
return CURLE_OK;
}
static CURLcode wolfssl_random(struct Curl_easy *data, static CURLcode wolfssl_random(struct Curl_easy *data,
unsigned char *entropy, size_t length) unsigned char *entropy, size_t length)
{ {
@ -2037,7 +1956,6 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
wolfssl_random, /* random */ wolfssl_random, /* random */
NULL, /* cert_status_request */ NULL, /* cert_status_request */
wolfssl_connect, /* connect */ wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */ Curl_ssl_adjust_pollset, /* adjust_pollset */
wolfssl_get_internals, /* get_internals */ wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */ wolfssl_close, /* close_one */

View File

@ -134,13 +134,12 @@ static void cf_test_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
static CURLcode cf_test_connect(struct Curl_cfilter *cf, static CURLcode cf_test_connect(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
bool blocking, bool *done) bool *done)
{ {
struct cf_test_ctx *ctx = cf->ctx; struct cf_test_ctx *ctx = cf->ctx;
timediff_t duration_ms; timediff_t duration_ms;
(void)data; (void)data;
(void)blocking;
*done = FALSE; *done = FALSE;
duration_ms = Curl_timediff(Curl_now(), ctx->started); duration_ms = Curl_timediff(Curl_now(), ctx->started);
if(duration_ms >= ctx->fail_delay_ms) { if(duration_ms >= ctx->fail_delay_ms) {