]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lua worker.resolve*: rework, get rid of light userdata
authorVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 5 Apr 2019 16:27:01 +0000 (18:27 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 13 Jun 2019 13:03:15 +0000 (15:03 +0200)
daemon/bindings/worker.c
daemon/lua/kres-gen.lua
daemon/lua/kres-gen.sh
daemon/lua/sandbox.lua.in
daemon/worker.c
daemon/worker.h
daemon/zimport.c

index 41379f45fd12e5859c734711a9c32640bce82578..8d6072a5d57d8d78fd52fe9fc1d4c466196d8c66 100644 (file)
 
 #include "daemon/worker.h"
 
-/** resolve_pkt(pkt, options, init_cb) */
-static int wrk_resolve_pkt(lua_State *L)
+knot_pkt_t * worker_resolve_mk_pkt(const char *qname_str, uint16_t qtype, uint16_t qclass,
+                                  const struct kr_qflags *options)
 {
-       if (!the_worker) {
-               return 0;
-       }
-
-       knot_pkt_t *pkt = *(knot_pkt_t **)lua_topointer(L, 1);
-       if (!pkt)
-               lua_error_maybe(L, ENOMEM);
-
-       /* Add query options */
-       const struct kr_qflags *options = lua_topointer(L, 2);
-       if (!options) /* but we rely on the lua wrapper when dereferencing non-NULL */
-               lua_error_p(L, "invalid options");
-
-       /* Create task and start with a first question */
-       struct qr_task *task = worker_resolve_start(the_worker, pkt, *options);
-       if (!task) {
-               lua_error_p(L, "couldn't create a resolution request");
-       }
-
-       /* Add initialisation callback */
-       if (lua_isfunction(L, 3)) {
-               lua_pushvalue(L, 3);
-               lua_pushlightuserdata(L, worker_task_request(task));
-               (void) execute_callback(L, 1);
-       }
-
-       /* Start execution */
-       int ret = worker_resolve_exec(task, pkt);
-       lua_pushboolean(L, ret == 0);
-       return 1;
-}
-
-/** resolve(qname, qtype, qclass, options, init_cb) */
-static int wrk_resolve(lua_State *L)
-{
-       struct worker_ctx *worker = the_worker;
-       if (!worker) {
-               return 0;
-       }
-
-       uint8_t dname[KNOT_DNAME_MAXLEN];
-       if (!knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname)))
-               lua_error_p(L, "invalid qname");
-
-       /* Check class and type */
-       uint16_t rrtype = lua_tointeger(L, 2);
-       if (!lua_isnumber(L, 2))
-               lua_error_p(L, "invalid RR type");
-
-       uint16_t rrclass = lua_tointeger(L, 3);
-       if (!lua_isnumber(L, 3)) { /* Default class is IN */
-               rrclass = KNOT_CLASS_IN;
-       }
-
-       /* Add query options */
-       const struct kr_qflags *options = lua_topointer(L, 4);
-       if (!options) /* but we rely on the lua wrapper when dereferencing non-NULL */
-               lua_error_p(L, "invalid options");
-
-       /* Create query packet */
+       uint8_t qname[KNOT_DNAME_MAXLEN];
+       if (!knot_dname_from_str(qname, qname_str, sizeof(qname)))
+               return NULL;
        knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_EDNS_MAX_UDP_PAYLOAD, NULL);
        if (!pkt)
-               lua_error_maybe(L, ENOMEM);
-       knot_pkt_put_question(pkt, dname, rrclass, rrtype);
+               return NULL;
+       knot_pkt_put_question(pkt, qname, qclass, qtype);
        knot_wire_set_rd(pkt->wire);
        knot_wire_set_ad(pkt->wire);
 
        /* Add OPT RR */
-       pkt->opt_rr = knot_rrset_copy(worker->engine->resolver.opt_rr, NULL);
+       pkt->opt_rr = knot_rrset_copy(the_worker->engine->resolver.opt_rr, NULL);
        if (!pkt->opt_rr) {
                knot_pkt_free(pkt);
-               lua_error_maybe(L, ENOMEM);
+               return NULL;
        }
        if (options->DNSSEC_WANT) {
                knot_edns_set_do(pkt->opt_rr);
        }
-
        if (options->DNSSEC_CD) {
                knot_wire_set_cd(pkt->wire);
        }
 
-       lua_pushcfunction(L, wrk_resolve_pkt);
-       lua_pushlightuserdata(L, &pkt);
-       lua_pushvalue(L, 4);  /* options */
-       lua_pushvalue(L, 5);  /* init_cb */
-       lua_call(L, 3, 1);  /* leaves return value on stack */
-
-       knot_rrset_free(pkt->opt_rr, NULL);
-       knot_pkt_free(pkt);
-       return 1;
+       return pkt;
 }
 
 static inline double getseconds(uv_timeval_t *tv)
