From: Vladimír Čunát Date: Fri, 5 Apr 2019 16:27:01 +0000 (+0200) Subject: lua worker.resolve*: rework, get rid of light userdata X-Git-Tag: v4.1.0~21^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=19ef77d1e582fcc5ce93ba34ee3afb6d2562e8fd;p=thirdparty%2Fknot-resolver.git lua worker.resolve*: rework, get rid of light userdata --- diff --git a/daemon/bindings/worker.c b/daemon/bindings/worker.c index 41379f45f..8d6072a5d 100644 --- a/daemon/bindings/worker.c +++ b/daemon/bindings/worker.c @@ -18,99 +18,33 @@ #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 } }; diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index 8cd5d974c..1d867682e 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -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; diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index 09bb36349..a8e9d1bb0 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -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 diff --git a/daemon/lua/sandbox.lua.in b/daemon/lua/sandbox.lua.in index a932c4953..e2fe8eb79 100644 --- a/daemon/lua/sandbox.lua.in +++ b/daemon/lua/sandbox.lua.in @@ -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 diff --git a/daemon/worker.c b/daemon/worker.c index fac20fcad..e337c46f8 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -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; diff --git a/daemon/worker.h b/daemon/worker.h index c1336efeb..2a741988a 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -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); diff --git a/daemon/zimport.c b/daemon/zimport.c index ede0dbf7d..61c3a9af4 100644 --- a/daemon/zimport.c +++ b/daemon/zimport.c @@ -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);