mirror of
https://github.com/curl/curl.git
synced 2026-04-11 12:01:42 +08:00
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:
parent
161be30854
commit
d7a9f1ab15
428
lib/url.c
428
lib/url.c
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user