#include <stdbool.h>
#include <stddef.h>
+#include <isc/async.h>
#include <isc/buffer.h>
#include <isc/md.h>
#include <isc/mem.h>
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;
bool want_tcp;
ISC_LINK(struct resctx) link;
- isc_task_t *task;
dns_view_t *view;
unsigned int restarts;
dns_fixedname_t name;
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;
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;
}
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);
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);
}
} 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) {
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;
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);
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));
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);
/*
* 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);
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);
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);
}
REQUIRE(RCTX_VALID(rctx));
REQUIRE(rctx->fetch == NULL);
- REQUIRE(rctx->event == NULL);
client = rctx->client;
*/
#include <isc/event.h>
+#include <isc/loop.h>
#include <isc/sockaddr.h>
#include <dns/tsig.h>
#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
*
*\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.
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'.
* 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:
*
*
*\li 'namelist' != NULL and is not empty.
*
- *\li 'task' is a valid task.
- *
*\li 'transp' != NULL && *transp == NULL;
*
* Returns: