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)
{
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;

View File

@ -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
}

View File

@ -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 */