diff options
author | Brad King <brad.king@kitware.com> | 2023-12-15 14:33:20 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2023-12-15 14:33:31 (GMT) |
commit | 6a67f71b57cef80f51bd225049198e80f325846b (patch) | |
tree | e6f7ee9569a7dcd1216d79423bb99bce036c5777 /Utilities/cmcurl/lib/url.c | |
parent | 673e6b3f3327d663542ad3faf2c0b430f7b10da2 (diff) | |
parent | fe2fe52c86105b9a22f14fd2c9605b6de3284c49 (diff) | |
download | CMake-6a67f71b57cef80f51bd225049198e80f325846b.zip CMake-6a67f71b57cef80f51bd225049198e80f325846b.tar.gz CMake-6a67f71b57cef80f51bd225049198e80f325846b.tar.bz2 |
Merge topic 'update-curl'
fe2fe52c86 curl: Set build options the way we need for CMake
548f0cfd1d Merge branch 'upstream-curl' into update-curl
fe5ffe06a9 curl 2023-12-06 (7161cb17)
38f85b8390 curl: Update script to get curl 8.5.0
Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !9069
Diffstat (limited to 'Utilities/cmcurl/lib/url.c')
-rw-r--r-- | Utilities/cmcurl/lib/url.c | 1187 |
1 files changed, 583 insertions, 604 deletions
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c index 61dad44..b81785f 100644 --- a/Utilities/cmcurl/lib/url.c +++ b/Utilities/cmcurl/lib/url.c @@ -168,130 +168,6 @@ static curl_prot_t get_protocol_family(const struct Curl_handler *h) return h->family; } - -/* - * Protocol table. Schemes (roughly) in 2019 popularity order: - * - * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP, - * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT - */ -static const struct Curl_handler * const protocols[] = { - -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_https, -#endif - -#ifndef CURL_DISABLE_HTTP - &Curl_handler_http, -#endif - -#ifdef USE_WEBSOCKETS -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_wss, -#endif - -#ifndef CURL_DISABLE_HTTP - &Curl_handler_ws, -#endif -#endif - -#ifndef CURL_DISABLE_FTP - &Curl_handler_ftp, -#endif - -#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) - &Curl_handler_ftps, -#endif - -#if defined(USE_SSH) - &Curl_handler_sftp, -#endif - -#ifndef CURL_DISABLE_FILE - &Curl_handler_file, -#endif - -#if defined(USE_SSH) && !defined(USE_WOLFSSH) - &Curl_handler_scp, -#endif - -#ifndef CURL_DISABLE_SMTP - &Curl_handler_smtp, -#ifdef USE_SSL - &Curl_handler_smtps, -#endif -#endif - -#ifndef CURL_DISABLE_LDAP - &Curl_handler_ldap, -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) - &Curl_handler_ldaps, -#endif -#endif - -#ifndef CURL_DISABLE_IMAP - &Curl_handler_imap, -#ifdef USE_SSL - &Curl_handler_imaps, -#endif -#endif - -#ifndef CURL_DISABLE_TELNET - &Curl_handler_telnet, -#endif - -#ifndef CURL_DISABLE_TFTP - &Curl_handler_tftp, -#endif - -#ifndef CURL_DISABLE_POP3 - &Curl_handler_pop3, -#ifdef USE_SSL - &Curl_handler_pop3s, -#endif -#endif - -#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (SIZEOF_CURL_OFF_T > 4) - &Curl_handler_smb, -#ifdef USE_SSL - &Curl_handler_smbs, -#endif -#endif - -#ifndef CURL_DISABLE_RTSP - &Curl_handler_rtsp, -#endif - -#ifndef CURL_DISABLE_MQTT - &Curl_handler_mqtt, -#endif - -#ifndef CURL_DISABLE_GOPHER - &Curl_handler_gopher, -#ifdef USE_SSL - &Curl_handler_gophers, -#endif -#endif - -#ifdef USE_LIBRTMP - &Curl_handler_rtmp, - &Curl_handler_rtmpt, - &Curl_handler_rtmpe, - &Curl_handler_rtmpte, - &Curl_handler_rtmps, - &Curl_handler_rtmpts, -#endif - -#ifndef CURL_DISABLE_DICT - &Curl_handler_dict, -#endif - - (struct Curl_handler *) NULL -}; - void Curl_freeset(struct Curl_easy *data) { /* Free all dynamic strings stored in the data->set substructure. */ @@ -320,8 +196,8 @@ void Curl_freeset(struct Curl_easy *data) Curl_mime_cleanpart(&data->set.mimepost); #ifndef CURL_DISABLE_COOKIES - curl_slist_free_all(data->set.cookielist); - data->set.cookielist = NULL; + curl_slist_free_all(data->state.cookielist); + data->state.cookielist = NULL; #endif } @@ -363,16 +239,18 @@ CURLcode Curl_close(struct Curl_easy **datap) /* 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_connection(data); - if(data->multi) - /* This handle is still part of a multi handle, take care of this first - and detach this handle from there. */ - curl_multi_remove_handle(data->multi, data); + if(!data->state.internal) { + if(data->multi) + /* This handle is still part of a multi handle, take care of this first + and detach this handle from there. */ + curl_multi_remove_handle(data->multi, data); - if(data->multi_easy) { - /* when curl_easy_perform() is used, it creates its own multi handle to - use and this is the one */ - curl_multi_cleanup(data->multi_easy); - data->multi_easy = NULL; + if(data->multi_easy) { + /* when curl_easy_perform() is used, it creates its own multi handle to + use and this is the one */ + curl_multi_cleanup(data->multi_easy); + data->multi_easy = NULL; + } } data->magic = 0; /* force a clear AFTER the possibly enforced removal from @@ -412,7 +290,7 @@ CURLcode Curl_close(struct Curl_easy **datap) #ifndef CURL_DISABLE_HSTS if(!data->share || !data->share->hsts) Curl_hsts_cleanup(&data->hsts); - curl_slist_free_all(data->set.hstslist); /* clean up list */ + curl_slist_free_all(data->state.hstslist); /* clean up list */ #endif #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); @@ -420,10 +298,6 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->info.contenttype); Curl_safefree(data->info.wouldredirect); - /* this destroys the channel and we cannot use it anymore after this */ - Curl_resolver_cancel(data); - Curl_resolver_cleanup(data->state.async.resolver); - data_priority_cleanup(data); /* No longer a dirty share, if it exists */ @@ -457,8 +331,8 @@ CURLcode Curl_close(struct Curl_easy **datap) } #endif - Curl_mime_cleanpart(data->state.formp); #ifndef CURL_DISABLE_HTTP + Curl_mime_cleanpart(data->state.formp); Curl_safefree(data->state.formp); #endif @@ -530,26 +404,16 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) Curl_mime_initpart(&set->mimepost); - /* - * libcurl 7.10 introduced SSL verification *by default*! This needs to be - * switched off unless wanted. - */ + Curl_ssl_easy_config_init(data); #ifndef CURL_DISABLE_DOH set->doh_verifyhost = TRUE; set->doh_verifypeer = TRUE; #endif - set->ssl.primary.verifypeer = TRUE; - set->ssl.primary.verifyhost = TRUE; #ifdef USE_SSH /* defaults to any auth type */ set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; set->new_directory_perms = 0755; /* Default permissions */ #endif - set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by - default */ -#ifndef CURL_DISABLE_PROXY - set->proxy_ssl = set->ssl; -#endif set->new_file_perms = 0644; /* Default permissions */ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL; @@ -650,13 +514,6 @@ CURLcode Curl_open(struct Curl_easy **curl) data->magic = CURLEASY_MAGIC_NUMBER; - result = Curl_resolver_init(data, &data->state.async.resolver); - if(result) { - DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); - free(data); - return result; - } - result = Curl_init_userdefined(data); if(!result) { Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER); @@ -673,7 +530,6 @@ CURLcode Curl_open(struct Curl_easy **curl) } if(result) { - Curl_resolver_cleanup(data->state.async.resolver); Curl_dyn_free(&data->state.headerb); Curl_freeset(data); free(data); @@ -707,6 +563,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_conn_cf_discard_all(data, conn, (int)i); } + Curl_resolver_cleanup(conn->resolve_async.resolver); Curl_free_idnconverted_hostname(&conn->host); Curl_free_idnconverted_hostname(&conn->conn_to_host); #ifndef CURL_DISABLE_PROXY @@ -718,7 +575,6 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->socks_proxy.passwd); Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ - Curl_free_primary_ssl_config(&conn->proxy_ssl_config); #endif Curl_safefree(conn->user); Curl_safefree(conn->passwd); @@ -733,7 +589,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->hostname_resolve); Curl_safefree(conn->secondaryhostname); Curl_safefree(conn->localdev); - Curl_free_primary_ssl_config(&conn->ssl_config); + Curl_ssl_conn_config_cleanup(conn); #ifdef USE_UNIX_SOCKETS Curl_safefree(conn->unix_domain_socket); @@ -807,6 +663,7 @@ void Curl_disconnect(struct Curl_easy *data, conn->handler->disconnect(data, conn, dead_connection); conn_shutdown(data); + Curl_resolver_cancel(data); /* detach it again */ Curl_detach_connection(data); @@ -1059,11 +916,11 @@ ConnectionExists(struct Curl_easy *data, bool *force_reuse, bool *waitpipe) { - struct connectdata *check; - struct connectdata *chosen = 0; + struct connectdata *chosen = NULL; bool foundPendingCandidate = FALSE; - bool canmultiplex = IsMultiplexingPossible(data, needle); + bool canmultiplex = FALSE; struct connectbundle *bundle; + struct Curl_llist_element *curr; #ifdef USE_NTLM bool wantNTLMhttp = ((data->state.authhost.want & @@ -1082,395 +939,368 @@ ConnectionExists(struct Curl_easy *data, bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) && (needle->handler->protocol & CURLPROTO_HTTP); + *usethis = NULL; *force_reuse = FALSE; *waitpipe = FALSE; /* Look up the bundle with all the connections to this particular host. Locks the connection cache, beware of early returns! */ bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache); - if(bundle) { - /* Max pipe length is zero (unlimited) for multiplexed connections */ - struct Curl_llist_element *curr; - - infof(data, "Found bundle for host: %p [%s]", - (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? - "can multiplex" : "serially")); - - /* We can't multiplex if we don't know anything about the server */ - if(canmultiplex) { - if(bundle->multiuse == BUNDLE_UNKNOWN) { - if(data->set.pipewait) { - infof(data, "Server doesn't support multiplex yet, wait"); - *waitpipe = TRUE; - CONNCACHE_UNLOCK(data); - return FALSE; /* no reuse */ - } - - infof(data, "Server doesn't support multiplex (yet)"); - canmultiplex = FALSE; + if(!bundle) { + CONNCACHE_UNLOCK(data); + return FALSE; + } + infof(data, "Found bundle for host: %p [%s]", + (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ? + "can multiplex" : "serially")); + + /* We can only multiplex iff the transfer allows it AND we know + * that the server we want to talk to supports it as well. */ + canmultiplex = FALSE; + if(IsMultiplexingPossible(data, needle)) { + if(bundle->multiuse == BUNDLE_UNKNOWN) { + if(data->set.pipewait) { + infof(data, "Server doesn't support multiplex yet, wait"); + *waitpipe = TRUE; + CONNCACHE_UNLOCK(data); + return FALSE; /* no reuse */ } - if((bundle->multiuse == BUNDLE_MULTIPLEX) && - !Curl_multiplex_wanted(data->multi)) { + infof(data, "Server doesn't support multiplex (yet)"); + } + else if(bundle->multiuse == BUNDLE_MULTIPLEX) { + if(Curl_multiplex_wanted(data->multi)) + canmultiplex = TRUE; + else infof(data, "Could multiplex, but not asked to"); - canmultiplex = FALSE; - } - if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { - infof(data, "Can not multiplex, even if we wanted to"); - canmultiplex = FALSE; - } } + else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) { + infof(data, "Can not multiplex, even if we wanted to"); + } + } - curr = bundle->conn_list.head; - while(curr) { - bool match = FALSE; - size_t multiplexed = 0; + curr = bundle->conn_list.head; + while(curr) { + struct connectdata *check = curr->ptr; + /* Get next node now. We might remove a dead `check` connection which + * would invalidate `curr` as well. */ + curr = curr->next; - /* - * Note that if we use an HTTP proxy in normal mode (no tunneling), we - * check connections to that proxy and not to the actual remote server. - */ - check = curr->ptr; - curr = curr->next; + /* Note that if we use an HTTP proxy in normal mode (no tunneling), we + * check connections to that proxy and not to the actual remote server. + */ + if(check->connect_only || check->bits.close) + /* connect-only or to-be-closed connections will not be reused */ + continue; - if(check->connect_only || check->bits.close) - /* connect-only or to-be-closed connections will not be reused */ - continue; + if(data->set.ipver != CURL_IPRESOLVE_WHATEVER + && data->set.ipver != check->ip_version) { + /* skip because the connection is not via the requested IP version */ + continue; + } - if(extract_if_dead(check, data)) { - /* disconnect it */ - Curl_disconnect(data, check, TRUE); + if(!canmultiplex) { + if(Curl_resolver_asynch() && + /* primary_ip[0] is NUL only if the resolving of the name hasn't + completed yet and until then we don't reuse this connection */ + !check->primary_ip[0]) continue; - } + } - if(data->set.ipver != CURL_IPRESOLVE_WHATEVER - && data->set.ipver != check->ip_version) { - /* skip because the connection is not via the requested IP version */ + if(CONN_INUSE(check)) { + if(!canmultiplex) { + /* transfer can't be multiplexed and check is in use */ continue; } - - if(bundle->multiuse == BUNDLE_MULTIPLEX) - multiplexed = CONN_INUSE(check); - - if(!canmultiplex) { - if(multiplexed) { - /* can only happen within multi handles, and means that another easy - handle is using this connection */ - continue; - } - - if(Curl_resolver_asynch() && - /* primary_ip[0] is NUL only if the resolving of the name hasn't - completed yet and until then we don't reuse this connection */ - !check->primary_ip[0]) + else { + /* Could multiplex, but not when check belongs to another multi */ + struct Curl_llist_element *e = check->easyq.head; + struct Curl_easy *entry = e->ptr; + if(entry->multi != data->multi) continue; } + } - if(!Curl_conn_is_connected(check, FIRSTSOCKET)) { - foundPendingCandidate = TRUE; - /* Don't pick a connection that hasn't connected yet */ - infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T - " isn't open enough, can't reuse", check->connection_id); - continue; - } + if(!Curl_conn_is_connected(check, FIRSTSOCKET)) { + foundPendingCandidate = TRUE; + /* Don't pick a connection that hasn't connected yet */ + infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T + " isn't open enough, can't reuse", check->connection_id); + continue; + } + + /* `check` is connected. if it is in use and does not support multiplex, + * we cannot use it. */ + if(!check->bits.multiplex && CONN_INUSE(check)) + continue; #ifdef USE_UNIX_SOCKETS - if(needle->unix_domain_socket) { - if(!check->unix_domain_socket) - continue; - if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) - continue; - if(needle->bits.abstract_unix_socket != - check->bits.abstract_unix_socket) - continue; - } - else if(check->unix_domain_socket) + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) continue; -#endif - - if((needle->handler->flags&PROTOPT_SSL) != - (check->handler->flags&PROTOPT_SSL)) - /* don't do mixed SSL and non-SSL connections */ - if(get_protocol_family(check->handler) != - needle->handler->protocol || !check->bits.tls_upgraded) - /* except protocols that have been upgraded via TLS */ - continue; - -#ifndef CURL_DISABLE_PROXY - if(needle->bits.httpproxy != check->bits.httpproxy || - needle->bits.socksproxy != check->bits.socksproxy) + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) continue; - - if(needle->bits.socksproxy && - !socks_proxy_info_matches(&needle->socks_proxy, - &check->socks_proxy)) + if(needle->bits.abstract_unix_socket != + check->bits.abstract_unix_socket) continue; + } + else if(check->unix_domain_socket) + continue; #endif - if(needle->bits.conn_to_host != check->bits.conn_to_host) - /* don't mix connections that use the "connect to host" feature and - * connections that don't use this feature */ - continue; - if(needle->bits.conn_to_port != check->bits.conn_to_port) - /* don't mix connections that use the "connect to port" feature and - * connections that don't use this feature */ + if((needle->handler->flags&PROTOPT_SSL) != + (check->handler->flags&PROTOPT_SSL)) + /* don't do mixed SSL and non-SSL connections */ + if(get_protocol_family(check->handler) != + needle->handler->protocol || !check->bits.tls_upgraded) + /* except protocols that have been upgraded via TLS */ continue; -#ifndef CURL_DISABLE_PROXY - if(needle->bits.httpproxy) { - if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) - continue; + if(needle->bits.conn_to_host != check->bits.conn_to_host) + /* don't mix connections that use the "connect to host" feature and + * connections that don't use this feature */ + continue; - if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) - continue; + if(needle->bits.conn_to_port != check->bits.conn_to_port) + /* don't mix connections that use the "connect to port" feature and + * connections that don't use this feature */ + continue; - if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { - /* use https proxy */ - if(needle->http_proxy.proxytype != - check->http_proxy.proxytype) - continue; - else if(needle->handler->flags&PROTOPT_SSL) { - /* use double layer ssl */ - if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, - &check->proxy_ssl_config)) - continue; - } - else if(!Curl_ssl_config_matches(&needle->ssl_config, - &check->ssl_config)) - continue; - } - } -#endif +#ifndef CURL_DISABLE_PROXY + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) + continue; - if(h2upgrade && !check->httpversion && canmultiplex) { - if(data->set.pipewait) { - infof(data, "Server upgrade doesn't support multiplex yet, wait"); - *waitpipe = TRUE; - CONNCACHE_UNLOCK(data); - return FALSE; /* no reuse */ - } - infof(data, "Server upgrade cannot be used"); - continue; /* can't be used atm */ - } + if(needle->bits.socksproxy && + !socks_proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) + continue; - if(!canmultiplex && CONN_INUSE(check)) - /* this request can't be multiplexed but the checked connection is - already in use so we skip it */ + if(needle->bits.httpproxy) { + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) continue; - if(CONN_INUSE(check)) { - /* Subject for multiplex use if 'checks' belongs to the same multi - handle as 'data' is. */ - struct Curl_llist_element *e = check->easyq.head; - struct Curl_easy *entry = e->ptr; - if(entry->multi != data->multi) - continue; - } + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; - if(needle->localdev || needle->localport) { - /* If we are bound to a specific local end (IP+port), we must not - reuse a random other one, although if we didn't ask for a - particular one we can reuse one that was bound. - - This comparison is a bit rough and too strict. Since the input - parameters can be specified in numerous ways and still end up the - same it would take a lot of processing to make it really accurate. - Instead, this matching will assume that reuses of bound connections - will most likely also reuse the exact same binding parameters and - missing out a few edge cases shouldn't hurt anyone very much. - */ - if((check->localport != needle->localport) || - (check->localportrange != needle->localportrange) || - (needle->localdev && - (!check->localdev || strcmp(check->localdev, needle->localdev)))) + if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) { + /* https proxies come in different types, http/1.1, h2, ... */ + if(needle->http_proxy.proxytype != check->http_proxy.proxytype) continue; - } - - if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { - /* This protocol requires credentials per connection, - so verify that we're using the same name and password as well */ - if(Curl_timestrcmp(needle->user, check->user) || - Curl_timestrcmp(needle->passwd, check->passwd) || - Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || - Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { - /* one of them was different */ + /* match SSL config to proxy */ + if(!Curl_ssl_conn_config_match(data, check, TRUE)) { + DEBUGF(infof(data, + "Connection #%" CURL_FORMAT_CURL_OFF_T + " has different SSL proxy parameters, can't reuse", + check->connection_id)); continue; } + /* the SSL config to the server, which may apply here is checked + * further below */ } + } +#endif - /* GSS delegation differences do not actually affect every connection - and auth method, but this check takes precaution before efficiency */ - if(needle->gssapi_delegation != check->gssapi_delegation) + if(h2upgrade && !check->httpversion && canmultiplex) { + if(data->set.pipewait) { + infof(data, "Server upgrade doesn't support multiplex yet, wait"); + *waitpipe = TRUE; + CONNCACHE_UNLOCK(data); + return FALSE; /* no reuse */ + } + infof(data, "Server upgrade cannot be used"); + continue; /* can't be used atm */ + } + + if(needle->localdev || needle->localport) { + /* If we are bound to a specific local end (IP+port), we must not + reuse a random other one, although if we didn't ask for a + particular one we can reuse one that was bound. + + This comparison is a bit rough and too strict. Since the input + parameters can be specified in numerous ways and still end up the + same it would take a lot of processing to make it really accurate. + Instead, this matching will assume that reuses of bound connections + will most likely also reuse the exact same binding parameters and + missing out a few edge cases shouldn't hurt anyone very much. + */ + if((check->localport != needle->localport) || + (check->localportrange != needle->localportrange) || + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) continue; + } - /* If multiplexing isn't enabled on the h2 connection and h1 is - explicitly requested, handle it: */ - if((needle->handler->protocol & PROTO_FAMILY_HTTP) && - (((check->httpversion >= 20) && - (data->state.httpwant < CURL_HTTP_VERSION_2_0)) - || ((check->httpversion >= 30) && - (data->state.httpwant < CURL_HTTP_VERSION_3)))) + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(Curl_timestrcmp(needle->user, check->user) || + Curl_timestrcmp(needle->passwd, check->passwd) || + Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || + Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ continue; -#ifdef USE_SSH - else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { - if(!ssh_config_matches(needle, check)) - continue; } + } + + /* GSS delegation differences do not actually affect every connection + and auth method, but this check takes precaution before efficiency */ + if(needle->gssapi_delegation != check->gssapi_delegation) + continue; + + /* If looking for HTTP and the HTTP version we want is less + * than the HTTP version of the check connection, continue looking */ + if((needle->handler->protocol & PROTO_FAMILY_HTTP) && + (((check->httpversion >= 20) && + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + || ((check->httpversion >= 30) && + (data->state.httpwant < CURL_HTTP_VERSION_3)))) + continue; +#ifdef USE_SSH + else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; + } #endif #ifndef CURL_DISABLE_FTP - else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { - /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ - if(Curl_timestrcmp(needle->proto.ftpc.account, - check->proto.ftpc.account) || - Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, - check->proto.ftpc.alternative_to_user) || - (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || - (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) - continue; - } + else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { + /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ + if(Curl_timestrcmp(needle->proto.ftpc.account, + check->proto.ftpc.account) || + Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, + check->proto.ftpc.alternative_to_user) || + (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || + (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) + continue; + } #endif - if((needle->handler->flags&PROTOPT_SSL) + /* Additional match requirements if talking TLS OR + * not talking to a HTTP proxy OR using a tunnel through a proxy */ + if((needle->handler->flags&PROTOPT_SSL) #ifndef CURL_DISABLE_PROXY - || !needle->bits.httpproxy || needle->bits.tunnel_proxy -#endif - ) { - /* The requested connection does not use an HTTP proxy or it uses SSL - or it is a non-SSL protocol tunneled or it is a non-SSL protocol - which is allowed to be upgraded via TLS */ - - if((strcasecompare(needle->handler->scheme, check->handler->scheme) || - (get_protocol_family(check->handler) == - needle->handler->protocol && check->bits.tls_upgraded)) && - (!needle->bits.conn_to_host || strcasecompare( - needle->conn_to_host.name, check->conn_to_host.name)) && - (!needle->bits.conn_to_port || - needle->conn_to_port == check->conn_to_port) && - strcasecompare(needle->host.name, check->host.name) && - needle->remote_port == check->remote_port) { - /* The schemes match or the protocol family is the same and the - previous connection was TLS upgraded, and the hostname and host - port match */ - if(needle->handler->flags & PROTOPT_SSL) { - /* This is a SSL connection so verify that we're using the same - SSL options as well */ - if(!Curl_ssl_config_matches(&needle->ssl_config, - &check->ssl_config)) { - DEBUGF(infof(data, - "Connection #%" CURL_FORMAT_CURL_OFF_T - " has different SSL parameters, can't reuse", - check->connection_id)); - continue; - } - } - match = TRUE; - } - } - else { - /* The requested connection is using the same HTTP proxy in normal - mode (no tunneling) */ - match = TRUE; + || !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, check->handler->scheme) && + (get_protocol_family(check->handler) != + needle->handler->protocol || !check->bits.tls_upgraded)) + continue; + + /* If needle has "conn_to_*" set, check must match this */ + if((needle->bits.conn_to_host && !strcasecompare( + needle->conn_to_host.name, check->conn_to_host.name)) || + (needle->bits.conn_to_port && + needle->conn_to_port != check->conn_to_port)) + continue; + + /* hostname and port must match */ + if(!strcasecompare(needle->host.name, check->host.name) || + needle->remote_port != check->remote_port) + continue; + + /* If talking TLS, check needs to use the same SSL options. */ + if((needle->handler->flags & PROTOPT_SSL) && + !Curl_ssl_conn_config_match(data, check, FALSE)) { + DEBUGF(infof(data, + "Connection #%" CURL_FORMAT_CURL_OFF_T + " has different SSL parameters, can't reuse", + check->connection_id)); + continue; } + } - if(match) { #if defined(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 - possible. (Especially we must not reuse the same connection if - partway through a handshake!) */ - if(wantNTLMhttp) { - if(Curl_timestrcmp(needle->user, check->user) || - Curl_timestrcmp(needle->passwd, check->passwd)) { - - /* we prefer a credential match, but this is at least a connection - that can be reused and "upgraded" to NTLM */ - if(check->http_ntlm_state == NTLMSTATE_NONE) - chosen = check; - continue; - } - } - else if(check->http_ntlm_state != NTLMSTATE_NONE) { - /* Connection is using NTLM auth but we don't want NTLM */ - continue; - } - -#ifndef CURL_DISABLE_PROXY - /* Same for Proxy NTLM authentication */ - if(wantProxyNTLMhttp) { - /* Both check->http_proxy.user and check->http_proxy.passwd can be - * NULL */ - if(!check->http_proxy.user || !check->http_proxy.passwd) - continue; - - if(Curl_timestrcmp(needle->http_proxy.user, - check->http_proxy.user) || - Curl_timestrcmp(needle->http_proxy.passwd, - check->http_proxy.passwd)) - continue; - } - else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { - /* Proxy connection is using NTLM auth but we don't want NTLM */ - continue; - } -#endif - if(wantNTLMhttp || wantProxyNTLMhttp) { - /* Credentials are already checked, we can use this connection */ + /* 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 + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { + if(Curl_timestrcmp(needle->user, check->user) || + Curl_timestrcmp(needle->passwd, check->passwd)) { + + /* we prefer a credential match, but this is at least a connection + that can be reused and "upgraded" to NTLM */ + if(check->http_ntlm_state == NTLMSTATE_NONE) chosen = check; + continue; + } + } + else if(check->http_ntlm_state != NTLMSTATE_NONE) { + /* Connection is using NTLM auth but we don't want NTLM */ + continue; + } - if((wantNTLMhttp && - (check->http_ntlm_state != NTLMSTATE_NONE)) || - (wantProxyNTLMhttp && - (check->proxy_ntlm_state != NTLMSTATE_NONE))) { - /* We must use this connection, no other */ - *force_reuse = TRUE; - break; - } +#ifndef CURL_DISABLE_PROXY + /* Same for Proxy NTLM authentication */ + if(wantProxyNTLMhttp) { + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) + continue; - /* Continue look up for a better connection */ - continue; - } + if(Curl_timestrcmp(needle->http_proxy.user, + check->http_proxy.user) || + Curl_timestrcmp(needle->http_proxy.passwd, + check->http_proxy.passwd)) + continue; + } + else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { + /* Proxy connection is using NTLM auth but we don't want NTLM */ + continue; + } +#endif + if(wantNTLMhttp || wantProxyNTLMhttp) { + /* Credentials are already checked, we may use this connection. + * With NTLM being weird as it is, we MUST use a + * connection where it has already been fully negotiated. + * If it has not, we keep on looking for a better one. */ + chosen = check; + + if((wantNTLMhttp && + (check->http_ntlm_state != NTLMSTATE_NONE)) || + (wantProxyNTLMhttp && + (check->proxy_ntlm_state != NTLMSTATE_NONE))) { + /* We must use this connection, no other */ + *force_reuse = TRUE; + break; + } + /* Continue look up for a better connection */ + continue; + } #endif - if(canmultiplex) { - /* We can multiplex if we want to. Let's continue looking for - the optimal connection to use. */ - - if(!multiplexed) { - /* We have the optimal connection. Let's stop looking. */ - chosen = check; - break; - } -#ifdef USE_NGHTTP2 - /* If multiplexed, make sure we don't go over concurrency limit */ - if(check->bits.multiplex) { - if(multiplexed >= Curl_conn_get_max_concurrent(data, check, - FIRSTSOCKET)) { - infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", - multiplexed); - continue; - } - else if(multiplexed >= - Curl_multi_max_concurrent_streams(data->multi)) { - infof(data, "client side MAX_CONCURRENT_STREAMS reached" - ", skip (%zu)", - multiplexed); - continue; - } - } -#endif - /* When not multiplexed, we have a match here! */ - chosen = check; - infof(data, "Multiplexed connection found"); - break; - } - else { - /* We have found a connection. Let's stop searching. */ - chosen = check; - break; - } + if(CONN_INUSE(check)) { + DEBUGASSERT(canmultiplex); + DEBUGASSERT(check->bits.multiplex); + /* If multiplexed, make sure we don't go over concurrency limit */ + if(CONN_INUSE(check) >= + Curl_multi_max_concurrent_streams(data->multi)) { + infof(data, "client side MAX_CONCURRENT_STREAMS reached" + ", skip (%zu)", CONN_INUSE(check)); + continue; } + if(CONN_INUSE(check) >= + Curl_conn_get_max_concurrent(data, check, FIRSTSOCKET)) { + infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)", + CONN_INUSE(check)); + continue; + } + /* When not multiplexed, we have a match here! */ + infof(data, "Multiplexed connection found"); + } + else if(extract_if_dead(check, data)) { + /* disconnect it */ + Curl_disconnect(data, check, TRUE); + continue; } - } + + /* We have found a connection. Let's stop searching. */ + chosen = check; + break; + } /* loop over connection bundle */ if(chosen) { /* mark it as used before releasing the lock */ @@ -1561,17 +1391,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; #endif - conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; - conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; - conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; - conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options; -#ifndef CURL_DISABLE_PROXY - conn->proxy_ssl_config.verifystatus = - data->set.proxy_ssl.primary.verifystatus; - conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; - conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; - conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options; -#endif conn->ip_version = data->set.ipver; conn->connect_only = data->set.connect_only; conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */ @@ -1615,30 +1434,231 @@ error: return NULL; } -/* returns the handler if the given scheme is built-in */ -const struct Curl_handler *Curl_builtin_scheme(const char *scheme, - size_t schemelen) +const struct Curl_handler *Curl_get_scheme_handler(const char *scheme) { - const struct Curl_handler * const *pp; - const struct Curl_handler *p; - /* Scan protocol handler table and match against 'scheme'. The handler may - be changed later when the protocol specific setup function is called. */ - if(schemelen == CURL_ZERO_TERMINATED) - schemelen = strlen(scheme); - for(pp = protocols; (p = *pp) != NULL; pp++) - if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen]) - /* Protocol found in table. */ - return p; - return NULL; /* not found */ + return Curl_getn_scheme_handler(scheme, strlen(scheme)); } +/* returns the handler if the given scheme is built-in */ +const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, + size_t len) +{ + /* table generated by schemetable.c: + 1. gcc schemetable.c && ./a.out + 2. check how small the table gets + 3. tweak the hash algorithm, then rerun from 1 + 4. when the table is good enough + 5. copy the table into this source code + 6. make sure this function uses the same hash function that worked for + schemetable.c + 7. if needed, adjust the #ifdefs in schemetable.c and rerun + */ + static const struct Curl_handler * const protocols[67] = { +#ifndef CURL_DISABLE_FILE + &Curl_handler_file, +#else + NULL, +#endif + NULL, NULL, +#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER) + &Curl_handler_gophers, +#else + NULL, +#endif + NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmpe, +#else + NULL, +#endif +#ifndef CURL_DISABLE_SMTP + &Curl_handler_smtp, +#else + NULL, +#endif +#if defined(USE_SSH) + &Curl_handler_sftp, +#else + NULL, +#endif +#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ + (SIZEOF_CURL_OFF_T > 4) + &Curl_handler_smb, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) + &Curl_handler_smtps, +#else + NULL, +#endif +#ifndef CURL_DISABLE_TELNET + &Curl_handler_telnet, +#else + NULL, +#endif +#ifndef CURL_DISABLE_GOPHER + &Curl_handler_gopher, +#else + NULL, +#endif +#ifndef CURL_DISABLE_TFTP + &Curl_handler_tftp, +#else + NULL, +#endif + NULL, NULL, NULL, +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + &Curl_handler_ftps, +#else + NULL, +#endif +#ifndef CURL_DISABLE_HTTP + &Curl_handler_http, +#else + NULL, +#endif +#ifndef CURL_DISABLE_IMAP + &Curl_handler_imap, +#else + NULL, +#endif +#ifdef USE_LIBRTMP + &Curl_handler_rtmps, +#else + NULL, +#endif +#ifdef USE_LIBRTMP + &Curl_handler_rtmpt, +#else + NULL, +#endif + NULL, NULL, NULL, +#if !defined(CURL_DISABLE_LDAP) && \ + !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + &Curl_handler_ldaps, +#else + NULL, +#endif +#if defined(USE_WEBSOCKETS) && \ + defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_wss, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_https, +#else + NULL, +#endif + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +#ifndef CURL_DISABLE_RTSP + &Curl_handler_rtsp, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \ + defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4) + &Curl_handler_smbs, +#else + NULL, +#endif +#if defined(USE_SSH) && !defined(USE_WOLFSSH) + &Curl_handler_scp, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifndef CURL_DISABLE_POP3 + &Curl_handler_pop3, +#else + NULL, +#endif + NULL, NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmp, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmpte, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifndef CURL_DISABLE_DICT + &Curl_handler_dict, +#else + NULL, +#endif + NULL, NULL, NULL, +#ifndef CURL_DISABLE_MQTT + &Curl_handler_mqtt, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) + &Curl_handler_pop3s, +#else + NULL, +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) + &Curl_handler_imaps, +#else + NULL, +#endif + NULL, +#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) + &Curl_handler_ws, +#else + NULL, +#endif + NULL, +#ifdef USE_LIBRTMP + &Curl_handler_rtmpts, +#else + NULL, +#endif +#ifndef CURL_DISABLE_LDAP + &Curl_handler_ldap, +#else + NULL, +#endif + NULL, NULL, +#ifndef CURL_DISABLE_FTP + &Curl_handler_ftp, +#else + NULL, +#endif + }; + + if(len && (len <= 7)) { + const char *s = scheme; + size_t l = len; + const struct Curl_handler *h; + unsigned int c = 978; + while(l) { + c <<= 5; + c += Curl_raw_tolower(*s); + s++; + l--; + } + + h = protocols[c % 67]; + if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len]) + return h; + } + return NULL; +} static CURLcode findprotocol(struct Curl_easy *data, struct connectdata *conn, const char *protostr) { - const struct Curl_handler *p = Curl_builtin_scheme(protostr, - CURL_ZERO_TERMINATED); + const struct Curl_handler *p = Curl_get_scheme_handler(protostr); if(p && /* Protocol found in table. Check if allowed */ (data->set.allowed_protocols & p->protocol)) { @@ -1652,7 +1672,6 @@ static CURLcode findprotocol(struct Curl_easy *data, else { /* Perform setup complement if some. */ conn->handler = conn->given = p; - /* 'port' and 'remote_port' are set in setup_connection_internals() */ return CURLE_OK; } @@ -1705,14 +1724,14 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, conn->scope_id = (unsigned int)scope; #if defined(HAVE_IF_NAMETOINDEX) else { -#elif defined(WIN32) +#elif defined(_WIN32) else if(Curl_if_nametoindex) { #endif -#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32) +#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32) /* Zone identifier is not numeric */ unsigned int scopeidx = 0; -#if defined(WIN32) +#if defined(_WIN32) scopeidx = Curl_if_nametoindex(zoneid); #else scopeidx = if_nametoindex(zoneid); @@ -1727,7 +1746,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, else conn->scope_id = scopeidx; } -#endif /* HAVE_IF_NAMETOINDEX || WIN32 */ +#endif /* HAVE_IF_NAMETOINDEX || _WIN32 */ free(zoneid); } @@ -3596,85 +3615,10 @@ static CURLcode create_conn(struct Curl_easy *data, conn->send[SECONDARYSOCKET] = Curl_conn_send; conn->bits.tcp_fastopen = data->set.tcp_fastopen; - /* Get a cloned copy of the SSL config situation stored in the - connection struct. But to get this going nicely, we must first make - sure that the strings in the master copy are pointing to the correct - strings in the session handle strings array! - - Keep in mind that the pointers in the master copy are pointing to strings - that will be freed as part of the Curl_easy struct, but all cloned - copies will be separately allocated. - */ - data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH]; - data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE]; - data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; - data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; - data->set.ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST]; - data->set.ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST]; - data->set.ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; - data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT]; - data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; - data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES]; - -#ifndef CURL_DISABLE_PROXY - data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; - data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; - data->set.proxy_ssl.primary.cipher_list = - data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; - data->set.proxy_ssl.primary.cipher_list13 = - data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; - data->set.proxy_ssl.primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; - data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY]; - data->set.proxy_ssl.primary.ca_info_blob = - data->set.blobs[BLOB_CAINFO_PROXY]; - data->set.proxy_ssl.primary.issuercert = - data->set.str[STRING_SSL_ISSUERCERT_PROXY]; - data->set.proxy_ssl.primary.issuercert_blob = - data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY]; - data->set.proxy_ssl.primary.CRLfile = - data->set.str[STRING_SSL_CRLFILE_PROXY]; - data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; - data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; - data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; - data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; - data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; - data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY]; -#endif - data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE]; - data->set.ssl.key = data->set.str[STRING_KEY]; - data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE]; - data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD]; - data->set.ssl.primary.clientcert = data->set.str[STRING_CERT]; -#ifdef USE_TLS_SRP - data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME]; - data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD]; -#ifndef CURL_DISABLE_PROXY - data->set.proxy_ssl.primary.username = - data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; - data->set.proxy_ssl.primary.password = - data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; -#endif -#endif - data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; - - if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, - &conn->ssl_config)) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - -#ifndef CURL_DISABLE_PROXY - if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, - &conn->proxy_ssl_config)) { - result = CURLE_OUT_OF_MEMORY; + /* Complete the easy's SSL configuration for connection cache matching */ + result = Curl_ssl_easy_config_complete(data); + if(result) goto out; - } -#endif prune_dead_connections(data); @@ -3789,7 +3733,41 @@ static CURLcode create_conn(struct Curl_easy *data, * 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(fprintf(stderr, "Error: init connection ssl config\n")); + goto out; + } + + result = Curl_resolver_init(data, &conn->resolve_async.resolver); + if(result) { + DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); + goto out; + } + Curl_attach_connection(data, conn); + +#ifdef USE_ARES + result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; + + result = Curl_set_dns_interface(data, + data->set.str[STRING_DNS_INTERFACE]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; + + result = Curl_set_dns_local_ip4(data, + data->set.str[STRING_DNS_LOCAL_IP4]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; + + result = Curl_set_dns_local_ip6(data, + data->set.str[STRING_DNS_LOCAL_IP6]); + if(result && result != CURLE_NOT_BUILT_IN) + goto out; +#endif /* USE_ARES */ + result = Curl_conncache_add_conn(data); if(result) goto out; @@ -3976,6 +3954,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) k->bytecount = 0; k->ignorebody = FALSE; + Curl_client_cleanup(data); Curl_speedinit(data); Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0); |