refactor dns_client to use loop callbacks
dns_client now uses isc_async_run() internally to post client-resume events. (a task is still used for dns_resolver_createfetch(), however.)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <isc/async.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/md.h>
|
||||
#include <isc/mem.h>
|
||||
@@ -75,10 +76,9 @@ struct dns_client {
|
||||
unsigned int magic;
|
||||
unsigned int attributes;
|
||||
isc_mem_t *mctx;
|
||||
isc_taskmgr_t *taskmgr;
|
||||
isc_task_t *task;
|
||||
isc_loop_t *loop;
|
||||
isc_nm_t *nm;
|
||||
isc_loopmgr_t *loopmgr;
|
||||
dns_dispatchmgr_t *dispatchmgr;
|
||||
dns_dispatch_t *dispatchv4;
|
||||
dns_dispatch_t *dispatchv6;
|
||||
@@ -107,7 +107,6 @@ typedef struct resctx {
|
||||
bool want_tcp;
|
||||
|
||||
ISC_LINK(struct resctx) link;
|
||||
isc_task_t *task;
|
||||
dns_view_t *view;
|
||||
unsigned int restarts;
|
||||
dns_fixedname_t name;
|
||||
@@ -115,7 +114,7 @@ typedef struct resctx {
|
||||
dns_fetch_t *fetch;
|
||||
dns_namelist_t namelist;
|
||||
isc_result_t result;
|
||||
dns_clientresume_t *event;
|
||||
dns_clientresume_t *rev;
|
||||
dns_rdataset_t *rdataset;
|
||||
dns_rdataset_t *sigrdataset;
|
||||
} resctx_t;
|
||||
@@ -265,12 +264,11 @@ dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
|
||||
|
||||
client = isc_mem_get(mctx, sizeof(*client));
|
||||
*client = (dns_client_t){
|
||||
.taskmgr = taskmgr,
|
||||
.loopmgr = loopmgr,
|
||||
.loop = isc_loop_get(loopmgr, 0),
|
||||
.nm = nm,
|
||||
};
|
||||
|
||||
result = isc_task_create(client->taskmgr, &client->task, 0);
|
||||
result = isc_task_create(taskmgr, &client->task, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_lock;
|
||||
}
|
||||
@@ -465,9 +463,8 @@ fetch_done(isc_task_t *task, isc_event_t *event) {
|
||||
resctx_t *rctx = event->ev_arg;
|
||||
dns_fetchevent_t *fevent;
|
||||
|
||||
REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
|
||||
REQUIRE(RCTX_VALID(rctx));
|
||||
REQUIRE(rctx->task == task);
|
||||
REQUIRE(rctx->client->task == task);
|
||||
fevent = (dns_fetchevent_t *)event;
|
||||
|
||||
client_resfind(rctx, fevent);
|
||||
@@ -497,8 +494,8 @@ start_fetch(resctx_t *rctx) {
|
||||
result = dns_resolver_createfetch(
|
||||
rctx->view->resolver, dns_fixedname_name(&rctx->name),
|
||||
rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL,
|
||||
rctx->task, fetch_done, rctx, rctx->rdataset, rctx->sigrdataset,
|
||||
&rctx->fetch);
|
||||
rctx->client->task, fetch_done, rctx, rctx->rdataset,
|
||||
rctx->sigrdataset, &rctx->fetch);
|
||||
|
||||
return (result);
|
||||
}
|
||||
@@ -860,30 +857,24 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
|
||||
} while (want_restart);
|
||||
|
||||
if (send_event) {
|
||||
isc_task_t *task;
|
||||
|
||||
while ((name = ISC_LIST_HEAD(rctx->namelist)) != NULL) {
|
||||
ISC_LIST_UNLINK(rctx->namelist, name, link);
|
||||
ISC_LIST_APPEND(rctx->event->answerlist, name, link);
|
||||
ISC_LIST_APPEND(rctx->rev->answerlist, name, link);
|
||||
}
|
||||
|
||||
rctx->event->result = result;
|
||||
rctx->event->vresult = vresult;
|
||||
task = rctx->event->ev_sender;
|
||||
rctx->event->ev_sender = rctx;
|
||||
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&rctx->event));
|
||||
rctx->rev->result = result;
|
||||
rctx->rev->vresult = vresult;
|
||||
isc_async_run(rctx->client->loop, rctx->rev->cb, rctx->rev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resolve_done(isc_task_t *task, isc_event_t *event) {
|
||||
resarg_t *resarg = event->ev_arg;
|
||||
dns_clientresume_t *rev = (dns_clientresume_t *)event;
|
||||
resolve_done(void *arg) {
|
||||
dns_clientresume_t *rev = (dns_clientresume_t *)arg;
|
||||
resarg_t *resarg = rev->arg;
|
||||
dns_name_t *name = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
resarg->result = rev->result;
|
||||
resarg->vresult = rev->vresult;
|
||||
while ((name = ISC_LIST_HEAD(rev->answerlist)) != NULL) {
|
||||
@@ -891,8 +882,7 @@ resolve_done(isc_task_t *task, isc_event_t *event) {
|
||||
ISC_LIST_APPEND(*resarg->namelist, name, link);
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
isc_mem_put(resarg->mctx, rev, sizeof(*rev));
|
||||
destroyrestrans(&resarg->trans);
|
||||
|
||||
result = resarg->result;
|
||||
@@ -939,8 +929,7 @@ dns_client_resolve(dns_client_t *client, const dns_name_t *name,
|
||||
isc_mem_attach(client->mctx, &resarg->mctx);
|
||||
|
||||
result = dns_client_startresolve(client, name, rdclass, type, options,
|
||||
client->task, resolve_done, resarg,
|
||||
&resarg->trans);
|
||||
resolve_done, resarg, &resarg->trans);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(client->mctx, resarg, sizeof(*resarg));
|
||||
return (result);
|
||||
@@ -952,15 +941,13 @@ dns_client_resolve(dns_client_t *client, const dns_name_t *name,
|
||||
isc_result_t
|
||||
dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
||||
unsigned int options, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg,
|
||||
unsigned int options, isc_job_cb cb, void *arg,
|
||||
dns_clientrestrans_t **transp) {
|
||||
dns_clientresume_t *event = NULL;
|
||||
dns_clientresume_t *rev = NULL;
|
||||
resctx_t *rctx = NULL;
|
||||
isc_task_t *tclone = NULL;
|
||||
isc_mem_t *mctx;
|
||||
isc_mem_t *mctx = NULL;
|
||||
isc_result_t result;
|
||||
dns_rdataset_t *rdataset, *sigrdataset;
|
||||
dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
|
||||
bool want_dnssec, want_validation, want_cdflag, want_tcp;
|
||||
|
||||
REQUIRE(DNS_CLIENT_VALID(client));
|
||||
@@ -968,8 +955,6 @@ dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
REQUIRE(rdclass == dns_rdataclass_in);
|
||||
|
||||
mctx = client->mctx;
|
||||
rdataset = NULL;
|
||||
sigrdataset = NULL;
|
||||
want_dnssec = ((options & DNS_CLIENTRESOPT_NODNSSEC) == 0);
|
||||
want_validation = ((options & DNS_CLIENTRESOPT_NOVALIDATE) == 0);
|
||||
want_cdflag = ((options & DNS_CLIENTRESOPT_NOCDFLAG) == 0);
|
||||
@@ -978,24 +963,25 @@ dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
/*
|
||||
* Prepare some intermediate resources
|
||||
*/
|
||||
tclone = NULL;
|
||||
isc_task_attach(task, &tclone);
|
||||
event = (dns_clientresume_t *)isc_event_allocate(
|
||||
mctx, tclone, DNS_EVENT_CLIENTRESDONE, action, arg,
|
||||
sizeof(*event));
|
||||
event->result = DNS_R_SERVFAIL;
|
||||
ISC_LIST_INIT(event->answerlist);
|
||||
rev = isc_mem_get(mctx, sizeof(*rev));
|
||||
*rev = (dns_clientresume_t){
|
||||
.result = DNS_R_SERVFAIL,
|
||||
.answerlist = ISC_LIST_INITIALIZER,
|
||||
.cb = cb,
|
||||
.arg = arg,
|
||||
};
|
||||
|
||||
rctx = isc_mem_get(mctx, sizeof(*rctx));
|
||||
*rctx = (resctx_t){
|
||||
.client = client,
|
||||
.task = client->task,
|
||||
.event = event,
|
||||
.rev = rev,
|
||||
.type = type,
|
||||
.want_dnssec = want_dnssec,
|
||||
.want_validation = want_validation,
|
||||
.want_cdflag = want_cdflag,
|
||||
.want_tcp = want_tcp,
|
||||
.namelist = ISC_LIST_INITIALIZER,
|
||||
.link = ISC_LINK_INITIALIZER,
|
||||
};
|
||||
|
||||
result = getrdataset(mctx, &rdataset);
|
||||
@@ -1015,9 +1001,7 @@ dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
dns_fixedname_init(&rctx->name);
|
||||
dns_name_copy(name, dns_fixedname_name(&rctx->name));
|
||||
|
||||
ISC_LINK_INIT(rctx, link);
|
||||
dns_view_attach(client->view, &rctx->view);
|
||||
ISC_LIST_INIT(rctx->namelist);
|
||||
|
||||
rctx->magic = RCTX_MAGIC;
|
||||
isc_refcount_increment(&client->references);
|
||||
@@ -1037,8 +1021,7 @@ cleanup:
|
||||
putrdataset(client->mctx, &sigrdataset);
|
||||
}
|
||||
isc_mem_put(mctx, rctx, sizeof(*rctx));
|
||||
isc_event_free(ISC_EVENT_PTR(&event));
|
||||
isc_task_detach(&tclone);
|
||||
isc_mem_put(mctx, rev, sizeof(*rev));
|
||||
|
||||
return (result);
|
||||
}
|
||||
@@ -1081,7 +1064,6 @@ destroyrestrans(dns_clientrestrans_t **transp) {
|
||||
|
||||
REQUIRE(RCTX_VALID(rctx));
|
||||
REQUIRE(rctx->fetch == NULL);
|
||||
REQUIRE(rctx->event == NULL);
|
||||
|
||||
client = rctx->client;
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
*/
|
||||
|
||||
#include <isc/event.h>
|
||||
#include <isc/loop.h>
|
||||
#include <isc/sockaddr.h>
|
||||
|
||||
#include <dns/tsig.h>
|
||||
@@ -73,19 +74,26 @@ ISC_LANG_BEGINDECLS
|
||||
#define DNS_CLIENTVIEW_NAME "_dnsclient"
|
||||
|
||||
/*%
|
||||
* A dns_clientresume_t is sent when name resolution performed by a client
|
||||
* completes. 'result' stores the result code of the entire resolution
|
||||
* A dns_clientresume_t holds state for resolution performed by a client,
|
||||
* and is sent to the callback when the resolution completes.
|
||||
* 'result' stores the result code of the entire resolution
|
||||
* procedure. 'vresult' specifically stores the result code of DNSSEC
|
||||
* validation if it is performed. When name resolution successfully completes,
|
||||
* 'answerlist' is typically non empty, containing answer names along with
|
||||
* RRsets. It is the receiver's responsibility to free this list by calling
|
||||
* dns_client_freeresanswer() before freeing the event structure.
|
||||
* RRsets. 'cb' is the callback function and 'arg' is the callback argument
|
||||
* that was specified by the caller.
|
||||
*
|
||||
* It is the receiver's responsibility to free 'answerlist' by
|
||||
* calling dns_client_freeresanswer(), and to free the dns_clientresume
|
||||
* structure itself.
|
||||
*/
|
||||
typedef struct dns_clientresume {
|
||||
ISC_EVENT_COMMON(struct dns_clientresume);
|
||||
isc_mem_t *mctx;
|
||||
isc_result_t result;
|
||||
isc_result_t vresult;
|
||||
dns_namelist_t answerlist;
|
||||
isc_job_cb cb;
|
||||
void *arg;
|
||||
} dns_clientresume_t; /* too long? */
|
||||
|
||||
isc_result_t
|
||||
@@ -110,6 +118,8 @@ dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
|
||||
*
|
||||
*\li 'mctx' is a valid memory context.
|
||||
*
|
||||
*\li 'loopmgr' is a valid loop manager.
|
||||
|
||||
*\li 'taskmgr' is a valid task manager.
|
||||
*
|
||||
*\li 'nm' is a valid network manager.
|
||||
@@ -202,8 +212,7 @@ dns_client_resolve(dns_client_t *client, const dns_name_t *name,
|
||||
isc_result_t
|
||||
dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
||||
unsigned int options, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg,
|
||||
unsigned int options, isc_job_cb cb, void *arg,
|
||||
dns_clientrestrans_t **transp);
|
||||
/*%<
|
||||
* Perform name resolution for 'name', 'rdclass', and 'type'.
|
||||
@@ -231,11 +240,11 @@ dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
* created via dns_client_create() and has external managers and contexts.
|
||||
*
|
||||
* dns_client_startresolve() is an asynchronous version of dns_client_resolve()
|
||||
* and does not block. When name resolution is completed, 'action' will be
|
||||
* and does not block. When name resolution is completed, 'cb' will be
|
||||
* called with the argument of a 'dns_clientresume_t' object, which contains
|
||||
* the resulting list of answer names (on success). On return, '*transp' is
|
||||
* set to an opaque transaction ID so that the caller can cancel this
|
||||
* resolution process.
|
||||
* the resulting list of answer names (on success), and a also contains
|
||||
* a pointer to 'arg'. On return, '*transp' is set to an opaque transaction
|
||||
* ID so that the caller can cancel this resolution process.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
@@ -247,8 +256,6 @@ dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
|
||||
*
|
||||
*\li 'namelist' != NULL and is not empty.
|
||||
*
|
||||
*\li 'task' is a valid task.
|
||||
*
|
||||
*\li 'transp' != NULL && *transp == NULL;
|
||||
*
|
||||
* Returns:
|
||||
|
||||
Reference in New Issue
Block a user