@@ -172,8 +106,6 @@ static int wrk_stats(lua_State *L)
 int kr_bindings_worker(lua_State *L)
 {
        static const luaL_Reg lib[] = {
-               { "resolve_unwrapped",  wrk_resolve },
-               { "resolve_unwrapped_pkt",  wrk_resolve_pkt },
                { "stats",    wrk_stats },
                { NULL, NULL }
        };
index 8cd5d974c46a77396c46f21c6d0f81a833342c84..1d867682e69b8218ca54b034212cc344dbbc5110 100644 (file)
@@ -319,6 +319,7 @@ char *knot_dname_to_str(char *, const knot_dname_t *, size_t);
 knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, uint16_t);
 int knot_rdataset_merge(knot_rdataset_t *, const knot_rdataset_t *, knot_mm_t *);
 int knot_rrset_add_rdata(knot_rrset_t *, const uint8_t *, uint16_t, knot_mm_t *);
+void knot_rrset_free(knot_rrset_t *, knot_mm_t *);
 int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *);
 int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *);
 size_t knot_rrset_size(const knot_rrset_t *);
@@ -399,6 +400,17 @@ struct endpoint {
        _Bool engaged;
        endpoint_flags_t flags;
 };
+struct request_ctx {
+       struct kr_request req;
+       /* beware: hidden stub, to avoid hardcoding sockaddr lengths */
+};
+struct qr_task {
+       struct request_ctx *ctx;
+       /* beware: hidden stub, to avoid qr_tasklist_t */
+};
+int worker_resolve_exec(struct qr_task *, knot_pkt_t *);
+knot_pkt_t *worker_resolve_mk_pkt(const char *, uint16_t, uint16_t, const struct kr_qflags *);
+struct qr_task *worker_resolve_start(knot_pkt_t *, struct kr_qflags);
 typedef struct {
        uint8_t bitmap[32];
        uint8_t length;
index 09bb3634985f90560f96f1a85403d0d7256b1fde..a8e9d1bb0c0418928468ed8c10a273aa59e8fd0f 100755 (executable)
@@ -147,6 +147,7 @@ ${CDEFS} libknot functions <<-EOF
        knot_rdataset_at
        knot_rdataset_merge
        knot_rrset_add_rdata
+       knot_rrset_free
        knot_rrset_txt_dump
        knot_rrset_txt_dump_data
        knot_rrset_size
@@ -229,11 +230,26 @@ ${CDEFS} ${LIBKRES} functions <<-EOF
        packet_ttl
 EOF
 
-## kresd daemon stuff, too
+
+## kresd itself: worker stuff
+
 ${CDEFS} ${KRESD} types <<-EOF
        endpoint_flags_t
 EOF
-echo "struct endpoint" | ${CDEFS} ${KRESD} types | sed 's/uv_handle_t \*/void */'
+
+echo "struct endpoint"    | ${CDEFS} ${KRESD} types | sed 's/uv_handle_t \*/void */'
+echo "struct request_ctx" | ${CDEFS} ${KRESD} types | sed '/struct {/,$ d'
+printf "\t/* beware: hidden stub, to avoid hardcoding sockaddr lengths */\n};\n"
+
+echo "struct qr_task" | ${CDEFS} ${KRESD} types | sed '/pktbuf/,$ d'
+printf "\t/* beware: hidden stub, to avoid qr_tasklist_t */\n};\n"
+
+${CDEFS} ${KRESD} functions <<-EOF
+       worker_resolve_exec
+       worker_resolve_mk_pkt
+       worker_resolve_start
+EOF
+
 
 ## libzscanner API for ./zonefile.lua
 ${CDEFS} libzscanner types <<-EOF
index a932c4953aeb863b668adfb02699acaa79e089d6..e2fe8eb79e0dfa1ade56824cda2a4661fbf8a76e 100644 (file)
@@ -32,27 +32,30 @@ if rawget(kres, 'str2dname') ~= nil then
        todname = kres.str2dname
 end
 
-local function prep_resolve_cb(finish, init)
-       local init_cb, finish_cb = init, nil
-       if finish then
-               -- Create callback for finalization
-               finish_cb = ffi.cast('trace_callback_f', function (req)
-                       jit.off(true, true) -- JIT for (C -> lua)^2 nesting isn't allowed
-                       req = kres.request_t(req)
-                       finish(req.answer, req)
-                       finish_cb:free()
-               end)
-               -- Wrap initialiser to install finish callback
-               init_cb = function (req)
+
+worker.resolve_pkt = function (pkt, options, finish, init)
+       options = kres.mk_qflags(options)
+       local task = ffi.C.worker_resolve_start(pkt, options)
+
+       -- Deal with finish and init callbacks
+       if finish ~= nil then
+               local finish_cb
+               finish_cb = ffi.cast('trace_callback_f',
+                       function (req)
+                               jit.off(true, true) -- JIT for (C -> lua)^2 nesting isn't allowed
                        req = kres.request_t(req)
-                       if init then init(req) end
-                       req.trace_finish = finish_cb
-               end
+                               finish(req.answer, req)
+                               finish_cb:free()
+                       end)
+               task.ctx.req.trace_finish = finish_cb
+       end
+       if init ~= nil then
+               init(task.ctx.req)
        end
-       return init_cb
+
+       return ffi.C.worker_resolve_exec(task, pkt) == 0
 end
 
--- Compatibility wrapper for query flags.
 worker.resolve = function (qname, qtype, qclass, options, finish, init)
        -- Alternatively use named arguments
        if type(qname) == 'table' then
@@ -64,19 +67,17 @@ worker.resolve = function (qname, qtype, qclass, options, finish, init)
                finish = t.finish
                init = t.init
        end
-       local init_cb = prep_resolve_cb(finish, init)
-
-       -- Translate options and resolve
        options = kres.mk_qflags(options)
-       return worker.resolve_unwrapped(qname, qtype, qclass, options, init_cb)
-end
-
-worker.resolve_pkt = function (pkt, options, finish, init)
-       local init_cb = prep_resolve_cb(finish, init)
-       options = kres.mk_qflags(options)
-       return worker.resolve_unwrapped_pkt(pkt, options, init_cb)
+       -- LATER: nicer errors for rubbish in qname, qtype, qclass?
+       local pkt = ffi.C.worker_resolve_mk_pkt(qname, qtype, qclass, options)
+       if pkt == nil then
+               panic('failure in worker.resolve(); probably invalid qname "%s"', qname)
+       end
+       local ret = worker.resolve_pkt(pkt, options, finish, init)
+       ffi.C.knot_rrset_free(pkt.opt_rr, nil);
+       ffi.C.knot_pkt_free(pkt);
+       return ret
 end
-
 resolve = worker.resolve
 
 -- Shorthand for aggregated per-worker information
index fac20fcad07be815af8a00acae49aa165f549ff7..e337c46f81e1dcf4ee3998d719ce0b8837c834b2 100644 (file)
@@ -1794,8 +1794,9 @@ int worker_end_tcp(struct session *session)
        return kr_ok();
 }
 
