lua worker.resolve*: rework, get rid of light userdata

parent 1902ba0f
......@@ -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 }
};
......
......@@ -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;
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment