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
This commit is contained in:
Daniel Stenberg 2021-01-19 15:57:24 +01:00
parent d0688dcbdf
commit 6246a1d8c6
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
3 changed files with 50 additions and 36 deletions

View File

@ -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) static int doh_done(struct Curl_easy *doh, CURLcode result)
{ {
struct Curl_easy *data = doh->set.dohfor; 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! */ /* so one of the DOH request done for the 'data' transfer is now complete! */
data->req.doh.pending--; dohp->pending--;
infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending); infof(data, "a DOH request is completed, %u to go\n", dohp->pending);
if(result) if(result)
infof(data, "DOH request %s\n", curl_easy_strerror(result)); infof(data, "DOH request %s\n", curl_easy_strerror(result));
if(!data->req.doh.pending) { if(!dohp->pending) {
/* DOH completed */ /* DOH completed */
curl_slist_free_all(data->req.doh.headers); curl_slist_free_all(dohp->headers);
data->req.doh.headers = NULL; dohp->headers = NULL;
Curl_expire(data, 0, EXPIRE_RUN_NOW); Curl_expire(data, 0, EXPIRE_RUN_NOW);
} }
return 0; return 0;
@ -386,50 +387,56 @@ struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
int slot; int slot;
struct dohdata *dohp;
*waitp = TRUE; /* this never returns synchronously */ *waitp = TRUE; /* this never returns synchronously */
(void)conn; (void)conn;
(void)hostname; (void)hostname;
(void)port; (void)port;
DEBUGASSERT(!data->req.doh);
/* start clean, consider allocating this struct on demand */ /* 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; conn->bits.doh = TRUE;
data->req.doh.host = hostname; dohp->host = hostname;
data->req.doh.port = port; dohp->port = port;
data->req.doh.headers = dohp->headers =
curl_slist_append(NULL, curl_slist_append(NULL,
"Content-Type: application/dns-message"); "Content-Type: application/dns-message");
if(!data->req.doh.headers) if(!dohp->headers)
goto error; goto error;
if(conn->ip_version != CURL_IPRESOLVE_V6) { if(conn->ip_version != CURL_IPRESOLVE_V6) {
/* create IPv4 DOH request */ /* 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], DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
data->multi, data->req.doh.headers); data->multi, dohp->headers);
if(result) if(result)
goto error; goto error;
data->req.doh.pending++; dohp->pending++;
} }
if(conn->ip_version != CURL_IPRESOLVE_V4) { if(conn->ip_version != CURL_IPRESOLVE_V4) {
/* create IPv6 DOH request */ /* 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], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
data->multi, data->req.doh.headers); data->multi, dohp->headers);
if(result) if(result)
goto error; goto error;
data->req.doh.pending++; dohp->pending++;
} }
return NULL; return NULL;
error: error:
curl_slist_free_all(data->req.doh.headers); curl_slist_free_all(dohp->headers);
data->req.doh.headers = NULL; data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { 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; return NULL;
} }
@ -909,15 +916,16 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
{ {
CURLcode result; CURLcode result;
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */ *dnsp = NULL; /* defaults to no response */
if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy && if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
failf(data, "Could not DOH-resolve: %s", conn->async.hostname); failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST; CURLE_COULDNT_RESOLVE_HOST;
} }
else if(!data->req.doh.pending) { else if(!dohp->pending) {
DOHcode rc[DOH_PROBE_SLOTS] = { DOHcode rc[DOH_PROBE_SLOTS] = {
DOH_OK, DOH_OK DOH_OK, DOH_OK
}; };
@ -925,13 +933,13 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
int slot; int slot;
/* remove DOH handles from multi handle and close them */ /* remove DOH handles from multi handle and close them */
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy); curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
Curl_close(&data->req.doh.probe[slot].easy); Curl_close(&dohp->probe[slot].easy);
} }
/* parse the responses, create the struct and return it! */ /* parse the responses, create the struct and return it! */
de_init(&de); de_init(&de);
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) { 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) if(!p->dnstype)
continue; continue;
rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh), 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); Curl_dyn_free(&p->serverdoh);
if(rc[slot]) { if(rc[slot]) {
infof(data, "DOH: %s type %s for %s\n", doh_strerror(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 */ } /* next slot */
@ -951,10 +959,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns;
struct Curl_addrinfo *ai; 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); showdoh(data, &de);
ai = doh2ai(&de, data->req.doh.host, data->req.doh.port); ai = doh2ai(&de, dohp->host, dohp->port);
if(!ai) { if(!ai) {
de_cleanup(&de); de_cleanup(&de);
return CURLE_OUT_OF_MEMORY; 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); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */ /* 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) if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS); Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@ -984,9 +992,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
/* All done */ /* All done */
de_cleanup(&de); de_cleanup(&de);
Curl_safefree(data->req.doh);
return result; return result;
} /* !data->req.doh.pending */ } /* !dohp->pending */
/* else wait for pending DOH transactions to complete */ /* else wait for pending DOH transactions to complete */
return CURLE_OK; return CURLE_OK;

View File

@ -451,9 +451,12 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->state.aptr.rtsp_transport); Curl_safefree(data->state.aptr.rtsp_transport);
#ifndef CURL_DISABLE_DOH #ifndef CURL_DISABLE_DOH
Curl_dyn_free(&data->req.doh.probe[0].serverdoh); if(data->req.doh) {
Curl_dyn_free(&data->req.doh.probe[1].serverdoh); Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
curl_slist_free_all(data->req.doh.headers); Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
curl_slist_free_all(data->req.doh->headers);
Curl_safefree(data->req.doh);
}
#endif #endif
/* destruct wildcard structures if it is needed */ /* 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); Curl_safefree(data->req.newurl);
#ifndef CURL_DISABLE_DOH #ifndef CURL_DISABLE_DOH
Curl_close(&data->req.doh.probe[0].easy); if(data->req.doh) {
Curl_close(&data->req.doh.probe[1].easy); Curl_close(&data->req.doh->probe[0].easy);
Curl_close(&data->req.doh->probe[1].easy);
}
#endif #endif
} }

View File

@ -682,7 +682,7 @@ struct SingleRequest {
struct TELNET *telnet; struct TELNET *telnet;
} p; } p;
#ifndef CURL_DISABLE_DOH #ifndef CURL_DISABLE_DOH
struct dohdata doh; /* DoH specific data for this request */ struct dohdata *doh; /* DoH specific data for this request */
#endif #endif
BIT(header); /* incoming data has HTTP header */ BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */ BIT(content_range); /* set TRUE if Content-Range: was found */