mirror of
https://github.com/curl/curl.git
synced 2025-04-12 16:20:35 +08:00
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:
parent
654f8cb5f3
commit
a1850ad7de
@ -598,7 +598,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
infof(data, "Connect me again please");
|
||||
Curl_conn_cf_close(cf, data);
|
||||
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;
|
||||
}
|
||||
else {
|
||||
@ -638,7 +638,7 @@ out:
|
||||
|
||||
static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
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");
|
||||
result = cf->next->cft->do_connect(cf->next, data, blocking, done);
|
||||
result = cf->next->cft->do_connect(cf->next, data, done);
|
||||
if(result || !*done)
|
||||
return result;
|
||||
|
||||
|
@ -1090,7 +1090,7 @@ out:
|
||||
|
||||
static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_h2_proxy_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -1105,7 +1105,7 @@ static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
|
||||
|
||||
/* Connect the lower filters first */
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
|
||||
|
||||
static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_haproxy_ctx *ctx = cf->ctx;
|
||||
CURLcode result;
|
||||
@ -117,7 +117,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
|
||||
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)
|
||||
return result;
|
||||
|
||||
|
@ -175,7 +175,7 @@ static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
|
||||
struct Curl_cfilter *save = cf->next;
|
||||
|
||||
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 */
|
||||
cf->next = save;
|
||||
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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_hc_ctx *ctx = cf->ctx;
|
||||
struct curltime now;
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t i, failed_ballers;
|
||||
|
||||
(void)blocking;
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
|
@ -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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_COULDNT_CONNECT;
|
||||
@ -1316,9 +1316,6 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if(blocking)
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
|
||||
*done = FALSE; /* a negative world view is best */
|
||||
if(ctx->sock == CURL_SOCKET_BAD) {
|
||||
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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_COULDNT_CONNECT;
|
||||
|
||||
(void)blocking;
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
#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 */
|
||||
(void)data;
|
||||
(void)blocking;
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
|
@ -368,10 +368,10 @@ bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
|
||||
|
||||
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
if(cf)
|
||||
return cf->cft->do_connect(cf, data, blocking, done);
|
||||
return cf->cft->do_connect(cf, data, done);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
@ -405,6 +405,9 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
|
||||
bool blocking,
|
||||
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;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
@ -419,7 +422,11 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
*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)) {
|
||||
DEBUGF(infof(data, "Curl_conn_connect(index=%d), flush", sockindex));
|
||||
result = Curl_conn_flush(data, sockindex);
|
||||
@ -427,7 +434,9 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
|
||||
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) {
|
||||
/* Now that the complete filter chain is connected, let all filters
|
||||
* 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);
|
||||
data->conn->keepalive = Curl_now();
|
||||
Curl_verboseconnect(data, data->conn, sockindex);
|
||||
goto out;
|
||||
}
|
||||
else if(result) {
|
||||
CURL_TRC_CF(data, cf, "Curl_conn_connect(), filter returned %d",
|
||||
result);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ typedef CURLcode Curl_cft_shutdown(struct Curl_cfilter *cf,
|
||||
|
||||
typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done);
|
||||
bool *done);
|
||||
|
||||
/* Return the hostname and port the connection goes to.
|
||||
* 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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done);
|
||||
bool *done);
|
||||
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,
|
||||
const void *buf, size_t len, bool eos,
|
||||
|
@ -593,7 +593,7 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
|
||||
*connected = baller->connected;
|
||||
if(!baller->result && !*connected) {
|
||||
/* 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(*connected) {
|
||||
@ -948,7 +948,7 @@ static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
|
||||
|
||||
static CURLcode cf_he_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_he_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -958,7 +958,6 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
(void)blocking;
|
||||
DEBUGASSERT(ctx);
|
||||
*done = FALSE;
|
||||
|
||||
@ -1263,7 +1262,7 @@ struct cf_setup_ctx {
|
||||
|
||||
static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_setup_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -1276,7 +1275,7 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
|
||||
/* connect current sub-chain */
|
||||
connect_sub_chain:
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
|
@ -3603,7 +3603,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
||||
if(ftpc->wait_data_conn) {
|
||||
bool serv_conned;
|
||||
|
||||
result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &serv_conned);
|
||||
result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &serv_conned);
|
||||
if(result)
|
||||
return result; /* Failed to accept data connection */
|
||||
|
||||
|
10
lib/http2.c
10
lib/http2.c
@ -2441,7 +2441,7 @@ static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
|
||||
|
||||
static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_h2_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -2455,7 +2455,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
|
||||
|
||||
/* Connect the lower filters first */
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
@ -2827,7 +2827,7 @@ CURLcode Curl_http2_switch(struct Curl_easy *data)
|
||||
|
||||
if(cf->next) {
|
||||
bool done;
|
||||
return Curl_conn_cf_connect(cf, data, FALSE, &done);
|
||||
return Curl_conn_cf_connect(cf, data, &done);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -2849,7 +2849,7 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
|
||||
if(cf_h2->next) {
|
||||
bool done;
|
||||
return Curl_conn_cf_connect(cf_h2, data, FALSE, &done);
|
||||
return Curl_conn_cf_connect(cf_h2, data, &done);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -2900,7 +2900,7 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
|
||||
|
||||
if(cf->next) {
|
||||
bool done;
|
||||
return Curl_conn_cf_connect(cf, data, FALSE, &done);
|
||||
return Curl_conn_cf_connect(cf, data, &done);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ out:
|
||||
|
||||
static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_proxy_ctx *ctx = cf->ctx;
|
||||
CURLcode result;
|
||||
@ -319,7 +319,7 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
|
||||
CURL_TRC_CF(data, cf, "connect");
|
||||
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)
|
||||
return result;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
DEBUGASSERT(cpfds);
|
||||
|
@ -122,6 +122,8 @@ void Curl_pollfds_init(struct curl_pollfds *cpfds,
|
||||
struct pollfd *static_pfds,
|
||||
unsigned int static_count);
|
||||
|
||||
void Curl_pollfds_reset(struct curl_pollfds *cpfds);
|
||||
|
||||
void Curl_pollfds_cleanup(struct curl_pollfds *cpfds);
|
||||
|
||||
CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds,
|
||||
|
@ -1128,7 +1128,7 @@ static void socks_proxy_cf_free(struct Curl_cfilter *cf)
|
||||
*/
|
||||
static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn = cf->conn;
|
||||
@ -1140,7 +1140,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
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)
|
||||
return result;
|
||||
|
||||
|
@ -877,13 +877,12 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
||||
|
||||
static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_msh3_ctx *ctx = cf->ctx;
|
||||
struct cf_call_data save;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
(void)blocking;
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
|
@ -2453,7 +2453,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
||||
|
||||
static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_ngtcp2_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -2468,7 +2468,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
|
||||
|
||||
/* Connect the UDP filter first */
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
|
@ -1718,7 +1718,7 @@ out:
|
||||
|
||||
static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -1733,7 +1733,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
|
||||
|
||||
/* Connect the UDP filter first */
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
|
@ -1378,7 +1378,7 @@ static CURLcode cf_quiche_verify_peer(struct Curl_cfilter *cf,
|
||||
|
||||
static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_quiche_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -1390,7 +1390,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
|
||||
|
||||
/* Connect the UDP filter first */
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
|
@ -911,18 +911,14 @@ static ssize_t bearssl_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
return applen;
|
||||
}
|
||||
|
||||
static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool nonblocking,
|
||||
bool *done)
|
||||
static CURLcode bearssl_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode ret;
|
||||
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 */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
CURL_TRC_CF(data, cf, "connect_common, connected");
|
||||
@ -930,61 +926,18 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
*done = FALSE;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_NONE;
|
||||
|
||||
if(ssl_connect_1 == connssl->connecting_state) {
|
||||
ret = bearssl_connect_step1(cf, data);
|
||||
if(ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
while(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;
|
||||
if(ssl_connect_2 == connssl->connecting_state) {
|
||||
ret = bearssl_connect_step2(cf, data);
|
||||
if(ret || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
|
||||
if(ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -998,11 +951,6 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
|
||||
connssl->state = ssl_connection_complete;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
*done = FALSE;
|
||||
|
||||
/* Reset our connect state machine */
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -1044,28 +992,6 @@ static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
|
||||
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,
|
||||
CURLINFO info UNUSED_PARAM)
|
||||
{
|
||||
@ -1161,7 +1087,6 @@ const struct Curl_ssl Curl_ssl_bearssl = {
|
||||
bearssl_random, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
bearssl_connect, /* connect */
|
||||
bearssl_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
bearssl_get_internals, /* get_internals */
|
||||
bearssl_close, /* close_one */
|
||||
|
203
lib/vtls/gtls.c
203
lib/vtls/gtls.c
@ -238,115 +238,68 @@ static void unload_file(gnutls_datum_t data)
|
||||
|
||||
/* this function does a SSL/TLS (re-)handshake */
|
||||
static CURLcode handshake(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool duringconnect,
|
||||
bool nonblocking)
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct gtls_ssl_backend_data *backend =
|
||||
(struct gtls_ssl_backend_data *)connssl->backend;
|
||||
gnutls_session_t session;
|
||||
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
|
||||
int rc;
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
session = backend->gtls.session;
|
||||
connssl->connecting_state = ssl_connect_2;
|
||||
|
||||
for(;;) {
|
||||
timediff_t timeout_ms;
|
||||
int rc;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_NONE;
|
||||
backend->gtls.io_result = CURLE_OK;
|
||||
rc = gnutls_handshake(session);
|
||||
|
||||
/* 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;
|
||||
backend->gtls.io_result = CURLE_OK;
|
||||
rc = gnutls_handshake(session);
|
||||
|
||||
if(!backend->gtls.shared_creds->trust_setup) {
|
||||
/* After having send off the ClientHello, we prepare the trust
|
||||
* store to verify the coming certificate from the server */
|
||||
CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
|
||||
connssl->io_need =
|
||||
gnutls_record_get_direction(session) ?
|
||||
CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
|
||||
continue;
|
||||
}
|
||||
else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
|
||||
const char *strerr = NULL;
|
||||
|
||||
if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
|
||||
gnutls_alert_description_t alert = gnutls_alert_get(session);
|
||||
strerr = gnutls_alert_get_name(alert);
|
||||
}
|
||||
|
||||
if(!strerr)
|
||||
strerr = gnutls_strerror(rc);
|
||||
|
||||
infof(data, "gnutls_handshake() warning: %s", strerr);
|
||||
continue;
|
||||
}
|
||||
else if((rc < 0) && backend->gtls.io_result) {
|
||||
return backend->gtls.io_result;
|
||||
}
|
||||
else if(rc < 0) {
|
||||
const char *strerr = NULL;
|
||||
|
||||
if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
|
||||
gnutls_alert_description_t alert = gnutls_alert_get(session);
|
||||
strerr = gnutls_alert_get_name(alert);
|
||||
}
|
||||
|
||||
if(!strerr)
|
||||
strerr = gnutls_strerror(rc);
|
||||
|
||||
failf(data, "GnuTLS, handshake failed: %s", strerr);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
/* Reset our connect state machine */
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
return CURLE_OK;
|
||||
if(!backend->gtls.shared_creds->trust_setup) {
|
||||
/* After having send off the ClientHello, we prepare the trust
|
||||
* store to verify the coming certificate from the server */
|
||||
CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
|
||||
connssl->io_need =
|
||||
gnutls_record_get_direction(session) ?
|
||||
CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
|
||||
const char *strerr = NULL;
|
||||
|
||||
if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
|
||||
gnutls_alert_description_t alert = gnutls_alert_get(session);
|
||||
strerr = gnutls_alert_get_name(alert);
|
||||
}
|
||||
|
||||
if(!strerr)
|
||||
strerr = gnutls_strerror(rc);
|
||||
|
||||
infof(data, "gnutls_handshake() warning: %s", strerr);
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
else if((rc < 0) && backend->gtls.io_result) {
|
||||
return backend->gtls.io_result;
|
||||
}
|
||||
else if(rc < 0) {
|
||||
const char *strerr = NULL;
|
||||
|
||||
if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
|
||||
gnutls_alert_description_t alert = gnutls_alert_get(session);
|
||||
strerr = gnutls_alert_get_name(alert);
|
||||
}
|
||||
|
||||
if(!strerr)
|
||||
strerr = gnutls_strerror(rc);
|
||||
|
||||
failf(data, "GnuTLS, handshake failed: %s", strerr);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||
|
||||
if(connssl->state == ssl_connection_complete)
|
||||
/* to make us tolerant against being called more than once for the
|
||||
@ -1901,17 +1853,22 @@ out:
|
||||
'ssl_connect_2' (doing handshake with the server), and
|
||||
'ssl_connect_3' (verifying and getting stats).
|
||||
*/
|
||||
static CURLcode
|
||||
gtls_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool nonblocking,
|
||||
bool *done) {
|
||||
static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done) {
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct gtls_ssl_backend_data *backend =
|
||||
(struct gtls_ssl_backend_data *)connssl->backend;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
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 */
|
||||
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) ||
|
||||
(connssl->earlydata_state == ssl_earlydata_sent));
|
||||
|
||||
result = handshake(cf, data, TRUE, nonblocking);
|
||||
result = handshake(cf, data);
|
||||
if(result)
|
||||
goto out;
|
||||
connssl->connecting_state = ssl_connect_3;
|
||||
@ -1951,7 +1908,6 @@ gtls_connect_common(struct Curl_cfilter *cf,
|
||||
goto out;
|
||||
|
||||
connssl->state = ssl_connection_complete;
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
|
||||
rc = gnutls_alpn_get_selected_protocol(backend->gtls.session, &proto);
|
||||
if(rc) { /* No ALPN from server */
|
||||
@ -1982,6 +1938,12 @@ gtls_connect_common(struct Curl_cfilter *cf,
|
||||
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:
|
||||
@ -1994,9 +1956,9 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
static CURLcode gtls_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
if(connssl->state == ssl_connection_deferred) {
|
||||
@ -2004,22 +1966,7 @@ static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
return gtls_connect_common(cf, data, TRUE, 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;
|
||||
return gtls_connect_common(cf, data, done);
|
||||
}
|
||||
|
||||
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 gtls_connect_common(cf, data, TRUE, done);
|
||||
return gtls_connect_common(cf, data, done);
|
||||
}
|
||||
|
||||
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) {
|
||||
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the
|
||||
proper way" takes a whole lot of work. */
|
||||
CURLcode result = handshake(cf, data, FALSE, FALSE);
|
||||
CURLcode result = handshake(cf, data);
|
||||
if(result)
|
||||
/* handshake() writes error message on its own */
|
||||
*curlcode = result;
|
||||
else
|
||||
*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_cert_status_request, /* cert_status_request */
|
||||
gtls_connect, /* connect */
|
||||
gtls_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
gtls_get_internals, /* get_internals */
|
||||
gtls_close, /* close_one */
|
||||
|
@ -1440,16 +1440,12 @@ static CURLcode mbedtls_random(struct Curl_easy *data,
|
||||
#endif
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
bool nonblocking,
|
||||
bool *done)
|
||||
static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode retcode;
|
||||
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 */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
@ -1457,73 +1453,20 @@ mbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if(ssl_connect_1 == connssl->connecting_state) {
|
||||
/* Find out how much more time we are allowed */
|
||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
*done = FALSE;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_NONE;
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* no need to continue if time already is up */
|
||||
failf(data, "SSL connection timeout");
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
if(ssl_connect_1 == connssl->connecting_state) {
|
||||
retcode = mbed_connect_step1(cf, data);
|
||||
if(retcode)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
while(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;
|
||||
if(ssl_connect_2 == connssl->connecting_state) {
|
||||
retcode = mbed_connect_step2(cf, data);
|
||||
if(retcode ||
|
||||
(nonblocking && (ssl_connect_2 == connssl->connecting_state)))
|
||||
if(retcode)
|
||||
return retcode;
|
||||
|
||||
} /* repeat step2 until all transactions are done. */
|
||||
}
|
||||
|
||||
if(ssl_connect_3 == connssl->connecting_state) {
|
||||
/* 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;
|
||||
*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;
|
||||
}
|
||||
@ -1682,7 +1597,6 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
|
||||
mbedtls_random, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
mbedtls_connect, /* connect */
|
||||
mbedtls_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
mbedtls_get_internals, /* get_internals */
|
||||
mbedtls_close, /* close_one */
|
||||
|
@ -4919,85 +4919,33 @@ static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool nonblocking,
|
||||
bool *done)
|
||||
static CURLcode ossl_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
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 */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
*done = FALSE;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_NONE;
|
||||
|
||||
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);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
while(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.
|
||||
*/
|
||||
if(ssl_connect_2 == connssl->connecting_state) {
|
||||
result = ossl_connect_step2(cf, data);
|
||||
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
} /* repeat step2 until all transactions are done. */
|
||||
}
|
||||
|
||||
if(ssl_connect_3 == connssl->connecting_state) {
|
||||
result = ossl_connect_step3(cf, data);
|
||||
@ -5009,38 +4957,11 @@ static CURLcode ossl_connect_common(struct Curl_cfilter *cf,
|
||||
connssl->state = ssl_connection_complete;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
*done = FALSE;
|
||||
|
||||
/* Reset our connect state machine */
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
|
||||
out:
|
||||
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,
|
||||
const struct Curl_easy *data)
|
||||
{
|
||||
@ -5500,7 +5421,6 @@ const struct Curl_ssl Curl_ssl_openssl = {
|
||||
ossl_random, /* random */
|
||||
ossl_cert_status_request, /* cert_status_request */
|
||||
ossl_connect, /* connect */
|
||||
ossl_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
ossl_get_internals, /* get_internals */
|
||||
ossl_close, /* close_one */
|
||||
|
@ -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.
|
||||
*
|
||||
* If `blocking` is true, this function will block until the handshake is
|
||||
* complete. Otherwise it will return as soon as I/O would block.
|
||||
*
|
||||
* 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*`.
|
||||
* This function will set `*done` to true once the handshake is complete.
|
||||
* This function never reads the value of `*done*`.
|
||||
*/
|
||||
static CURLcode
|
||||
cr_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking,
|
||||
bool *done)
|
||||
cr_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data, bool *done)
|
||||
{
|
||||
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 *)connssl->backend;
|
||||
struct rustls_connection *rconn = NULL;
|
||||
CURLcode tmperr = CURLE_OK;
|
||||
int result;
|
||||
int what;
|
||||
bool wants_read;
|
||||
bool wants_write;
|
||||
curl_socket_t writefd;
|
||||
curl_socket_t readfd;
|
||||
timediff_t timeout_ms;
|
||||
timediff_t socket_check_timeout;
|
||||
|
||||
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;
|
||||
|
||||
if(!backend->conn) {
|
||||
result = cr_init_backend(cf, data,
|
||||
(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) {
|
||||
return result;
|
||||
}
|
||||
connssl->state = ssl_connection_negotiating;
|
||||
}
|
||||
|
||||
rconn = backend->conn;
|
||||
|
||||
/* 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) ||
|
||||
backend->plain_out_buffered;
|
||||
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) {
|
||||
CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls.");
|
||||
cr_send(cf, data, NULL, 0, &tmperr);
|
||||
if(tmperr == CURLE_AGAIN) {
|
||||
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) {
|
||||
return tmperr;
|
||||
@ -923,7 +875,8 @@ cr_connect_common(struct Curl_cfilter *cf,
|
||||
if(tls_recv_more(cf, data, &tmperr) < 0) {
|
||||
if(tmperr == CURLE_AGAIN) {
|
||||
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) {
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -940,20 +893,6 @@ cr_connect_common(struct Curl_cfilter *cf,
|
||||
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 *
|
||||
cr_get_internals(struct ssl_connect_data *connssl,
|
||||
CURLINFO info UNUSED_PARAM)
|
||||
@ -1083,8 +1022,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
|
||||
cr_data_pending, /* data_pending */
|
||||
cr_random, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
cr_connect_blocking, /* connect */
|
||||
cr_connect_nonblocking, /* connect_nonblocking */
|
||||
cr_connect, /* connect */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
cr_get_internals, /* get_internals */
|
||||
cr_close, /* close_one */
|
||||
|
@ -1648,16 +1648,12 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
schannel_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool nonblocking, bool *done)
|
||||
static CURLcode schannel_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
|
||||
timediff_t timeout_ms;
|
||||
int what;
|
||||
CURLcode result;
|
||||
|
||||
/* check if the connection has already been established */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
@ -1665,73 +1661,19 @@ schannel_connect_common(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
*done = FALSE;
|
||||
|
||||
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);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
while(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.
|
||||
*/
|
||||
if(ssl_connect_2 == connssl->connecting_state) {
|
||||
result = schannel_connect_step2(cf, data);
|
||||
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
} /* repeat step2 until all transactions are done. */
|
||||
}
|
||||
|
||||
if(ssl_connect_3 == connssl->connecting_state) {
|
||||
result = schannel_connect_step3(cf, data);
|
||||
@ -1758,11 +1700,6 @@ schannel_connect_common(struct Curl_cfilter *cf,
|
||||
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
*done = FALSE;
|
||||
|
||||
/* reset our connection state machine */
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -2135,7 +2072,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
connssl->connecting_state = ssl_connect_2;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_SEND;
|
||||
backend->recv_renegotiating = TRUE;
|
||||
*err = schannel_connect_common(cf, data, FALSE, &done);
|
||||
*err = schannel_connect(cf, data, &done);
|
||||
backend->recv_renegotiating = FALSE;
|
||||
if(*err) {
|
||||
infof(data, "schannel: renegotiation failed");
|
||||
@ -2246,28 +2183,6 @@ cleanup:
|
||||
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,
|
||||
const struct Curl_easy *data)
|
||||
{
|
||||
@ -2806,7 +2721,6 @@ const struct Curl_ssl Curl_ssl_schannel = {
|
||||
schannel_random, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
schannel_connect, /* connect */
|
||||
schannel_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
schannel_get_internals, /* get_internals */
|
||||
schannel_close, /* close_one */
|
||||
|
@ -2287,15 +2287,12 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
bool nonblocking,
|
||||
bool *done)
|
||||
static CURLcode sectransp_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
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 */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
@ -2303,73 +2300,20 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
*done = FALSE;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_NONE;
|
||||
|
||||
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);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
while(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.
|
||||
*/
|
||||
if(ssl_connect_2 == connssl->connecting_state) {
|
||||
result = sectransp_connect_step2(cf, data);
|
||||
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
} /* repeat step2 until all transactions are done. */
|
||||
|
||||
}
|
||||
|
||||
if(ssl_connect_3 == connssl->connecting_state) {
|
||||
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;
|
||||
*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;
|
||||
}
|
||||
@ -2754,7 +2670,6 @@ const struct Curl_ssl Curl_ssl_sectransp = {
|
||||
sectransp_random, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
sectransp_connect, /* connect */
|
||||
sectransp_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
sectransp_get_internals, /* get_internals */
|
||||
sectransp_close, /* close_one */
|
||||
|
@ -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
|
||||
ssl_connect_nonblocking(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
bool *done)
|
||||
ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done)
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
@ -923,20 +902,11 @@ static int multissl_init(void)
|
||||
}
|
||||
|
||||
static CURLcode multissl_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
struct Curl_easy *data, bool *done)
|
||||
{
|
||||
if(multissl_setup(NULL))
|
||||
return CURLE_FAILED_INIT;
|
||||
return Curl_ssl->connect_blocking(cf, data);
|
||||
}
|
||||
|
||||
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);
|
||||
return Curl_ssl->do_connect(cf, data, done);
|
||||
}
|
||||
|
||||
static void multissl_adjust_pollset(struct Curl_cfilter *cf,
|
||||
@ -995,7 +965,6 @@ static const struct Curl_ssl Curl_ssl_multi = {
|
||||
NULL, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
multissl_connect, /* connect */
|
||||
multissl_connect_nonblocking, /* connect_nonblocking */
|
||||
multissl_adjust_pollset, /* adjust_pollset */
|
||||
multissl_get_internals, /* get_internals */
|
||||
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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct cf_call_data save;
|
||||
@ -1360,7 +1329,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
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)
|
||||
return result;
|
||||
}
|
||||
@ -1380,13 +1349,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(blocking) {
|
||||
result = ssl_connect(cf, data);
|
||||
*done = (result == CURLE_OK);
|
||||
}
|
||||
else {
|
||||
result = ssl_connect_nonblocking(cf, data, done);
|
||||
}
|
||||
result = ssl_connect(cf, data, done);
|
||||
|
||||
if(!result && *done) {
|
||||
cf->connected = TRUE;
|
||||
|
@ -157,11 +157,8 @@ struct Curl_ssl {
|
||||
size_t length);
|
||||
bool (*cert_status_request)(void);
|
||||
|
||||
CURLcode (*connect_blocking)(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
CURLcode (*connect_nonblocking)(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done);
|
||||
CURLcode (*do_connect)(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
bool *done);
|
||||
|
||||
/* During handshake/shutdown, adjust the pollset to include the socket
|
||||
* for POLLOUT or POLLIN as needed. Mandatory. */
|
||||
|
@ -1842,15 +1842,12 @@ static bool wolfssl_data_pending(struct Curl_cfilter *cf,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
wolfssl_connect_common(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool nonblocking,
|
||||
bool *done)
|
||||
static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
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 */
|
||||
if(ssl_connection_complete == connssl->state) {
|
||||
@ -1858,70 +1855,20 @@ wolfssl_connect_common(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
*done = FALSE;
|
||||
connssl->io_need = CURL_SSL_IO_NEED_NONE;
|
||||
|
||||
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);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
while(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.
|
||||
*/
|
||||
if(ssl_connect_2 == connssl->connecting_state) {
|
||||
result = wolfssl_connect_step2(cf, data);
|
||||
if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
|
||||
if(result)
|
||||
return result;
|
||||
} /* repeat step2 until all transactions are done. */
|
||||
}
|
||||
|
||||
if(ssl_connect_3 == connssl->connecting_state) {
|
||||
/* 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;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
*done = FALSE;
|
||||
|
||||
/* Reset our connect state machine */
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
|
||||
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,
|
||||
unsigned char *entropy, size_t length)
|
||||
{
|
||||
@ -2037,7 +1956,6 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
|
||||
wolfssl_random, /* random */
|
||||
NULL, /* cert_status_request */
|
||||
wolfssl_connect, /* connect */
|
||||
wolfssl_connect_nonblocking, /* connect_nonblocking */
|
||||
Curl_ssl_adjust_pollset, /* adjust_pollset */
|
||||
wolfssl_get_internals, /* get_internals */
|
||||
wolfssl_close, /* close_one */
|
||||
|
@ -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,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
bool *done)
|
||||
{
|
||||
struct cf_test_ctx *ctx = cf->ctx;
|
||||
timediff_t duration_ms;
|
||||
|
||||
(void)data;
|
||||
(void)blocking;
|
||||
*done = FALSE;
|
||||
duration_ms = Curl_timediff(Curl_now(), ctx->started);
|
||||
if(duration_ms >= ctx->fail_delay_ms) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user