diff options
Diffstat (limited to 'libs/libcurl/src/url.c')
-rw-r--r-- | libs/libcurl/src/url.c | 436 |
1 files changed, 203 insertions, 233 deletions
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c index fe8d61aeda..dcd4b25d38 100644 --- a/libs/libcurl/src/url.c +++ b/libs/libcurl/src/url.c @@ -75,7 +75,6 @@ #include "strcase.h"
#include "strerror.h"
#include "escape.h"
-#include "strtok.h"
#include "share.h"
#include "content_encoding.h"
#include "http_digest.h"
@@ -91,6 +90,7 @@ #include "hsts.h"
#include "noproxy.h"
#include "cfilters.h"
+#include "curl_krb5.h"
#include "idn.h"
/* And now for the protocols */
@@ -119,7 +119,7 @@ #include "altsvc.h"
#include "dynbuf.h"
#include "headers.h"
-
+#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -286,6 +286,7 @@ CURLcode Curl_close(struct Curl_easy **datap) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
+ Curl_safefree(data->state.most_recent_ftp_entrypath);
Curl_safefree(data->info.contenttype);
Curl_safefree(data->info.wouldredirect);
@@ -428,7 +429,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) */
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL &&
Curl_ssl_backend() != CURLSSLBACKEND_SECURETRANSPORT) {
-#if defined(CURL_CA_BUNDLE)
+#ifdef CURL_CA_BUNDLE
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(result)
return result;
@@ -439,7 +440,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) return result;
#endif
#endif
-#if defined(CURL_CA_PATH)
+#ifdef CURL_CA_PATH
result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
if(result)
return result;
@@ -474,11 +475,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->maxage_conn = 118;
set->maxlifetime_conn = 0;
set->http09_allowed = FALSE;
-#ifdef USE_HTTP2
- set->httpwant = CURL_HTTP_VERSION_2TLS
-#else
- set->httpwant = CURL_HTTP_VERSION_1_1
-#endif
+ set->httpwant = CURL_HTTP_VERSION_NONE
;
#if defined(USE_HTTP2) || defined(USE_HTTP3)
memset(&set->priority, 0, sizeof(set->priority));
@@ -510,39 +507,38 @@ CURLcode Curl_open(struct Curl_easy **curl) data->magic = CURLEASY_MAGIC_NUMBER;
+ Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
Curl_req_init(&data->req);
+ Curl_initinfo(data);
+#ifndef CURL_DISABLE_HTTP
+ Curl_llist_init(&data->state.httphdrs, NULL);
+#endif
+ Curl_netrc_init(&data->state.netrc);
result = Curl_resolver_init(data, &data->state.async.resolver);
if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
- Curl_req_free(&data->req, data);
- free(data);
- return result;
+ goto out;
}
result = Curl_init_userdefined(data);
- if(!result) {
- Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
- Curl_initinfo(data);
-
- /* most recent connection is not yet defined */
- data->state.lastconnect_id = -1;
- data->state.recent_conn_id = -1;
- /* and not assigned an id yet */
- data->id = -1;
- data->mid = -1;
+ if(result)
+ goto out;
+
+ /* most recent connection is not yet defined */
+ data->state.lastconnect_id = -1;
+ data->state.recent_conn_id = -1;
+ /* and not assigned an id yet */
+ data->id = -1;
+ data->mid = -1;
#ifndef CURL_DISABLE_DOH
- data->set.dohfor_mid = -1;
+ data->set.dohfor_mid = -1;
#endif
- data->progress.flags |= PGRS_HIDE;
- data->state.current_speed = -1; /* init to negative == impossible */
-#ifndef CURL_DISABLE_HTTP
- Curl_llist_init(&data->state.httphdrs, NULL);
-#endif
- Curl_netrc_init(&data->state.netrc);
- }
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
+out:
if(result) {
Curl_resolver_cleanup(data->state.async.resolver);
Curl_dyn_free(&data->state.headerb);
@@ -562,6 +558,10 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn) DEBUGASSERT(conn);
+ if(conn->handler && conn->handler->disconnect &&
+ !conn->bits.shutdown_handler)
+ conn->handler->disconnect(data, conn, TRUE);
+
for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
Curl_conn_cf_discard_all(data, conn, (int)i);
}
@@ -578,6 +578,7 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
#endif
+ Curl_sec_conn_destroy(conn);
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->sasl_authzid);
@@ -599,52 +600,6 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn) }
/*
- * Disconnects the given connection. Note the connection may not be the
- * primary connection, like when freeing room in the connection pool or
- * killing of a dead old connection.
- *
- * A connection needs an easy handle when closing down. We support this passed
- * in separately since the connection to get closed here is often already
- * disassociated from an easy handle.
- *
- * This function MUST NOT reset state in the Curl_easy struct if that
- * is not strictly bound to the life-time of *this* particular connection.
- */
-bool Curl_on_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool aborted)
-{
- /* there must be a connection to close */
- DEBUGASSERT(conn);
-
- /* it must be removed from the connection pool */
- DEBUGASSERT(!conn->bits.in_cpool);
-
- /* there must be an associated transfer */
- DEBUGASSERT(data);
-
- /* the transfer must be detached from the connection */
- DEBUGASSERT(!data->conn);
-
- DEBUGF(infof(data, "Curl_disconnect(conn #%" FMT_OFF_T ", aborted=%d)",
- conn->connection_id, aborted));
-
- if(conn->dns_entry)
- Curl_resolv_unlink(data, &conn->dns_entry);
-
- /* Cleanup NTLM connection-related data */
- Curl_http_auth_cleanup_ntlm(conn);
-
- /* Cleanup NEGOTIATE connection-related data */
- Curl_http_auth_cleanup_negotiate(conn);
-
- if(conn->connect_only)
- /* treat the connection as aborted in CONNECT_ONLY situations */
- aborted = TRUE;
-
- return aborted;
-}
-
-/*
* xfer_may_multiplex()
*
* Return a TRUE, iff the transfer can be done over an (appropriate)
@@ -653,15 +608,20 @@ bool Curl_on_disconnect(struct Curl_easy *data, static bool xfer_may_multiplex(const struct Curl_easy *data,
const struct connectdata *conn)
{
+#ifndef CURL_DISABLE_HTTP
/* If an HTTP protocol and multiplexing is enabled */
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(!conn->bits.protoconnstart || !conn->bits.close)) {
if(Curl_multiplex_wanted(data->multi) &&
- (data->state.httpwant >= CURL_HTTP_VERSION_2))
+ (data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)))
/* allows HTTP/2 or newer */
return TRUE;
}
+#else
+ (void)data;
+ (void)conn;
+#endif
return FALSE;
}
@@ -836,8 +796,6 @@ static bool ssh_config_matches(struct connectdata *one, return Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub);
}
-#else
-#define ssh_config_matches(x,y) FALSE
#endif
struct url_conn_match {
@@ -952,13 +910,17 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) return FALSE;
#endif
- if((!(needle->handler->flags&PROTOPT_SSL) !=
- !Curl_conn_is_ssl(conn, FIRSTSOCKET)) &&
- !(get_protocol_family(conn->handler) == needle->handler->protocol &&
- conn->bits.tls_upgraded))
- /* Deny `conn` if it is not fit for `needle`'s SSL needs,
- * UNLESS `conn` is the same protocol family and was upgraded to SSL. */
+ if(needle->handler->flags&PROTOPT_SSL) {
+ /* We are looking for SSL, if `conn` does not do it, not a match. */
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET))
return FALSE;
+ }
+ else if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ /* We are not *requiring* SSL, however `conn` has it. If the
+ * protocol *family* is not the same, not a match. */
+ if(get_protocol_family(conn->handler) != needle->handler->protocol)
+ return FALSE;
+ }
#ifndef CURL_DISABLE_PROXY
if(needle->bits.httpproxy != conn->bits.httpproxy ||
@@ -995,8 +957,9 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) }
#endif
+#ifndef CURL_DISABLE_HTTP
if(match->may_multiplex &&
- (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
+ (data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)) &&
(needle->handler->protocol & CURLPROTO_HTTP) &&
!conn->httpversion_seen) {
if(data->set.pipewait) {
@@ -1008,6 +971,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) infof(data, "Server upgrade cannot be used");
return FALSE;
}
+#endif
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
@@ -1028,27 +992,36 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) return FALSE;
#endif
- /* If looking for HTTP and the HTTP version we want is less
- * than the HTTP version of conn, continue looking.
- * CURL_HTTP_VERSION_2TLS is default which indicates no preference,
- * so we take any existing connection. */
- if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
- (data->state.httpwant != CURL_HTTP_VERSION_2TLS)) {
- unsigned char httpversion = Curl_conn_http_version(data);
- if((httpversion >= 20) &&
- (data->state.httpwant < CURL_HTTP_VERSION_2_0)) {
- DEBUGF(infof(data, "nor reusing conn #%" CURL_FORMAT_CURL_OFF_T
- " with httpversion=%d, we want a version less than h2",
- conn->connection_id, httpversion));
- }
- if((httpversion >= 30) &&
- (data->state.httpwant < CURL_HTTP_VERSION_3)) {
- DEBUGF(infof(data, "nor reusing conn #%" CURL_FORMAT_CURL_OFF_T
- " with httpversion=%d, we want a version less than h3",
- conn->connection_id, httpversion));
- return FALSE;
+#ifndef CURL_DISABLE_HTTP
+ /* If looking for HTTP and the HTTP versions allowed do not include
+ * the HTTP version of conn, continue looking. */
+ if((needle->handler->protocol & PROTO_FAMILY_HTTP)) {
+ switch(Curl_conn_http_version(data, conn)) {
+ case 30:
+ if(!(data->state.http_neg.allowed & CURL_HTTP_V3x)) {
+ DEBUGF(infof(data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
+ ", we do not want h3", conn->connection_id));
+ return FALSE;
+ }
+ break;
+ case 20:
+ if(!(data->state.http_neg.allowed & CURL_HTTP_V2x)) {
+ DEBUGF(infof(data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
+ ", we do not want h2", conn->connection_id));
+ return FALSE;
+ }
+ break;
+ default:
+ if(!(data->state.http_neg.allowed & CURL_HTTP_V1x)) {
+ DEBUGF(infof(data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
+ ", we do not want h1", conn->connection_id));
+ return FALSE;
+ }
+ break;
}
}
+#endif
+
#ifdef USE_SSH
else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
if(!ssh_config_matches(needle, conn))
@@ -1075,12 +1048,21 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) || !needle->bits.httpproxy || needle->bits.tunnel_proxy
#endif
) {
- /* Talking the same protocol scheme or a TLS upgraded protocol in the
- * same protocol family? */
- if(!strcasecompare(needle->handler->scheme, conn->handler->scheme) &&
- (get_protocol_family(conn->handler) !=
- needle->handler->protocol || !conn->bits.tls_upgraded))
- return FALSE;
+ if(!strcasecompare(needle->handler->scheme, conn->handler->scheme)) {
+ /* `needle` and `conn` do not have the same scheme... */
+ if(get_protocol_family(conn->handler) != needle->handler->protocol) {
+ /* and `conn`s protocol family is not the protocol `needle` wants.
+ * IMAPS would work for IMAP, but no vice versa. */
+ return FALSE;
+ }
+ /* We are in an IMAPS vs IMAP like case. We expect `conn` to have SSL */
+ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ DEBUGF(infof(data,
+ "Connection #%" FMT_OFF_T " has compatible protocol famiy, "
+ "but no SSL, no match", conn->connection_id));
+ return FALSE;
+ }
+ }
/* If needle has "conn_to_*" set, conn must match this */
if((needle->bits.conn_to_host && !strcasecompare(
@@ -1105,7 +1087,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) }
}
-#if defined(USE_NTLM)
+#ifdef USE_NTLM
/* If we are looking for an HTTP+NTLM connection, check if this is
already authenticating with the right credentials. If not, keep
looking so that we can reuse NTLM connections if
@@ -1187,7 +1169,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) }
else if(Curl_conn_seems_dead(conn, data, NULL)) {
/* removed and disconnect. Do not treat as aborted. */
- Curl_cpool_disconnect(data, conn, FALSE);
+ Curl_conn_terminate(data, conn, FALSE);
return FALSE;
}
@@ -1260,7 +1242,7 @@ ConnectionExists(struct Curl_easy *data, /* Find a connection in the pool that matches what "data + needle"
* requires. If a suitable candidate is found, it is attached to "data". */
- result = Curl_cpool_find(data, needle->destination, needle->destination_len,
+ result = Curl_cpool_find(data, needle->destination,
url_match_conn, url_match_result, &match);
/* wait_pipe is TRUE if we encounter a bundle that is undecided. There
@@ -1285,7 +1267,7 @@ void Curl_verboseconnect(struct Curl_easy *data, infof(data, "Connected to %s (%s) port %u",
CURL_CONN_HOST_DISPNAME(conn), conn->primary.remote_ip,
conn->primary.remote_port);
-#if !defined(CURL_DISABLE_HTTP)
+#ifndef CURL_DISABLE_HTTP
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
switch(conn->alpn) {
case CURL_HTTP_VERSION_3:
@@ -1440,7 +1422,7 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, #else
NULL,
#endif
-#if defined(USE_SSH)
+#ifdef USE_SSH
&Curl_handler_sftp,
#else
NULL,
@@ -1682,12 +1664,12 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, #endif
if(!uc && zoneid) {
- char *endp;
- unsigned long scope = strtoul(zoneid, &endp, 10);
- if(!*endp && (scope < UINT_MAX))
+ const char *p = zoneid;
+ curl_off_t scope;
+ if(!Curl_str_number(&p, &scope, UINT_MAX))
/* A plain number, use it directly as a scope id. */
conn->scope_id = (unsigned int)scope;
-#if defined(HAVE_IF_NAMETOINDEX)
+#ifdef HAVE_IF_NAMETOINDEX
else {
#elif defined(_WIN32)
else if(Curl_if_nametoindex) {
@@ -1696,7 +1678,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, #if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32)
/* Zone identifier is not numeric */
unsigned int scopeidx = 0;
-#if defined(_WIN32)
+#ifdef _WIN32
scopeidx = Curl_if_nametoindex(zoneid);
#else
scopeidx = if_nametoindex(zoneid);
@@ -1921,10 +1903,17 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY;
}
else {
- unsigned long port = strtoul(data->state.up.port, NULL, 10);
- conn->primary.remote_port = conn->remote_port =
- (data->set.use_port && data->state.allow_port) ?
- data->set.use_port : curlx_ultous(port);
+ curl_off_t port;
+ bool valid = TRUE;
+ if(data->set.use_port && data->state.allow_port)
+ port = data->set.use_port;
+ else {
+ const char *p = data->state.up.port;
+ if(Curl_str_number(&p, &port, 0xffff))
+ valid = FALSE;
+ }
+ if(valid)
+ conn->primary.remote_port = conn->remote_port = (unsigned short)port;
}
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
@@ -2029,9 +2018,8 @@ static CURLcode setup_connection_internals(struct Curl_easy *data, if(!conn->destination)
return CURLE_OUT_OF_MEMORY;
- conn->destination_len = strlen(conn->destination) + 1;
Curl_strntolower(conn->destination, conn->destination,
- conn->destination_len - 1);
+ strlen(conn->destination));
return CURLE_OK;
}
@@ -2068,7 +2056,7 @@ static char *detect_proxy(struct Curl_easy *data, * checked if the lowercase versions do not exist.
*/
char proxy_env[20];
- char *envp = proxy_env;
+ const char *envp = proxy_env;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -2109,10 +2097,10 @@ static char *detect_proxy(struct Curl_easy *data, }
if(!proxy) {
#endif
- envp = (char *)"all_proxy";
+ envp = "all_proxy";
proxy = curl_getenv(envp); /* default proxy to use */
if(!proxy) {
- envp = (char *)"ALL_PROXY";
+ envp = "ALL_PROXY";
proxy = curl_getenv(envp);
}
#ifndef CURL_DISABLE_WEBSOCKETS
@@ -2228,7 +2216,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, goto error;
if(proxyuser || proxypasswd) {
- Curl_safefree(proxyinfo->user);
+ free(proxyinfo->user);
proxyinfo->user = proxyuser;
result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser);
proxyuser = NULL;
@@ -2253,7 +2241,10 @@ static CURLcode parse_proxy(struct Curl_easy *data, (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
if(portptr) {
- port = (int)strtol(portptr, NULL, 10);
+ curl_off_t num;
+ const char *p = portptr;
+ if(!Curl_str_number(&p, &num, 0xffff))
+ port = (int)num;
free(portptr);
}
else {
@@ -2297,7 +2288,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, result = CURLE_OUT_OF_MEMORY;
goto error;
}
- Curl_safefree(proxyinfo->host.rawalloc);
+ free(proxyinfo->host.rawalloc);
proxyinfo->host.rawalloc = host;
proxyinfo->host.name = host;
host = NULL;
@@ -2306,7 +2297,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, if(!is_unix_proxy) {
#endif
- Curl_safefree(proxyinfo->host.rawalloc);
+ free(proxyinfo->host.rawalloc);
proxyinfo->host.rawalloc = host;
if(host[0] == '[') {
/* this is a numerical IPv6, strip off the brackets */
@@ -2493,7 +2484,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, if(!conn->socks_proxy.user) {
conn->socks_proxy.user = conn->http_proxy.user;
conn->http_proxy.user = NULL;
- Curl_safefree(conn->socks_proxy.passwd);
+ free(conn->socks_proxy.passwd);
conn->socks_proxy.passwd = conn->http_proxy.passwd;
conn->http_proxy.passwd = NULL;
}
@@ -2728,7 +2719,7 @@ static CURLcode override_login(struct Curl_easy *data, }
}
if(url_provided) {
- Curl_safefree(conn->user);
+ free(conn->user);
conn->user = strdup(*userp);
if(!conn->user)
return CURLE_OUT_OF_MEMORY;
@@ -2836,7 +2827,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, int port = -1;
CURLcode result = CURLE_OK;
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void) data;
#endif
@@ -2891,19 +2882,18 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, /* Get port number off server.com:1080 */
host_portno = strchr(portptr, ':');
if(host_portno) {
- char *endp = NULL;
*host_portno = '\0'; /* cut off number from hostname */
host_portno++;
if(*host_portno) {
- long portparse = strtol(host_portno, &endp, 10);
- if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
+ curl_off_t portparse;
+ const char *p = host_portno;
+ if(Curl_str_number(&p, &portparse, 0xffff)) {
failf(data, "No valid port number in connect to host string (%s)",
host_portno);
result = CURLE_SETOPT_OPTION_SYNTAX;
goto error;
}
- else
- port = (int)portparse; /* we know it will fit */
+ port = (int)portparse; /* we know it will fit */
}
}
@@ -2974,12 +2964,11 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data, /* check whether the URL's port matches */
char *ptr_next = strchr(ptr, ':');
if(ptr_next) {
- char *endp = NULL;
- long port_to_match = strtol(ptr, &endp, 10);
- if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
+ curl_off_t port_to_match;
+ if(!Curl_str_number(&ptr, &port_to_match, 0xffff) &&
+ (port_to_match == (curl_off_t)conn->remote_port))
port_match = TRUE;
- ptr = ptr_next + 1;
- }
+ ptr = ptr_next + 1;
}
}
}
@@ -3049,75 +3038,50 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, )) {
/* no connect_to match, try alt-svc! */
enum alpnid srcalpnid = ALPN_none;
- bool use_alt_svc = FALSE;
bool hit = FALSE;
struct altsvc *as = NULL;
- const int allowed_versions = ( ALPN_h1
-#ifdef USE_HTTP2
- | ALPN_h2
-#endif
-#ifdef USE_HTTP3
- | ALPN_h3
-#endif
- ) & data->asi->flags;
- static enum alpnid alpn_ids[] = {
-#ifdef USE_HTTP3
- ALPN_h3,
-#endif
-#ifdef USE_HTTP2
- ALPN_h2,
-#endif
- ALPN_h1,
- };
- size_t i;
-
- switch(data->state.httpwant) {
- case CURL_HTTP_VERSION_1_0:
- break;
- case CURL_HTTP_VERSION_1_1:
- use_alt_svc = TRUE;
- srcalpnid = ALPN_h1; /* only regard alt-svc advice for http/1.1 */
- break;
- case CURL_HTTP_VERSION_2_0:
- use_alt_svc = TRUE;
- srcalpnid = ALPN_h2; /* only regard alt-svc advice for h2 */
- break;
- case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
- break;
- case CURL_HTTP_VERSION_3:
- use_alt_svc = TRUE;
- srcalpnid = ALPN_h3; /* only regard alt-svc advice for h3 */
- break;
- case CURL_HTTP_VERSION_3ONLY:
- break;
- default: /* no specific HTTP version wanted, look at all of alt-svc */
- use_alt_svc = TRUE;
- srcalpnid = ALPN_none;
- break;
- }
- if(!use_alt_svc)
- return CURLE_OK;
+ int allowed_alpns = ALPN_none;
+ struct http_negotiation *neg = &data->state.http_neg;
+
+ DEBUGF(infof(data, "Alt-svc check wanted=%x, allowed=%x",
+ neg->wanted, neg->allowed));
+ if(neg->allowed & CURL_HTTP_V3x)
+ allowed_alpns |= ALPN_h3;
+ if(neg->allowed & CURL_HTTP_V2x)
+ allowed_alpns |= ALPN_h2;
+ if(neg->allowed & CURL_HTTP_V1x)
+ allowed_alpns |= ALPN_h1;
+ allowed_alpns &= (int)data->asi->flags;
host = conn->host.rawalloc;
DEBUGF(infof(data, "check Alt-Svc for host %s", host));
- if(srcalpnid == ALPN_none) {
- /* scan all alt-svc protocol ids in order or relevance */
- for(i = 0; !hit && (i < CURL_ARRAYSIZE(alpn_ids)); ++i) {
- srcalpnid = alpn_ids[i];
- hit = Curl_altsvc_lookup(data->asi,
- srcalpnid, host, conn->remote_port, /* from */
- &as /* to */,
- allowed_versions);
- }
+#ifdef USE_HTTP3
+ if(!hit && (neg->wanted & CURL_HTTP_V3x)) {
+ srcalpnid = ALPN_h3;
+ hit = Curl_altsvc_lookup(data->asi,
+ ALPN_h3, host, conn->remote_port, /* from */
+ &as /* to */,
+ allowed_alpns);
}
- else {
- /* look for a specific alt-svc protocol id */
+ #endif
+ #ifdef USE_HTTP2
+ if(!hit && (neg->wanted & CURL_HTTP_V2x) &&
+ !neg->h2_prior_knowledge) {
+ srcalpnid = ALPN_h2;
hit = Curl_altsvc_lookup(data->asi,
- srcalpnid, host, conn->remote_port, /* from */
+ ALPN_h2, host, conn->remote_port, /* from */
&as /* to */,
- allowed_versions);
+ allowed_alpns);
+ }
+ #endif
+ if(!hit && (neg->wanted & CURL_HTTP_V1x) &&
+ !neg->only_10) {
+ srcalpnid = ALPN_h1;
+ hit = Curl_altsvc_lookup(data->asi,
+ ALPN_h1, host, conn->remote_port, /* from */
+ &as /* to */,
+ allowed_alpns);
}
-
if(hit) {
char *hostd = strdup((char *)as->dst.host);
@@ -3136,14 +3100,15 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, /* protocol version switch */
switch(as->dst.alpnid) {
case ALPN_h1:
- data->state.httpwant = CURL_HTTP_VERSION_1_1;
+ neg->wanted = neg->allowed = CURL_HTTP_V1x;
+ neg->only_10 = FALSE;
break;
case ALPN_h2:
- data->state.httpwant = CURL_HTTP_VERSION_2_0;
+ neg->wanted = neg->allowed = CURL_HTTP_V2x;
break;
case ALPN_h3:
conn->transport = TRNSPRT_QUIC;
- data->state.httpwant = CURL_HTTP_VERSION_3;
+ neg->wanted = neg->allowed = CURL_HTTP_V3x;
break;
default: /* should not be possible */
break;
@@ -3273,8 +3238,8 @@ static void reuse_conn(struct Curl_easy *data, * be new for this request even when we reuse an existing connection */
if(temp->user) {
/* use the new username and password though */
- Curl_safefree(existing->user);
- Curl_safefree(existing->passwd);
+ free(existing->user);
+ free(existing->passwd);
existing->user = temp->user;
existing->passwd = temp->passwd;
temp->user = NULL;
@@ -3285,10 +3250,10 @@ static void reuse_conn(struct Curl_easy *data, existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd;
if(existing->bits.proxy_user_passwd) {
/* use the new proxy username and proxy password though */
- Curl_safefree(existing->http_proxy.user);
- Curl_safefree(existing->socks_proxy.user);
- Curl_safefree(existing->http_proxy.passwd);
- Curl_safefree(existing->socks_proxy.passwd);
+ free(existing->http_proxy.user);
+ free(existing->socks_proxy.user);
+ free(existing->http_proxy.passwd);
+ 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;
@@ -3325,8 +3290,7 @@ static void reuse_conn(struct Curl_easy *data, temp->conn_to_host.rawalloc = NULL;
existing->conn_to_port = temp->conn_to_port;
existing->remote_port = temp->remote_port;
- Curl_safefree(existing->hostname_resolve);
-
+ free(existing->hostname_resolve);
existing->hostname_resolve = temp->hostname_resolve;
temp->hostname_resolve = NULL;
@@ -3390,6 +3354,10 @@ static CURLcode create_conn(struct Curl_easy *data, any failure */
*in_connect = conn;
+ /* Do the unfailable inits first, before checks that may early return */
+ /* GSSAPI related inits */
+ Curl_sec_conn_init(conn);
+
result = parseurlandfillconn(data, conn);
if(result)
goto out;
@@ -3534,14 +3502,12 @@ static CURLcode create_conn(struct Curl_easy *data, /* Setup a "faked" transfer that will do nothing */
if(!result) {
Curl_attach_connection(data, conn);
- result = Curl_cpool_add_conn(data, conn);
- if(result)
- goto out;
+ result = Curl_cpool_add(data, conn);
+ if(!result) {
+ /* Setup whatever necessary for a resumed transfer */
+ result = setup_range(data);
+ }
- /*
- * Setup whatever necessary for a resumed transfer
- */
- result = setup_range(data);
if(result) {
DEBUGASSERT(conn->handler->done);
/* we ignore the return code for the protocol-specific DONE */
@@ -3597,18 +3563,25 @@ static CURLcode create_conn(struct Curl_easy *data, * `existing` and thus we need to cleanup the one we just
* allocated before we can move along and use `existing`.
*/
+ bool tls_upgraded = (!(conn->given->flags & PROTOPT_SSL) &&
+ Curl_conn_is_ssl(conn, FIRSTSOCKET));
+
reuse_conn(data, conn, existing);
conn = existing;
*in_connect = conn;
#ifndef CURL_DISABLE_PROXY
- infof(data, "Re-using existing connection with %s %s",
+ infof(data, "Re-using existing %s: connection%s with %s %s",
+ conn->given->scheme,
+ tls_upgraded ? " (upgraded to SSL)" : "",
conn->bits.proxy ? "proxy" : "host",
conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
conn->host.dispname);
#else
- infof(data, "Re-using existing connection with host %s",
+ infof(data, "Re-using existing %s: connection%s with host %s",
+ conn->given->scheme,
+ tls_upgraded ? " (upgraded to SSL)" : "",
conn->host.dispname);
#endif
}
@@ -3671,12 +3644,12 @@ static CURLcode create_conn(struct Curl_easy *data, }
Curl_attach_connection(data, conn);
- result = Curl_cpool_add_conn(data, conn);
+ result = Curl_cpool_add(data, conn);
if(result)
goto out;
}
-#if defined(USE_NTLM)
+#ifdef USE_NTLM
/* If NTLM is requested in a part of this connection, make sure we do not
assume the state is fine as this is a fresh connection and NTLM is
connection based. */
@@ -3762,9 +3735,6 @@ CURLcode Curl_setup_conn(struct Curl_easy *data, return result;
}
- /* set start time here for timeout purposes in the connect procedure, it
- is later set again for the progress meter purpose */
- conn->now = Curl_now();
if(!conn->bits.reuse)
result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
CURL_CF_SSL_DEFAULT);
@@ -3810,7 +3780,7 @@ CURLcode Curl_connect(struct Curl_easy *data, /* We are not allowed to return failure with memory left allocated in the
connectdata struct, free those here */
Curl_detach_connection(data);
- Curl_cpool_disconnect(data, conn, TRUE);
+ Curl_conn_terminate(data, conn, TRUE);
}
return result;
|