From 6246a1d8c6776a60f266f1906f0ef9048e9e1069 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 19 Jan 2021 15:57:24 +0100 Subject: [PATCH] doh: allocate state struct on demand ... instead of having it static within the Curl_easy struct. This takes away 1176 bytes (18%) from the Curl_easy struct that aren't used very often and instead makes the code allocate it when needed. Closes #6492 --- lib/doh.c | 69 +++++++++++++++++++++++++++++---------------------- lib/url.c | 15 +++++++---- lib/urldata.h | 2 +- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/lib/doh.c b/lib/doh.c index c6377fef4c..f9feabacc0 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -190,16 +190,17 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp) static int doh_done(struct Curl_easy *doh, CURLcode result) { struct Curl_easy *data = doh->set.dohfor; + struct dohdata *dohp = data->req.doh; /* so one of the DOH request done for the 'data' transfer is now complete! */ - data->req.doh.pending--; - infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending); + dohp->pending--; + infof(data, "a DOH request is completed, %u to go\n", dohp->pending); if(result) infof(data, "DOH request %s\n", curl_easy_strerror(result)); - if(!data->req.doh.pending) { + if(!dohp->pending) { /* DOH completed */ - curl_slist_free_all(data->req.doh.headers); - data->req.doh.headers = NULL; + curl_slist_free_all(dohp->headers); + dohp->headers = NULL; Curl_expire(data, 0, EXPIRE_RUN_NOW); } return 0; @@ -386,50 +387,56 @@ struct Curl_addrinfo *Curl_doh(struct connectdata *conn, struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; int slot; + struct dohdata *dohp; *waitp = TRUE; /* this never returns synchronously */ (void)conn; (void)hostname; (void)port; + DEBUGASSERT(!data->req.doh); + /* start clean, consider allocating this struct on demand */ - memset(&data->req.doh, 0, sizeof(struct dohdata)); + dohp = data->req.doh = calloc(sizeof(struct dohdata), 1); + if(!dohp) + return NULL; conn->bits.doh = TRUE; - data->req.doh.host = hostname; - data->req.doh.port = port; - data->req.doh.headers = + dohp->host = hostname; + dohp->port = port; + dohp->headers = curl_slist_append(NULL, "Content-Type: application/dns-message"); - if(!data->req.doh.headers) + if(!dohp->headers) goto error; if(conn->ip_version != CURL_IPRESOLVE_V6) { /* create IPv4 DOH request */ - result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4], + result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4], DNS_TYPE_A, hostname, data->set.str[STRING_DOH], - data->multi, data->req.doh.headers); + data->multi, dohp->headers); if(result) goto error; - data->req.doh.pending++; + dohp->pending++; } if(conn->ip_version != CURL_IPRESOLVE_V4) { /* create IPv6 DOH request */ - result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6], + result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH], - data->multi, data->req.doh.headers); + data->multi, dohp->headers); if(result) goto error; - data->req.doh.pending++; + dohp->pending++; } return NULL; error: - curl_slist_free_all(data->req.doh.headers); - data->req.doh.headers = NULL; + curl_slist_free_all(dohp->headers); + data->req.doh->headers = NULL; for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - Curl_close(&data->req.doh.probe[slot].easy); + Curl_close(&dohp->probe[slot].easy); } + Curl_safefree(data->req.doh); return NULL; } @@ -909,15 +916,16 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, { CURLcode result; struct Curl_easy *data = conn->data; + struct dohdata *dohp = data->req.doh; *dnsp = NULL; /* defaults to no response */ - if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy && - !data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { + if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy && + !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { failf(data, "Could not DOH-resolve: %s", conn->async.hostname); return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: CURLE_COULDNT_RESOLVE_HOST; } - else if(!data->req.doh.pending) { + else if(!dohp->pending) { DOHcode rc[DOH_PROBE_SLOTS] = { DOH_OK, DOH_OK }; @@ -925,13 +933,13 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, int slot; /* remove DOH handles from multi handle and close them */ for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy); - Curl_close(&data->req.doh.probe[slot].easy); + curl_multi_remove_handle(data->multi, dohp->probe[slot].easy); + Curl_close(&dohp->probe[slot].easy); } /* parse the responses, create the struct and return it! */ de_init(&de); for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { - struct dnsprobe *p = &data->req.doh.probe[slot]; + struct dnsprobe *p = &dohp->probe[slot]; if(!p->dnstype) continue; rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh), @@ -941,7 +949,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, Curl_dyn_free(&p->serverdoh); if(rc[slot]) { infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]), - type2name(p->dnstype), data->req.doh.host); + type2name(p->dnstype), dohp->host); } } /* next slot */ @@ -951,10 +959,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, struct Curl_dns_entry *dns; struct Curl_addrinfo *ai; - infof(data, "DOH Host name: %s\n", data->req.doh.host); + infof(data, "DOH Host name: %s\n", dohp->host); showdoh(data, &de); - ai = doh2ai(&de, data->req.doh.host, data->req.doh.port); + ai = doh2ai(&de, dohp->host, dohp->port); if(!ai) { de_cleanup(&de); return CURLE_OUT_OF_MEMORY; @@ -964,7 +972,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* we got a response, store it in the cache */ - dns = Curl_cache_addr(data, ai, data->req.doh.host, data->req.doh.port); + dns = Curl_cache_addr(data, ai, dohp->host, dohp->port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); @@ -984,9 +992,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, /* All done */ de_cleanup(&de); + Curl_safefree(data->req.doh); return result; - } /* !data->req.doh.pending */ + } /* !dohp->pending */ /* else wait for pending DOH transactions to complete */ return CURLE_OK; diff --git a/lib/url.c b/lib/url.c index 4a145b028e..fe6c9a1f27 100644 --- a/lib/url.c +++ b/lib/url.c @@ -451,9 +451,12 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->state.aptr.rtsp_transport); #ifndef CURL_DISABLE_DOH - Curl_dyn_free(&data->req.doh.probe[0].serverdoh); - Curl_dyn_free(&data->req.doh.probe[1].serverdoh); - curl_slist_free_all(data->req.doh.headers); + if(data->req.doh) { + Curl_dyn_free(&data->req.doh->probe[0].serverdoh); + Curl_dyn_free(&data->req.doh->probe[1].serverdoh); + curl_slist_free_all(data->req.doh->headers); + Curl_safefree(data->req.doh); + } #endif /* destruct wildcard structures if it is needed */ @@ -2138,8 +2141,10 @@ void Curl_free_request_state(struct Curl_easy *data) Curl_safefree(data->req.newurl); #ifndef CURL_DISABLE_DOH - Curl_close(&data->req.doh.probe[0].easy); - Curl_close(&data->req.doh.probe[1].easy); + if(data->req.doh) { + Curl_close(&data->req.doh->probe[0].easy); + Curl_close(&data->req.doh->probe[1].easy); + } #endif } diff --git a/lib/urldata.h b/lib/urldata.h index 0038e580aa..f482f1c8a1 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -682,7 +682,7 @@ struct SingleRequest { struct TELNET *telnet; } p; #ifndef CURL_DISABLE_DOH - struct dohdata doh; /* DoH specific data for this request */ + struct dohdata *doh; /* DoH specific data for this request */ #endif BIT(header); /* incoming data has HTTP header */ BIT(content_range); /* set TRUE if Content-Range: was found */