#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)
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 }
};
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 *);
_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;
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
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
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
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
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;
*/
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.
*
* @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);
* @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) {
/* 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);