url.c: code/comment cleanup around conn creation

Several comments were outdated and parameters to create_conn() and
ConnectionExists() were not needed. Give functions better names and
consistently use terms `needle` and `conn`.

No functional change.

Closes #20464
This commit is contained in:
Stefan Eissing 2026-01-28 17:20:57 +01:00 committed by Daniel Stenberg
parent 161be30854
commit d7a9f1ab15
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

428
lib/url.c
View File

@ -1268,25 +1268,22 @@ static bool url_match_result(bool result, void *userdata)
}
/*
* Given one filled in connection struct (named needle), this function should
* detect if there already is one that has all the significant details
* exactly the same and thus should be used instead.
* Given a transfer and a prototype connection (needle),
* find and attach an existing connection that matches.
*
* If there is a match, this function returns TRUE - and has marked the
* connection as 'in-use'. It must later be called with ConnectionDone() to
* return back to 'idle' (unused) state.
*
* The force_reuse flag is set if the connection must be used.
* Return TRUE if an existing connection was attached.
* `waitpipe` is TRUE if no existing connection matched, but there
* might be suitable one in the near future (common cause: multiplexing
* capability has not been determined yet, e.g. ALPN handshake).
*/
static bool ConnectionExists(struct Curl_easy *data,
struct connectdata *needle,
struct connectdata **usethis,
bool *force_reuse,
bool *waitpipe)
static bool url_attach_existing(struct Curl_easy *data,
struct connectdata *needle,
bool *waitpipe)
{
struct url_conn_match match;
bool result;
DEBUGASSERT(!data->conn);
memset(&match, 0, sizeof(match));
match.data = data;
match.needle = needle;
@ -1310,8 +1307,6 @@ static bool ConnectionExists(struct Curl_easy *data,
/* wait_pipe is TRUE if we encounter a bundle that is undecided. There
* is no matching connection then, yet. */
*usethis = match.found;
*force_reuse = (bool)match.force_reuse;
*waitpipe = (bool)match.wait_pipe;
return result;
}
@ -3118,42 +3113,41 @@ static void url_move_hostname(struct hostname *dest, struct hostname *src)
}
/*
* Cleanup the connection `temp`, just allocated for `data`, before using the
* previously `existing` one for `data`. All relevant info is copied over
* and `temp` is freed.
* Adjust reused connection settings to the transfer/needle.
*/
static void reuse_conn(struct Curl_easy *data,
struct connectdata *temp,
struct connectdata *existing)
static void url_conn_reuse_adjust(struct Curl_easy *data,
struct connectdata *needle)
{
/* get the user+password information from the temp struct since it may
* be new for this request even when we reuse an existing connection */
if(temp->user) {
struct connectdata *conn = data->conn;
/* get the user+password information from the needle since it may
* be new for this request even when we reuse conn */
if(needle->user) {
/* use the new username and password though */
curlx_free(existing->user);
curlx_free(existing->passwd);
existing->user = temp->user;
existing->passwd = temp->passwd;
temp->user = NULL;
temp->passwd = NULL;
curlx_free(conn->user);
curlx_free(conn->passwd);
conn->user = needle->user;
conn->passwd = needle->passwd;
needle->user = NULL;
needle->passwd = NULL;
}
#ifndef CURL_DISABLE_PROXY
existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd;
if(existing->bits.proxy_user_passwd) {
conn->bits.proxy_user_passwd = needle->bits.proxy_user_passwd;
if(conn->bits.proxy_user_passwd) {
/* use the new proxy username and proxy password though */
curlx_free(existing->http_proxy.user);
curlx_free(existing->socks_proxy.user);
curlx_free(existing->http_proxy.passwd);
curlx_free(existing->socks_proxy.passwd);
existing->http_proxy.user = temp->http_proxy.user;
existing->socks_proxy.user = temp->socks_proxy.user;
existing->http_proxy.passwd = temp->http_proxy.passwd;
existing->socks_proxy.passwd = temp->socks_proxy.passwd;
temp->http_proxy.user = NULL;
temp->socks_proxy.user = NULL;
temp->http_proxy.passwd = NULL;
temp->socks_proxy.passwd = NULL;
curlx_free(conn->http_proxy.user);
curlx_free(conn->socks_proxy.user);
curlx_free(conn->http_proxy.passwd);
curlx_free(conn->socks_proxy.passwd);
conn->http_proxy.user = needle->http_proxy.user;
conn->socks_proxy.user = needle->socks_proxy.user;
conn->http_proxy.passwd = needle->http_proxy.passwd;
conn->socks_proxy.passwd = needle->socks_proxy.passwd;
needle->http_proxy.user = NULL;
needle->socks_proxy.user = NULL;
needle->http_proxy.passwd = NULL;
needle->socks_proxy.passwd = NULL;
}
#endif
@ -3163,27 +3157,19 @@ static void reuse_conn(struct Curl_easy *data,
* - we use a proxy (not tunneling). we want to send all requests
* that use the same proxy on this connection.
* - we have a "connect-to" setting that may redirect the hostname of
* a new request to the same remote endpoint of an existing conn.
* We want to reuse an existing conn to the remote endpoint.
* a new request to the same remote endpoint of an conn conn.
* We want to reuse an conn conn to the remote endpoint.
* Since connection reuse does not match on conn->host necessarily, we
* switch `existing` conn to `temp` conn's host settings.
* Is this correct in the case of TLS connections that have
* used the original hostname in SNI to negotiate? Do we send
* requests for another host through the different SNI?
* switch conn to needle's host settings.
*/
url_move_hostname(&existing->host, &temp->host);
url_move_hostname(&existing->conn_to_host, &temp->conn_to_host);
url_move_hostname(&conn->host, &needle->host);
url_move_hostname(&conn->conn_to_host, &needle->conn_to_host);
existing->conn_to_port = temp->conn_to_port;
existing->remote_port = temp->remote_port;
curlx_free(existing->hostname_resolve);
existing->hostname_resolve = temp->hostname_resolve;
temp->hostname_resolve = NULL;
/* reuse init */
existing->bits.reuse = TRUE; /* yes, we are reusing here */
Curl_conn_free(data, temp);
conn->conn_to_port = needle->conn_to_port;
conn->remote_port = needle->remote_port;
curlx_free(conn->hostname_resolve);
conn->hostname_resolve = needle->hostname_resolve;
needle->hostname_resolve = NULL;
}
static void conn_meta_freeentry(void *p)
@ -3195,35 +3181,11 @@ static void conn_meta_freeentry(void *p)
DEBUGASSERT(p == NULL);
}
/**
* create_conn() sets up a new connectdata struct, or reuses an already
* existing one, and resolves hostname.
*
* if this function returns CURLE_OK and *async is set to TRUE, the resolve
* response will be coming asynchronously. If *async is FALSE, the name is
* already resolved.
*
* @param data The sessionhandle pointer
* @param in_connect is set to the next connection data pointer
* @param reusedp is set to to TRUE if connection was reused
* @see Curl_setup_conn()
*
*/
static CURLcode create_conn(struct Curl_easy *data,
struct connectdata **in_connect,
bool *reusedp)
static CURLcode url_create_needle(struct Curl_easy *data,
struct connectdata **pneedle)
{
struct connectdata *needle = NULL;
CURLcode result = CURLE_OK;
struct connectdata *conn;
struct connectdata *existing = NULL;
bool reuse;
bool connections_available = TRUE;
bool force_reuse = FALSE;
bool waitpipe = FALSE;
*reusedp = FALSE;
*in_connect = NULL;
/*************************************************************
* Check input data
@ -3237,37 +3199,31 @@ static CURLcode create_conn(struct Curl_easy *data,
parts for checking against the already present connections. In order
to not have to modify everything at once, we allocate a temporary
connection data struct and fill in for comparison purposes. */
conn = allocate_conn(data);
if(!conn) {
needle = allocate_conn(data);
if(!needle) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
/* We must set the return variable as soon as possible, so that our
parent can cleanup any possible allocs we may have done before
any failure */
*in_connect = conn;
/* Do the unfailable inits first, before checks that may early return */
Curl_hash_init(&conn->meta_hash, 23,
Curl_hash_init(&needle->meta_hash, 23,
Curl_hash_str, curlx_str_key_compare, conn_meta_freeentry);
result = parseurlandfillconn(data, conn);
result = parseurlandfillconn(data, needle);
if(result)
goto out;
if(data->set.str[STRING_SASL_AUTHZID]) {
conn->sasl_authzid = curlx_strdup(data->set.str[STRING_SASL_AUTHZID]);
if(!conn->sasl_authzid) {
needle->sasl_authzid = curlx_strdup(data->set.str[STRING_SASL_AUTHZID]);
if(!needle->sasl_authzid) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
}
if(data->set.str[STRING_BEARER]) {
conn->oauth_bearer = curlx_strdup(data->set.str[STRING_BEARER]);
if(!conn->oauth_bearer) {
needle->oauth_bearer = curlx_strdup(data->set.str[STRING_BEARER]);
if(!needle->oauth_bearer) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@ -3275,20 +3231,20 @@ static CURLcode create_conn(struct Curl_easy *data,
#ifdef USE_UNIX_SOCKETS
if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
conn->unix_domain_socket =
needle->unix_domain_socket =
curlx_strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
if(!conn->unix_domain_socket) {
if(!needle->unix_domain_socket) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
needle->bits.abstract_unix_socket = data->set.abstract_unix_socket;
}
#endif
/* After the Unix socket init but before the proxy vars are used, parse and
initialize the proxy vars */
#ifndef CURL_DISABLE_PROXY
result = create_conn_helper_init_proxy(data, conn);
result = create_conn_helper_init_proxy(data, needle);
if(result)
goto out;
@ -3296,24 +3252,24 @@ static CURLcode create_conn(struct Curl_easy *data,
* If the protocol is using SSL and HTTP proxy is used, we set
* the tunnel_proxy bit.
*************************************************************/
if((conn->given->flags & PROTOPT_SSL) && conn->bits.httpproxy)
conn->bits.tunnel_proxy = TRUE;
if((needle->given->flags & PROTOPT_SSL) && needle->bits.httpproxy)
needle->bits.tunnel_proxy = TRUE;
#endif
/*************************************************************
* Figure out the remote port number and fix it in the URL
*************************************************************/
result = parse_remote_port(data, conn);
result = parse_remote_port(data, needle);
if(result)
goto out;
/* Check for overridden login details and set them accordingly so that
they are known when protocol->setup_connection is called! */
result = override_login(data, conn);
result = override_login(data, needle);
if(result)
goto out;
result = set_login(data, conn); /* default credentials */
result = set_login(data, needle); /* default credentials */
if(result)
goto out;
@ -3321,7 +3277,7 @@ static CURLcode create_conn(struct Curl_easy *data,
* Process the "connect to" linked list of hostname/port mappings.
* Do this after the remote port number has been fixed in the URL.
*************************************************************/
result = parse_connect_to_slist(data, conn, data->set.connect_to);
result = parse_connect_to_slist(data, needle, data->set.connect_to);
if(result)
goto out;
@ -3329,38 +3285,39 @@ static CURLcode create_conn(struct Curl_easy *data,
* IDN-convert the proxy hostnames
*************************************************************/
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy) {
result = Curl_idnconvert_hostname(&conn->http_proxy.host);
if(needle->bits.httpproxy) {
result = Curl_idnconvert_hostname(&needle->http_proxy.host);
if(result)
return result;
goto out;
}
if(conn->bits.socksproxy) {
result = Curl_idnconvert_hostname(&conn->socks_proxy.host);
if(needle->bits.socksproxy) {
result = Curl_idnconvert_hostname(&needle->socks_proxy.host);
if(result)
return result;
goto out;
}
#endif
if(conn->bits.conn_to_host) {
result = Curl_idnconvert_hostname(&conn->conn_to_host);
if(needle->bits.conn_to_host) {
result = Curl_idnconvert_hostname(&needle->conn_to_host);
if(result)
return result;
goto out;
}
/*************************************************************
* Check whether the host and the "connect to host" are equal.
* Do this after the hostnames have been IDN-converted.
*************************************************************/
if(conn->bits.conn_to_host &&
curl_strequal(conn->conn_to_host.name, conn->host.name)) {
conn->bits.conn_to_host = FALSE;
if(needle->bits.conn_to_host &&
curl_strequal(needle->conn_to_host.name, needle->host.name)) {
needle->bits.conn_to_host = FALSE;
}
/*************************************************************
* Check whether the port and the "connect to port" are equal.
* Do this after the remote port number has been fixed in the URL.
*************************************************************/
if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
conn->bits.conn_to_port = FALSE;
if(needle->bits.conn_to_port &&
needle->conn_to_port == needle->remote_port) {
needle->bits.conn_to_port = FALSE;
}
#ifndef CURL_DISABLE_PROXY
@ -3368,101 +3325,137 @@ static CURLcode create_conn(struct Curl_easy *data,
* If the "connect to" feature is used with an HTTP proxy,
* we set the tunnel_proxy bit.
*************************************************************/
if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
conn->bits.httpproxy)
conn->bits.tunnel_proxy = TRUE;
if((needle->bits.conn_to_host || needle->bits.conn_to_port) &&
needle->bits.httpproxy)
needle->bits.tunnel_proxy = TRUE;
#endif
/*************************************************************
* Setup internals depending on protocol. Needs to be done after
* we figured out what/if proxy to use.
*************************************************************/
result = setup_connection_internals(data, conn);
result = setup_connection_internals(data, needle);
if(result)
goto out;
if(needle->scheme->flags & PROTOPT_ALPN) {
/* The protocol wants it, so set the bits if enabled in the easy handle
(default) */
if(data->set.ssl_enable_alpn)
needle->bits.tls_enable_alpn = TRUE;
}
if(!(needle->scheme->flags & PROTOPT_NONETWORK)) {
/* Setup callbacks for network connections */
needle->recv[FIRSTSOCKET] = Curl_cf_recv;
needle->send[FIRSTSOCKET] = Curl_cf_send;
needle->recv[SECONDARYSOCKET] = Curl_cf_recv;
needle->send[SECONDARYSOCKET] = Curl_cf_send;
needle->bits.tcp_fastopen = data->set.tcp_fastopen;
}
out:
if(!result) {
DEBUGASSERT(needle);
*pneedle = needle;
}
else {
*pneedle = NULL;
if(needle)
Curl_conn_free(data, needle);
}
return result;
}
/**
* Find an existing connection for the transfer or create a new one.
* Returns
* - CURLE_OK on success with a connection attached to data
* - CURLE_NO_CONNECTION_AVAILABLE when connection limits apply or when
* a suitable connection has not determined its multiplex capability.
* - a fatal error
*/
static CURLcode url_find_or_create_conn(struct Curl_easy *data)
{
struct connectdata *needle = NULL;
bool waitpipe = FALSE;
CURLcode result;
/* create the template connection for transfer data. Use this needle to
* find an existing connection or, if none exists, convert needle
* to a full connection and attach it to data. */
result = url_create_needle(data, &needle);
if(result)
goto out;
DEBUGASSERT(needle);
/***********************************************************************
* file: is a special case in that it does not need a network connection
***********************************************************************/
#ifndef CURL_DISABLE_FILE
if(conn->scheme->flags & PROTOPT_NONETWORK) {
if(needle->scheme->flags & PROTOPT_NONETWORK) {
bool done;
/* this is supposed to be the connect function so we better at least check
that the file is present here! */
DEBUGASSERT(conn->scheme->run->connect_it);
data->info.conn_scheme = conn->scheme->name;
DEBUGASSERT(needle->scheme->run->connect_it);
data->info.conn_scheme = needle->scheme->name;
/* conn_protocol can only provide "old" protocols */
data->info.conn_protocol = (conn->scheme->protocol) & CURLPROTO_MASK;
result = conn->scheme->run->connect_it(data, &done);
data->info.conn_protocol = (needle->scheme->protocol) & CURLPROTO_MASK;
result = needle->scheme->run->connect_it(data, &done);
if(result)
goto out;
/* Setup a "faked" transfer that will do nothing */
Curl_attach_connection(data, conn);
result = Curl_cpool_add(data, conn);
Curl_attach_connection(data, needle);
needle = NULL;
result = Curl_cpool_add(data, data->conn);
if(!result) {
/* Setup whatever necessary for a resumed transfer */
result = setup_range(data);
if(!result) {
Curl_xfer_setup_nop(data);
result = Curl_init_do(data, conn);
result = Curl_init_do(data, data->conn);
}
}
if(result) {
DEBUGASSERT(conn->scheme->run->done);
DEBUGASSERT(data->conn->scheme->run->done);
/* we ignore the return code for the protocol-specific DONE */
(void)conn->scheme->run->done(data, result, FALSE);
(void)data->conn->scheme->run->done(data, result, FALSE);
}
goto out;
}
#endif
/* Setup filter for network connections */
conn->recv[FIRSTSOCKET] = Curl_cf_recv;
conn->send[FIRSTSOCKET] = Curl_cf_send;
conn->recv[SECONDARYSOCKET] = Curl_cf_recv;
conn->send[SECONDARYSOCKET] = Curl_cf_send;
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
/* Complete the easy's SSL configuration for connection cache matching */
result = Curl_ssl_easy_config_complete(data);
if(result)
goto out;
/* Get rid of any dead connections so limit are easier kept. */
Curl_cpool_prune_dead(data);
/*************************************************************
* Check the current list of connections to see if we can
* reuse an already existing one or if we have to create a
* new one.
* Reuse of existing connection is not allowed when
* - connect_only is set or
* - reuse_fresh is set and this is not a follow-up request
* (like with HTTP followlocation)
*************************************************************/
if((!data->set.reuse_fresh || data->state.followlocation) &&
!data->set.connect_only) {
/* Ok, try to find and attach an existing one */
url_attach_existing(data, needle, &waitpipe);
}
DEBUGASSERT(conn->user);
DEBUGASSERT(conn->passwd);
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
we only acknowledge this option if this is not a reused connection
already (which happens due to follow-location or during an HTTP
authentication phase). CONNECT_ONLY transfers also refuse reuse. */
if((data->set.reuse_fresh && !data->state.followlocation) ||
data->set.connect_only)
reuse = FALSE;
else
reuse = ConnectionExists(data, conn, &existing, &force_reuse, &waitpipe);
if(reuse) {
/*
* We already have a connection for this, we got the former connection in
* `existing` and thus we need to cleanup the one we just
* allocated before we can move along and use `existing`.
*/
VERBOSE(bool tls_upgraded = (!(conn->given->flags & PROTOPT_SSL) &&
if(data->conn) {
/* We attached an existing connection for this transfer. Copy
* over transfer specific properties over from needle. */
struct connectdata *conn = data->conn;
VERBOSE(bool tls_upgraded = (!(needle->given->flags & PROTOPT_SSL) &&
Curl_conn_is_ssl(conn, FIRSTSOCKET)));
reuse_conn(data, conn, existing);
conn = existing;
*in_connect = conn;
conn->bits.reuse = TRUE;
url_conn_reuse_adjust(data, needle);
#ifndef CURL_DISABLE_PROXY
infof(data, "Reusing existing %s: connection%s with %s %s",
@ -3483,27 +3476,21 @@ static CURLcode create_conn(struct Curl_easy *data,
/* We have decided that we want a new connection. However, we may not
be able to do that if we have reached the limit of how many
connections we are allowed to open. */
DEBUGF(infof(data, "new connection, bits.close=%d", conn->bits.close));
if(conn->scheme->flags & PROTOPT_ALPN) {
/* The protocol wants it, so set the bits if enabled in the easy handle
(default) */
if(data->set.ssl_enable_alpn)
conn->bits.tls_enable_alpn = TRUE;
}
DEBUGF(infof(data, "new connection, bits.close=%d", needle->bits.close));
if(waitpipe) {
/* There is a connection that *might* become usable for multiplexing
"soon", and we wait for that */
infof(data, "Waiting on connection to negotiate possible multiplexing.");
connections_available = FALSE;
result = CURLE_NO_CONNECTION_AVAILABLE;
goto out;
}
else {
switch(Curl_cpool_check_limits(data, conn)) {
switch(Curl_cpool_check_limits(data, needle)) {
case CPOOL_LIMIT_DEST:
infof(data, "No more connections allowed to host");
connections_available = FALSE;
break;
result = CURLE_NO_CONNECTION_AVAILABLE;
goto out;
case CPOOL_LIMIT_TOTAL:
if(data->master_mid != UINT32_MAX)
CURL_TRC_M(data, "Allowing sub-requests (like DoH) to override "
@ -3511,7 +3498,8 @@ static CURLcode create_conn(struct Curl_easy *data,
else {
infof(data, "No connections available, total of %zu reached.",
data->multi->max_total_connections);
connections_available = FALSE;
result = CURLE_NO_CONNECTION_AVAILABLE;
goto out;
}
break;
default:
@ -3519,29 +3507,20 @@ static CURLcode create_conn(struct Curl_easy *data,
}
}
if(!connections_available) {
Curl_conn_free(data, conn);
*in_connect = NULL;
result = CURLE_NO_CONNECTION_AVAILABLE;
/* Convert needle into a full connection by filling in all the
* remaining parts like the cloned SSL configuration. */
result = Curl_ssl_conn_config_init(data, needle);
if(result) {
DEBUGF(curl_mfprintf(stderr, "Error: init connection ssl config\n"));
goto out;
}
else {
/*
* This is a brand new connection, so let's store it in the connection
* cache of ours!
*/
result = Curl_ssl_conn_config_init(data, conn);
if(result) {
DEBUGF(curl_mfprintf(stderr, "Error: init connection ssl config\n"));
goto out;
}
/* attach it and no longer own it */
Curl_attach_connection(data, needle);
needle = NULL;
Curl_attach_connection(data, conn);
result = Curl_cpool_add(data, conn);
if(result)
goto out;
}
result = Curl_cpool_add(data, data->conn);
if(result)
goto out;
#ifdef USE_NTLM
/* If NTLM is requested in a part of this connection, make sure we do not
@ -3564,43 +3543,34 @@ static CURLcode create_conn(struct Curl_easy *data,
}
/* Setup and init stuff before DO starts, in preparing for the transfer. */
result = Curl_init_do(data, conn);
result = Curl_init_do(data, data->conn);
if(result)
goto out;
/*
* Setup whatever necessary for a resumed transfer
*/
/* Setup whatever necessary for a resumed transfer */
result = setup_range(data);
if(result)
goto out;
/* Continue connectdata initialization here. */
if(conn->bits.reuse) {
/* We are reusing the connection - no need to resolve anything, and
idnconvert_hostname() was called already in create_conn() for the reuse
case. */
*reusedp = TRUE;
}
/* persist the scheme and handler the transfer is using */
data->info.conn_scheme = conn->scheme->name;
data->info.conn_scheme = data->conn->scheme->name;
/* conn_protocol can only provide "old" protocols */
data->info.conn_protocol = (conn->scheme->protocol) & CURLPROTO_MASK;
data->info.conn_protocol = (data->conn->scheme->protocol) & CURLPROTO_MASK;
data->info.used_proxy =
#ifdef CURL_DISABLE_PROXY
0
#else
conn->bits.proxy
data->conn->bits.proxy
#endif
;
/* Everything general done, inform filters that they need
* to prepare for a data transfer. */
/* Lastly, inform connection filters that a new transfer is attached */
result = Curl_conn_ev_data_setup(data);
out:
if(needle)
Curl_conn_free(data, needle);
DEBUGASSERT(result || data->conn);
return result;
}
@ -3636,7 +3606,6 @@ CURLcode Curl_connect(struct Curl_easy *data,
{
CURLcode result;
struct connectdata *conn;
bool reused = FALSE;
*asyncp = FALSE; /* assume synchronous resolves by default */
*protocol_done = FALSE;
@ -3644,8 +3613,9 @@ CURLcode Curl_connect(struct Curl_easy *data,
/* Set the request to virgin state based on transfer settings */
Curl_req_hard_reset(&data->req, data);
/* call the stuff that needs to be called */
result = create_conn(data, &conn, &reused);
/* Get or create a connection for the transfer. */
result = url_find_or_create_conn(data);
conn = data->conn;
if(result == CURLE_NO_CONNECTION_AVAILABLE) {
DEBUGASSERT(!conn);
@ -3655,7 +3625,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
if(!result) {
DEBUGASSERT(conn);
Curl_pgrsTime(data, TIMER_POSTQUEUE);
if(reused) {
if(conn->bits.reuse) {
if(conn->attached_xfers > 1)
/* multiplexed */
*protocol_done = TRUE;