-struct qr_task *worker_resolve_start(struct worker_ctx *worker, knot_pkt_t *query, struct kr_qflags options)
+struct qr_task *worker_resolve_start(knot_pkt_t *query, struct kr_qflags options)
 {
+       struct worker_ctx *worker = the_worker;
        if (!worker || !query) {
                assert(!EINVAL);
                return NULL;
index c1336efebe309ff681601aa1e4ab49ef89cb09f6..2a741988a12bbe64b9c0b186717be9c7cfcb17ec 100644 (file)
@@ -55,12 +55,18 @@ int worker_submit(struct session *session, knot_pkt_t *query);
  */
 int worker_end_tcp(struct session *session);
 
+/** FIXME docs */
+KR_EXPORT knot_pkt_t *
+worker_resolve_mk_pkt(const char *qname_str, uint16_t qtype, uint16_t qclass,
+                       const struct kr_qflags *options);
+
 /**
  * Start query resolution with given query.
  *
  * @return task or NULL
  */
-struct qr_task *worker_resolve_start(struct worker_ctx *worker, knot_pkt_t *query, struct kr_qflags options);
+KR_EXPORT struct qr_task *
+worker_resolve_start(knot_pkt_t *query, struct kr_qflags options);
 
 /**
  * Execute a request with given query.
@@ -68,7 +74,7 @@ struct qr_task *worker_resolve_start(struct worker_ctx *worker, knot_pkt_t *quer
  *
  * @return 0 or an error code
  */
-int worker_resolve_exec(struct qr_task *task, knot_pkt_t *query);
+KR_EXPORT int worker_resolve_exec(struct qr_task *task, knot_pkt_t *query);
 
 /** @return struct kr_request associated with opaque task */
 struct kr_request *worker_task_request(struct qr_task *task);
index ede0dbf7db52f13e73d09c441c9166392b757875..61c3a9af454ce2da63308554057180b3c6bc672b 100644 (file)
@@ -338,10 +338,6 @@ static knot_pkt_t *zi_query_create(zone_import_ctx_t *z_import, knot_rrset_t *rr
  * @return -1 if failed; 0 if success */
 static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr)
 {
-       struct worker_ctx *worker = z_import->worker;
-
-       assert(worker);
-
        /* Create "pseudo query" which asks for given rrset. */
        knot_pkt_t *query = zi_query_create(z_import, rr);
        if (!query) {
@@ -369,7 +365,7 @@ static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr)
 
        /* This call creates internal structures which necessary for
         * resolving - qr_task & request_ctx. */
-       struct qr_task *task = worker_resolve_start(worker, query, options);
+       struct qr_task *task = worker_resolve_start(query, options);
        if (!task) {
                knot_pkt_free(query);
                knot_pkt_free(answer);