diff --git a/lib/cf-https-connect.c b/lib/cf-https-connect.c index 53dae9900d..c677f12f7b 100644 --- a/lib/cf-https-connect.c +++ b/lib/cf-https-connect.c @@ -113,7 +113,6 @@ static CURLcode cf_hc_baller_cntrl(struct cf_hc_baller *b, struct cf_hc_ctx { cf_hc_state state; - const struct Curl_dns_entry *remotehost; struct curltime started; /* when connect started */ CURLcode result; /* overall result */ struct cf_hc_baller ballers[2]; @@ -147,7 +146,6 @@ static void cf_hc_baller_init(struct cf_hc_baller *b, struct Curl_easy *data, int transport) { - struct cf_hc_ctx *ctx = cf->ctx; struct Curl_cfilter *save = cf->next; cf->next = NULL; @@ -161,8 +159,8 @@ static void cf_hc_baller_init(struct cf_hc_baller *b, } if(!b->result) - b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost, - transport, CURL_CF_SSL_ENABLE); + b->result = Curl_cf_setup_insert_after(cf, data, transport, + CURL_CF_SSL_ENABLE); b->cf = cf->next; cf->next = save; } @@ -576,7 +574,6 @@ struct Curl_cftype Curl_cft_http_connect = { static CURLcode cf_hc_create(struct Curl_cfilter **pcf, struct Curl_easy *data, - const struct Curl_dns_entry *remotehost, enum alpnid *alpnids, size_t alpn_count) { struct Curl_cfilter *cf = NULL; @@ -598,7 +595,6 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf, result = CURLE_OUT_OF_MEMORY; goto out; } - ctx->remotehost = remotehost; for(i = 0; i < alpn_count; ++i) cf_hc_baller_assign(&ctx->ballers[i], alpnids[i]); for(; i < CURL_ARRAYSIZE(ctx->ballers); ++i) @@ -620,14 +616,13 @@ out: static CURLcode cf_http_connect_add(struct Curl_easy *data, struct connectdata *conn, int sockindex, - const struct Curl_dns_entry *remotehost, enum alpnid *alpn_ids, size_t alpn_count) { struct Curl_cfilter *cf; CURLcode result = CURLE_OK; DEBUGASSERT(data); - result = cf_hc_create(&cf, data, remotehost, alpn_ids, alpn_count); + result = cf_hc_create(&cf, data, alpn_ids, alpn_count); if(result) goto out; Curl_conn_cf_add(data, conn, sockindex, cf); @@ -648,8 +643,7 @@ static bool cf_https_alpns_contain(enum alpnid id, CURLcode Curl_cf_https_setup(struct Curl_easy *data, struct connectdata *conn, - int sockindex, - const struct Curl_dns_entry *remotehost) + int sockindex) { enum alpnid alpn_ids[2]; size_t alpn_count = 0; @@ -657,7 +651,6 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, struct Curl_cfilter cf_fake, *cf = NULL; (void)sockindex; - (void)remotehost; /* we want to log for the filter before we create it, fake it. */ memset(&cf_fake, 0, sizeof(cf_fake)); cf_fake.cft = &Curl_cft_http_connect; @@ -669,7 +662,8 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, * We are here after having selected a connection to a host+port and * can no longer change that. Any HTTPSRR advice for other hosts and ports * we need to ignore. */ - struct Curl_https_rrinfo *rr = remotehost ? remotehost->hinfo : NULL; + struct Curl_dns_entry *dns = data->state.dns[sockindex]; + struct Curl_https_rrinfo *rr = dns ? dns->hinfo : NULL; if(rr && !rr->no_def_alpn && /* ALPNs are defaults */ (!rr->target || /* for same host */ !rr->target[0] || @@ -739,8 +733,7 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, /* If we identified ALPNs to use, install our filter. Otherwise, * install nothing, so our call will use a default connect setup. */ if(alpn_count) { - result = cf_http_connect_add(data, conn, sockindex, remotehost, - alpn_ids, alpn_count); + result = cf_http_connect_add(data, conn, sockindex, alpn_ids, alpn_count); } out: diff --git a/lib/cf-https-connect.h b/lib/cf-https-connect.h index 4ff9ef8d37..c36726f0a2 100644 --- a/lib/cf-https-connect.h +++ b/lib/cf-https-connect.h @@ -38,20 +38,17 @@ extern struct Curl_cftype Curl_cft_http_connect; CURLcode Curl_cf_http_connect_add(struct Curl_easy *data, struct connectdata *conn, int sockindex, - const struct Curl_dns_entry *remotehost, bool try_h3, bool try_h21); CURLcode Curl_cf_http_connect_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - const struct Curl_dns_entry *remotehost, bool try_h3, bool try_h21); CURLcode Curl_cf_https_setup(struct Curl_easy *data, struct connectdata *conn, - int sockindex, - const struct Curl_dns_entry *remotehost); + int sockindex); #endif /* !defined(CURL_DISABLE_HTTP) */ diff --git a/lib/connect.c b/lib/connect.c index 2ae87bc0c1..1dcdde3fc5 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -408,7 +408,6 @@ typedef enum { struct cf_he_ctx { int transport; cf_ip_connect_create *cf_create; - const struct Curl_dns_entry *remotehost; cf_connect_state state; struct eyeballer *baller[2]; struct eyeballer *winner; @@ -782,8 +781,7 @@ evaluate: * There might be more than one IP address to try out. */ static CURLcode start_connect(struct Curl_cfilter *cf, - struct Curl_easy *data, - const struct Curl_dns_entry *remotehost) + struct Curl_easy *data) { struct cf_he_ctx *ctx = cf->ctx; struct connectdata *conn = cf->conn; @@ -791,6 +789,10 @@ static CURLcode start_connect(struct Curl_cfilter *cf, int ai_family0 = 0, ai_family1 = 0; timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); const struct Curl_addrinfo *addr0 = NULL, *addr1 = NULL; + struct Curl_dns_entry *dns = data->state.dns[cf->sockindex]; + + if(!dns) + return CURLE_FAILED_INIT; if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ @@ -800,7 +802,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf, ctx->started = curlx_now(); - /* remotehost->addr is the list of addresses from the resolver, each + /* dns->addr is the list of addresses from the resolver, each * with an address family. The list has at least one entry, possibly * many more. * We try at most 2 at a time, until we either get a connection or @@ -812,27 +814,27 @@ static CURLcode start_connect(struct Curl_cfilter *cf, if(conn->ip_version == CURL_IPRESOLVE_V6) { #ifdef USE_IPV6 ai_family0 = AF_INET6; - addr0 = addr_first_match(remotehost->addr, ai_family0); + addr0 = addr_first_match(dns->addr, ai_family0); #endif } else if(conn->ip_version == CURL_IPRESOLVE_V4) { ai_family0 = AF_INET; - addr0 = addr_first_match(remotehost->addr, ai_family0); + addr0 = addr_first_match(dns->addr, ai_family0); } else { /* no user preference, we try ipv6 always first when available */ #ifdef USE_IPV6 ai_family0 = AF_INET6; - addr0 = addr_first_match(remotehost->addr, ai_family0); + addr0 = addr_first_match(dns->addr, ai_family0); #endif /* next candidate is ipv4 */ ai_family1 = AF_INET; - addr1 = addr_first_match(remotehost->addr, ai_family1); + addr1 = addr_first_match(dns->addr, ai_family1); /* no ip address families, probably AF_UNIX or something, use the * address family given to us */ - if(!addr1 && !addr0 && remotehost->addr) { - ai_family0 = remotehost->addr->ai_family; - addr0 = addr_first_match(remotehost->addr, ai_family0); + if(!addr1 && !addr0 && dns->addr) { + ai_family0 = dns->addr->ai_family; + addr0 = addr_first_match(dns->addr, ai_family0); } } @@ -966,7 +968,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf, case SCFST_INIT: DEBUGASSERT(CURL_SOCKET_BAD == Curl_conn_cf_get_socket(cf, data)); DEBUGASSERT(!cf->connected); - result = start_connect(cf, data, ctx->remotehost); + result = start_connect(cf, data); if(result) return result; ctx->state = SCFST_WAITING; @@ -1158,7 +1160,6 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, cf_ip_connect_create *cf_create, - const struct Curl_dns_entry *remotehost, int transport) { struct cf_he_ctx *ctx = NULL; @@ -1174,14 +1175,13 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf, } ctx->transport = transport; ctx->cf_create = cf_create; - ctx->remotehost = remotehost; result = Curl_cf_create(pcf, &Curl_cft_happy_eyeballs, ctx); out: if(result) { Curl_safefree(*pcf); - Curl_safefree(ctx); + free(ctx); } return result; } @@ -1220,7 +1220,6 @@ static cf_ip_connect_create *get_cf_create(int transport) static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - const struct Curl_dns_entry *remotehost, int transport) { cf_ip_connect_create *cf_create; @@ -1235,8 +1234,7 @@ static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at, return CURLE_UNSUPPORTED_PROTOCOL; } result = cf_happy_eyeballs_create(&cf, data, cf_at->conn, - cf_create, remotehost, - transport); + cf_create, transport); if(result) return result; @@ -1256,7 +1254,6 @@ typedef enum { struct cf_setup_ctx { cf_setup_state state; - const struct Curl_dns_entry *remotehost; int ssl_mode; int transport; }; @@ -1267,6 +1264,7 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf, { struct cf_setup_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; + struct Curl_dns_entry *dns = data->state.dns[cf->sockindex]; if(cf->connected) { *done = TRUE; @@ -1275,6 +1273,9 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf, /* connect current sub-chain */ connect_sub_chain: + if(!dns) + return CURLE_FAILED_INIT; + if(cf->next && !cf->next->connected) { result = Curl_conn_cf_connect(cf->next, data, done); if(result || !*done) @@ -1282,7 +1283,7 @@ connect_sub_chain: } if(ctx->state < CF_SETUP_CNNCT_EYEBALLS) { - result = cf_he_insert_after(cf, data, ctx->remotehost, ctx->transport); + result = cf_he_insert_after(cf, data, ctx->transport); if(result) return result; ctx->state = CF_SETUP_CNNCT_EYEBALLS; @@ -1410,7 +1411,6 @@ struct Curl_cftype Curl_cft_setup = { static CURLcode cf_setup_create(struct Curl_cfilter **pcf, struct Curl_easy *data, - const struct Curl_dns_entry *remotehost, int transport, int ssl_mode) { @@ -1425,7 +1425,6 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, goto out; } ctx->state = CF_SETUP_INIT; - ctx->remotehost = remotehost; ctx->ssl_mode = ssl_mode; ctx->transport = transport; @@ -1436,14 +1435,15 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, out: *pcf = result ? NULL : cf; - free(ctx); + if(ctx) { + free(ctx); + } return result; } static CURLcode cf_setup_add(struct Curl_easy *data, struct connectdata *conn, int sockindex, - const struct Curl_dns_entry *remotehost, int transport, int ssl_mode) { @@ -1451,7 +1451,7 @@ static CURLcode cf_setup_add(struct Curl_easy *data, CURLcode result = CURLE_OK; DEBUGASSERT(data); - result = cf_setup_create(&cf, data, remotehost, transport, ssl_mode); + result = cf_setup_create(&cf, data, transport, ssl_mode); if(result) goto out; Curl_conn_cf_add(data, conn, sockindex, cf); @@ -1476,7 +1476,6 @@ void Curl_debug_set_transport_provider(int transport, CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - const struct Curl_dns_entry *remotehost, int transport, int ssl_mode) { @@ -1484,7 +1483,7 @@ CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at, CURLcode result; DEBUGASSERT(data); - result = cf_setup_create(&cf, data, remotehost, transport, ssl_mode); + result = cf_setup_create(&cf, data, transport, ssl_mode); if(result) goto out; Curl_conn_cf_insert_after(cf_at, cf); @@ -1495,19 +1494,23 @@ out: CURLcode Curl_conn_setup(struct Curl_easy *data, struct connectdata *conn, int sockindex, - const struct Curl_dns_entry *remotehost, + struct Curl_dns_entry *dns, int ssl_mode) { CURLcode result = CURLE_OK; DEBUGASSERT(data); DEBUGASSERT(conn->handler); + DEBUGASSERT(dns); + + Curl_resolv_unlink(data, &data->state.dns[sockindex]); + data->state.dns[sockindex] = dns; #if !defined(CURL_DISABLE_HTTP) if(!conn->cfilter[sockindex] && conn->handler->protocol == CURLPROTO_HTTPS) { DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE); - result = Curl_cf_https_setup(data, conn, sockindex, remotehost); + result = Curl_cf_https_setup(data, conn, sockindex); if(result) goto out; } @@ -1515,13 +1518,14 @@ CURLcode Curl_conn_setup(struct Curl_easy *data, /* Still no cfilter set, apply default. */ if(!conn->cfilter[sockindex]) { - result = cf_setup_add(data, conn, sockindex, remotehost, - conn->transport, ssl_mode); + result = cf_setup_add(data, conn, sockindex, conn->transport, ssl_mode); if(result) goto out; } DEBUGASSERT(conn->cfilter[sockindex]); out: + if(result) + Curl_resolv_unlink(data, &data->state.dns[sockindex]); return result; } diff --git a/lib/connect.h b/lib/connect.h index 81391aa430..120338eb99 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -126,7 +126,6 @@ typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf, CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - const struct Curl_dns_entry *remotehost, int transport, int ssl_mode); @@ -138,7 +137,7 @@ CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at, CURLcode Curl_conn_setup(struct Curl_easy *data, struct connectdata *conn, int sockindex, - const struct Curl_dns_entry *remotehost, + struct Curl_dns_entry *dns, int ssl_mode); extern struct Curl_cftype Curl_cft_happy_eyeballs; diff --git a/lib/cshutdn.c b/lib/cshutdn.c index 46c93689f6..f05b87d277 100644 --- a/lib/cshutdn.c +++ b/lib/cshutdn.c @@ -53,8 +53,6 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data, struct connectdata *conn) { if(!conn->bits.shutdown_handler) { - if(conn->dns_entry) - Curl_resolv_unlink(data, &conn->dns_entry); /* Cleanup NTLM connection-related data */ Curl_http_auth_cleanup_ntlm(conn); diff --git a/lib/easy.c b/lib/easy.c index 4dab47284a..9d824244e9 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -1084,8 +1084,10 @@ void curl_easy_reset(CURL *d) /* clear all meta data */ Curl_meta_reset(data); - /* clear any async resolve data */ + /* clear any resolve data */ Curl_async_shutdown(data); + Curl_resolv_unlink(data, &data->state.dns[0]); + Curl_resolv_unlink(data, &data->state.dns[1]); /* zero out UserDefined data: */ Curl_freeset(data); memset(&data->set, 0, sizeof(struct UserDefined)); diff --git a/lib/ftp.c b/lib/ftp.c index b47406f8c2..e28236da01 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -1941,7 +1941,6 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE); if(result) { - Curl_resolv_unlink(data, &dns); /* we are done using this dns entry */ if(ftpc->count1 == 0 && ftpcode == 229) return ftp_epsv_disable(data, ftpc, conn); @@ -1959,8 +1958,6 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, /* this just dumps information about this second connection */ ftp_pasv_verbose(data, dns->addr, ftpc->newhost, connectport); - Curl_resolv_unlink(data, &dns); /* we are done using this address */ - free(conn->secondaryhostname); conn->secondary_port = ftpc->newport; conn->secondaryhostname = strdup(ftpc->newhost); diff --git a/lib/hostip.c b/lib/hostip.c index 6cb695f3c4..ca6724ed55 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -1534,19 +1534,21 @@ int Curl_resolv_getsock(struct Curl_easy *data, Note: this function disconnects and frees the conn data in case of resolve failure */ -CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done) +CURLcode Curl_once_resolved(struct Curl_easy *data, + struct Curl_dns_entry *dns, + bool *protocol_done) { CURLcode result; struct connectdata *conn = data->conn; #ifdef USE_CURL_ASYNC if(data->state.async.dns) { - conn->dns_entry = data->state.async.dns; + DEBUGASSERT(data->state.async.dns == dns); data->state.async.dns = NULL; } #endif - result = Curl_setup_conn(data, protocol_done); + result = Curl_setup_conn(data, dns, protocol_done); if(result) { Curl_detach_connection(data); diff --git a/lib/hostip.h b/lib/hostip.h index 4b652c87a0..cd3d957e1e 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -133,7 +133,9 @@ void Curl_dnscache_prune(struct Curl_easy *data); /* IPv4 threadsafe resolve function used for synch and asynch builds */ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); -CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect); +CURLcode Curl_once_resolved(struct Curl_easy *data, + struct Curl_dns_entry *dns, + bool *protocol_connect); /* * Curl_printable_address() returns a printable version of the 1st address diff --git a/lib/multi.c b/lib/multi.c index f71d7a88f3..79c8975e4b 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -521,8 +521,8 @@ static void multi_done_locked(struct connectdata *conn, data->state.done = TRUE; /* called just now! */ data->state.recent_conn_id = conn->connection_id; - if(conn->dns_entry) - Curl_resolv_unlink(data, &conn->dns_entry); /* done with this */ + Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */ + Curl_resolv_unlink(data, &data->state.dns[1]); Curl_dnscache_prune(data); /* if data->set.reuse_forbid is TRUE, it means the libcurl client has @@ -2165,7 +2165,7 @@ static CURLMcode state_resolving(struct Curl_multi *multi, bool connected; /* Perform the next step in the connection phase, and then move on to the WAITCONNECT state */ - result = Curl_once_resolved(data, &connected); + result = Curl_once_resolved(data, dns, &connected); if(result) /* if Curl_once_resolved() returns failure, the connection struct is diff --git a/lib/setopt.c b/lib/setopt.c index efa604e040..61153f3f92 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -45,6 +45,7 @@ #include "vtls/vtls.h" #include "curlx/warnless.h" #include "sendf.h" +#include "hostip.h" #include "http2.h" #include "setopt.h" #include "multiif.h" @@ -1602,6 +1603,10 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, if(data->psl == &data->share->psl) data->psl = data->multi ? &data->multi->psl : NULL; #endif + if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) { + Curl_resolv_unlink(data, &data->state.dns[0]); + Curl_resolv_unlink(data, &data->state.dns[1]); + } data->share->dirty--; diff --git a/lib/url.c b/lib/url.c index aac9c2e84f..1a95267ab2 100644 --- a/lib/url.c +++ b/lib/url.c @@ -291,7 +291,10 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->info.contenttype); Curl_safefree(data->info.wouldredirect); + /* release any resolve information this transfer kept */ Curl_async_destroy(data); + Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */ + Curl_resolv_unlink(data, &data->state.dns[1]); data_priority_cleanup(data); @@ -3143,13 +3146,14 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, #ifdef USE_UNIX_SOCKETS static CURLcode resolve_unix(struct Curl_easy *data, struct connectdata *conn, - char *unix_path) + char *unix_path, + struct Curl_dns_entry **pdns) { - struct Curl_dns_entry *hostaddr = NULL; + struct Curl_dns_entry *hostaddr; bool longpath = FALSE; DEBUGASSERT(unix_path); - DEBUGASSERT(conn->dns_entry == NULL); + *pdns = NULL; /* Unix domain sockets are local. The host gets ignored, just use the * specified domain socket address. Do not cache "DNS entries". There is @@ -3169,7 +3173,7 @@ static CURLcode resolve_unix(struct Curl_easy *data, } hostaddr->refcount = 1; /* connection is the only one holding this */ - conn->dns_entry = hostaddr; + *pdns = hostaddr; return CURLE_OK; } #endif @@ -3179,31 +3183,35 @@ static CURLcode resolve_unix(struct Curl_easy *data, *************************************************************/ static CURLcode resolve_server(struct Curl_easy *data, struct connectdata *conn, - bool *async) + bool *async, + struct Curl_dns_entry **pdns) { struct hostname *ehost; timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); const char *peertype = "host"; CURLcode result; + + *pdns = NULL; + #ifdef USE_UNIX_SOCKETS - char *unix_path = conn->unix_domain_socket; + { + char *unix_path = conn->unix_domain_socket; #ifndef CURL_DISABLE_PROXY - if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name && - !strncmp(UNIX_SOCKET_PREFIX"/", - conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) - unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; + if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name && + !strncmp(UNIX_SOCKET_PREFIX"/", + conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) + unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; #endif - if(unix_path) { - /* This only works if previous transport is TRNSPRT_TCP. Check it? */ - conn->transport = TRNSPRT_UNIX; - return resolve_unix(data, conn, unix_path); + if(unix_path) { + /* This only works if previous transport is TRNSPRT_TCP. Check it? */ + conn->transport = TRNSPRT_UNIX; + return resolve_unix(data, conn, unix_path, pdns); + } } #endif - DEBUGASSERT(conn->dns_entry == NULL); - #ifndef CURL_DISABLE_PROXY if(CONN_IS_PROXIED(conn)) { ehost = conn->bits.socksproxy ? &conn->socks_proxy.host : @@ -3227,9 +3235,9 @@ static CURLcode resolve_server(struct Curl_easy *data, result = Curl_resolv_timeout(data, conn->hostname_resolve, conn->primary.remote_port, conn->ip_version, - &conn->dns_entry, timeout_ms); + pdns, timeout_ms); + DEBUGASSERT(!result || !*pdns); if(result == CURLE_AGAIN) { - DEBUGASSERT(!conn->dns_entry); *async = TRUE; return CURLE_OK; } @@ -3243,7 +3251,7 @@ static CURLcode resolve_server(struct Curl_easy *data, failf(data, "Could not resolve %s: %s", peertype, ehost->dispname); return result; } - DEBUGASSERT(conn->dns_entry); + DEBUGASSERT(*pdns); return CURLE_OK; } @@ -3348,7 +3356,7 @@ static void conn_meta_freeentry(void *p) static CURLcode create_conn(struct Curl_easy *data, struct connectdata **in_connect, - bool *async) + bool *reusedp) { CURLcode result = CURLE_OK; struct connectdata *conn; @@ -3358,7 +3366,7 @@ static CURLcode create_conn(struct Curl_easy *data, bool force_reuse = FALSE; bool waitpipe = FALSE; - *async = FALSE; + *reusedp = FALSE; *in_connect = NULL; /************************************************************* @@ -3718,15 +3726,7 @@ static CURLcode create_conn(struct Curl_easy *data, /* We are reusing the connection - no need to resolve anything, and idnconvert_hostname() was called already in create_conn() for the reuse case. */ - *async = FALSE; - } - else { - /************************************************************* - * Resolve the address of the server or proxy - *************************************************************/ - result = resolve_server(data, conn, async); - if(result) - goto out; + *reusedp = TRUE; } /* persist the scheme and handler the transfer is using */ @@ -3755,21 +3755,17 @@ out: * Curl_setup_conn() also handles reused connections */ CURLcode Curl_setup_conn(struct Curl_easy *data, + struct Curl_dns_entry *dns, bool *protocol_done) { CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; + DEBUGASSERT(dns); Curl_pgrsTime(data, TIMER_NAMELOOKUP); - if(conn->handler->flags & PROTOPT_NONETWORK) { - /* nothing to setup when not using a network */ - *protocol_done = TRUE; - return result; - } - if(!conn->bits.reuse) - result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry, + result = Curl_conn_setup(data, conn, FIRSTSOCKET, dns, CURL_CF_SSL_DEFAULT); if(!result) result = Curl_headers_init(data); @@ -3785,31 +3781,52 @@ 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; /* 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, asyncp); + result = create_conn(data, &conn, &reused); + + if(result == CURLE_NO_CONNECTION_AVAILABLE) { + DEBUGASSERT(!conn); + return result; + } if(!result) { - if(CONN_ATTACHED(conn) > 1) - /* multiplexed */ + DEBUGASSERT(conn); + if(reused) { + if(CONN_ATTACHED(conn) > 1) + /* multiplexed */ + *protocol_done = TRUE; + } + else if(conn->handler->flags & PROTOPT_NONETWORK) { + *asyncp = FALSE; + Curl_pgrsTime(data, TIMER_NAMELOOKUP); *protocol_done = TRUE; - else if(!*asyncp) { - /* DNS resolution is done: that is either because this is a reused - connection, in which case DNS was unnecessary, or because DNS - really did finish already (synch resolver/fast async resolve) */ - result = Curl_setup_conn(data, protocol_done); + } + else { + /************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ + struct Curl_dns_entry *dns; + result = resolve_server(data, conn, asyncp, &dns); + if(!result) { + *asyncp = !dns; + if(dns) + /* DNS resolution is done: that is either because this is a reused + connection, in which case DNS was unnecessary, or because DNS + really did finish already (synch resolver/fast async resolve) */ + result = Curl_setup_conn(data, dns, protocol_done); + } } } - if(result == CURLE_NO_CONNECTION_AVAILABLE) { - return result; - } - else if(result && conn) { + if(result && conn) { /* We are not allowed to return failure with memory left allocated in the connectdata struct, free those here */ Curl_detach_connection(data); diff --git a/lib/url.h b/lib/url.h index 76a935ecee..7aba98dbb9 100644 --- a/lib/url.h +++ b/lib/url.h @@ -38,6 +38,7 @@ CURLcode Curl_uc_to_curlcode(CURLUcode uc); CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */ CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect); CURLcode Curl_setup_conn(struct Curl_easy *data, + struct Curl_dns_entry *dns, bool *protocol_done); void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn); CURLcode Curl_parse_login_details(const char *login, const size_t len, diff --git a/lib/urldata.h b/lib/urldata.h index 9cba2c25b1..96af33dced 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -753,12 +753,6 @@ struct connectdata { * the connection is cleaned up (see Curl_hash_add2()).*/ struct Curl_hash meta_hash; - /* 'dns_entry' is the particular host we use. This points to an entry in the - DNS cache and it will not get pruned while locked. It gets unlocked in - multi_done(). This entry will be NULL if the connection is reused as then - there is no name resolve done. */ - struct Curl_dns_entry *dns_entry; - /* 'remote_addr' is the particular IP we connected to. it is owned, set * and NULLed by the connected socket filter (if there is one). */ const struct Curl_sockaddr_ex *remote_addr; @@ -1150,6 +1144,8 @@ struct UrlState { #endif struct auth authhost; /* auth details for host */ struct auth authproxy; /* auth details for proxy */ + + struct Curl_dns_entry *dns[2]; /* DNS to connect FIRST/SECONDARY */ #ifdef USE_CURL_ASYNC struct Curl_async async; /* asynchronous name resolver data */ #endif