]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
refactor dns_client to use loop callbacks
authorEvan Hunt <each@isc.org>
Thu, 27 Oct 2022 18:45:33 +0000 (11:45 -0700)
committerOndřej Surý <ondrej@isc.org>
Thu, 16 Feb 2023 16:16:42 +0000 (17:16 +0100)
dns_client now uses isc_async_run() internally to post
client-resume events. (a task is still used for
dns_resolver_createfetch(), however.)

lib/dns/client.c
lib/dns/include/dns/client.h

index 96821f0181c830c67d8d1a5c2f552d3dc4f55630..1253dafe6a47c0acec1dc1468b0afbf5cb231c2b 100644 (file)
@@ -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;
 
index 5e8135bf28fccb9c6c8bcf5f0b920bf10eb4a3f5..ee0a4c26957cdfe039519be2650fef23e0c1d901 100644 (file)
@@ -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: