diff options
author | Daniel Stenberg <daniel@haxx.se> | 2021-01-08 17:58:15 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-01-17 23:56:09 +0100 |
commit | 215db086e09665ee7af9b646ad6c4d6e281001ac (patch) | |
tree | 50c74f8456df87e86de6d72e90190a3563083a1a /lib/url.c | |
parent | 0d26ab9ed3ac29da2a383d313e93df3e9f5295a2 (diff) | |
download | curl-215db086e09665ee7af9b646ad6c4d6e281001ac.tar.gz |
lib: pass in 'struct Curl_easy *' to most functions
... in most cases instead of 'struct connectdata *' but in some cases in
addition to.
- We mostly operate on transfers and not connections.
- We need the transfer handle to log, store data and more. Everything in
libcurl is driven by a transfer (the CURL * in the public API).
- This work clarifies and separates the transfers from the connections
better.
- We should avoid "conn->data". Since individual connections can be used
by many transfers when multiplexing, making sure that conn->data
points to the current and correct transfer at all times is difficult
and has been notoriously error-prone over the years. The goal is to
ultimately remove the conn->data pointer for this reason.
Closes #6425
Diffstat (limited to 'lib/url.c')
-rw-r--r-- | lib/url.c | 97 |
1 files changed, 59 insertions, 38 deletions
@@ -364,6 +364,9 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_expire_clear(data); /* shut off timers */ + /* Detach connection if any is left. This should not be normal, but can be + the case for example with CONNECT_ONLY + recv/send (test 556) */ + Curl_detach_connnection(data); m = data->multi; if(m) /* This handle is still part of a multi handle, take care of this first @@ -709,11 +712,11 @@ static void conn_reset_all_postponed_data(struct connectdata *conn) #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ -static void conn_shutdown(struct connectdata *conn) +static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn) { DEBUGASSERT(conn); - infof(conn->data, "Closing connection %ld\n", conn->connection_id); - DEBUGASSERT(conn->data); + DEBUGASSERT(data); + infof(data, "Closing connection %ld\n", conn->connection_id); /* possible left-overs from the async name resolvers */ Curl_resolver_cancel(conn); @@ -725,13 +728,13 @@ static void conn_shutdown(struct connectdata *conn) /* close possibly still open sockets */ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) - Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]); if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) - Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); + Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]); if(CURL_SOCKET_BAD != conn->tempsock[0]) - Curl_closesocket(conn, conn->tempsock[0]); + Curl_closesocket(data, conn, conn->tempsock[0]); if(CURL_SOCKET_BAD != conn->tempsock[1]) - Curl_closesocket(conn, conn->tempsock[1]); + Curl_closesocket(data, conn, conn->tempsock[1]); } static void conn_free(struct connectdata *conn) @@ -834,11 +837,18 @@ CURLcode Curl_disconnect(struct Curl_easy *data, /* treat the connection as dead in CONNECT_ONLY situations */ dead_connection = TRUE; - if(conn->handler->disconnect) + if(conn->handler->disconnect) { + /* During disconnect, the connection and the transfer is already + disassociated, but the SSH backends (and more?) still need the + transfer's connection pointer to identify the used connection */ + data->conn = conn; + /* This is set if protocol-specific cleanups should be made */ - conn->handler->disconnect(conn, dead_connection); + conn->handler->disconnect(data, conn, dead_connection); + data->conn = NULL; /* forget it again */ + } - conn_shutdown(conn); + conn_shutdown(data, conn); conn_free(conn); return CURLE_OK; } @@ -961,23 +971,29 @@ static bool conn_maxage(struct Curl_easy *data, static bool extract_if_dead(struct connectdata *conn, struct Curl_easy *data) { - if(!CONN_INUSE(conn) && !conn->data) { + if(!CONN_INUSE(conn)) { /* The check for a dead socket makes sense only if the connection isn't in use */ bool dead; struct curltime now = Curl_now(); if(conn_maxage(data, conn, now)) { + /* avoid check if already too old */ dead = TRUE; } else if(conn->handler->connection_check) { /* The protocol has a special method for checking the state of the connection. Use it to check if the connection is dead. */ unsigned int state; - struct Curl_easy *olddata = conn->data; - conn->data = data; /* use this transfer for now */ - state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); - conn->data = olddata; + + /* briefly attach the connection to this transfer for the purpose of + checking it */ + Curl_attach_connnection(data, conn); + conn->data = data; /* find the way back if necessary */ + state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD); dead = (state & CONNRESULT_DEAD); + /* detach the connection again */ + Curl_detach_connnection(data); + conn->data = NULL; /* clear it again */ } else { /* Use the general method for determining the death of a connection */ @@ -1002,10 +1018,11 @@ struct prunedead { * Wrapper to use extract_if_dead() function in Curl_conncache_foreach() * */ -static int call_extract_if_dead(struct connectdata *conn, void *param) +static int call_extract_if_dead(struct Curl_easy *data, + struct connectdata *conn, void *param) { struct prunedead *p = (struct prunedead *)param; - if(extract_if_dead(conn, p->data)) { + if(extract_if_dead(conn, data)) { /* stop the iteration here, pass back the connection that was extracted */ p->extracted = conn; return 1; @@ -1015,14 +1032,16 @@ static int call_extract_if_dead(struct connectdata *conn, void *param) /* * This function scans the connection cache for half-open/dead connections, - * closes and removes them. - * The cleanup is done at most once per second. + * closes and removes them. The cleanup is done at most once per second. + * + * When called, this transfer has no connection attached. */ static void prune_dead_connections(struct Curl_easy *data) { struct curltime now = Curl_now(); timediff_t elapsed; + DEBUGASSERT(!data->conn); /* no connection */ CONNCACHE_LOCK(data); elapsed = Curl_timediff(now, data->state.conn_cache->last_cleanup); @@ -1463,9 +1482,10 @@ ConnectionExists(struct Curl_easy *data, * verboseconnect() displays verbose information after a connect */ #ifndef CURL_DISABLE_VERBOSE_STRINGS -void Curl_verboseconnect(struct connectdata *conn) +void Curl_verboseconnect(struct Curl_easy *data, + struct connectdata *conn) { - if(conn->data->set.verbose) + if(data->set.verbose) infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", #ifndef CURL_DISABLE_PROXY conn->bits.socksproxy ? conn->socks_proxy.host.dispname : @@ -2084,7 +2104,8 @@ static CURLcode setup_range(struct Curl_easy *data) * * This MUST get called after proxy magic has been figured out. */ -static CURLcode setup_connection_internals(struct connectdata *conn) +static CURLcode setup_connection_internals(struct Curl_easy *data, + struct connectdata *conn) { const struct Curl_handler *p; CURLcode result; @@ -2093,7 +2114,7 @@ static CURLcode setup_connection_internals(struct connectdata *conn) p = conn->handler; if(p->setup_connection) { - result = (*p->setup_connection)(conn); + result = (*p->setup_connection)(data, conn); if(result) return result; @@ -3337,7 +3358,8 @@ static CURLcode resolve_server(struct Curl_easy *data, * previously existing one. All relevant data is copied over and old_conn is * ready for freeing once this function returns. */ -static void reuse_conn(struct connectdata *old_conn, +static void reuse_conn(struct Curl_easy *data, + struct connectdata *old_conn, struct connectdata *conn) { #ifndef CURL_DISABLE_PROXY @@ -3352,7 +3374,7 @@ static void reuse_conn(struct connectdata *old_conn, allocated in vain and is targeted for destruction */ Curl_free_primary_ssl_config(&old_conn->ssl_config); - conn->data = old_conn->data; + conn->data = data; /* get the user+password information from the old_conn struct since it may * be new for this request even when we re-use an existing connection */ @@ -3406,7 +3428,7 @@ static void reuse_conn(struct connectdata *old_conn, old_conn->hostname_resolve = NULL; /* persist connection info in session handle */ - Curl_persistconninfo(conn); + Curl_persistconninfo(data, conn); conn_reset_all_postponed_data(old_conn); /* free buffers */ @@ -3600,7 +3622,7 @@ static CURLcode create_conn(struct Curl_easy *data, * Setup internals depending on protocol. Needs to be done after * we figured out what/if proxy to use. *************************************************************/ - result = setup_connection_internals(conn); + result = setup_connection_internals(data, conn); if(result) goto out; @@ -3620,8 +3642,8 @@ static CURLcode create_conn(struct Curl_easy *data, /* this is supposed to be the connect function so we better at least check that the file is present here! */ DEBUGASSERT(conn->handler->connect_it); - Curl_persistconninfo(conn); - result = conn->handler->connect_it(conn, &done); + Curl_persistconninfo(data, conn); + result = conn->handler->connect_it(data, &done); /* Setup a "faked" transfer that'll do nothing */ if(!result) { @@ -3639,7 +3661,7 @@ static CURLcode create_conn(struct Curl_easy *data, if(result) { DEBUGASSERT(conn->handler->done); /* we ignore the return code for the protocol-specific DONE */ - (void)conn->handler->done(conn, result, FALSE); + (void)conn->handler->done(data, result, FALSE); goto out; } Curl_setup_transfer(data, -1, -1, FALSE, -1); @@ -3752,12 +3774,11 @@ static CURLcode create_conn(struct Curl_easy *data, if(reuse) { /* - * We already have a connection for this, we got the former connection - * in the conn_temp variable and thus we need to cleanup the one we - * just allocated before we can move along and use the previously - * existing one. + * We already have a connection for this, we got the former connection in + * the conn_temp variable and thus we need to cleanup the one we just + * allocated before we can move along and use the previously existing one. */ - reuse_conn(conn, conn_temp); + reuse_conn(data, conn, conn_temp); #ifdef USE_SSL free(conn->ssl_extra); #endif @@ -3958,7 +3979,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn, if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; - result = Curl_connecthost(conn, conn->dns_entry); + result = Curl_connecthost(data, conn, conn->dns_entry); if(result) return result; } @@ -3969,8 +3990,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn, Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */ conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; *protocol_done = TRUE; - Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]); - Curl_verboseconnect(conn); + Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]); + Curl_verboseconnect(data, conn); } conn->now = Curl_now(); /* time this *after* the connect is done, we set |