Commit 809d5b76 authored by Tomas Krizek's avatar Tomas Krizek

Merge branch 'lua-light-userdata_4.0.0' into 'master'

parts of !797: lua light userdata WIP

See merge request knot/knot-resolver!800
parents 4024fcfc b54dd81d
......@@ -42,6 +42,8 @@ Bugfixes
Module API changes
------------------
- kr_straddr_split() changed API a bit (compiler will catch that)
- C modules defining `*_layer` or `*_props` symbols need to change a bit
See the upgrading guide for details. It's detected on module load.
Knot Resolver 3.2.1 (2019-01-10)
......
......@@ -662,13 +662,13 @@ int engine_init(struct engine *engine, knot_mm_t *pool)
return ret;
}
/** Unregister a (found) module */
static void engine_unload(struct engine *engine, struct kr_module *module)
{
/* Unregister module */
auto_free char *name = strdup(module->name);
kr_module_unload(module);
/* Clear in Lua world, but not for embedded modules ('cache' in particular). */
if (name && !kr_module_embedded(name)) {
if (name && !kr_module_get_embedded(name)) {
lua_pushnil(engine->L);
lua_setglobal(engine->L, name);
}
......@@ -821,8 +821,7 @@ static int register_properties(struct engine *engine, struct kr_module *module)
REGISTER_MODULE_CALL(engine->L, module, module->config, "config");
}
const struct kr_prop *p = module->props == NULL ? NULL : module->props();
for (; p && p->name; ++p) {
for (const struct kr_prop *p = module->props; p && p->name; ++p) {
if (p->cb != NULL) {
REGISTER_MODULE_CALL(engine->L, module, p->cb, p->name);
}
......
......@@ -81,12 +81,12 @@ static int l_ffi_defer(lua_State *L)
return uv_idle_start(check, l_ffi_resume_cb);
}
/** @internal Helper for calling the entrypoint. */
static inline int l_ffi_call(lua_State *L, int argc)
/** @internal Helper for calling the entrypoint, for kr_module functions. */
static inline int l_ffi_call_mod(lua_State *L, int argc)
{
int status = lua_pcall(L, argc, 1, 0);
if (status != 0) {
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
kr_log_error("error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
return kr_error(EIO);
}
......@@ -99,13 +99,21 @@ static inline int l_ffi_call(lua_State *L, int argc)
return status;
}
/** @internal Helper for calling the entrypoint, for kr_layer_api functions. */
static inline int l_ffi_call_layer(lua_State *L, int argc)
{
int ret = l_ffi_call_mod(L, argc);
/* The return codes are mixed at this point. We need to return KR_STATE_* */
return ret < 0 ? KR_STATE_FAIL : ret;
}
static int l_ffi_init(struct kr_module *module)
{
lua_State *L = l_ffi_preface(module, "init");
if (!L) {
return 0;
}
return l_ffi_call(L, 1);
return l_ffi_call_mod(L, 1);
}
static int l_ffi_deinit(struct kr_module *module)
......@@ -114,7 +122,7 @@ static int l_ffi_deinit(struct kr_module *module)
int ret = 0;
lua_State *L = module->lib;
if (l_ffi_preface(module, "deinit")) {
ret = l_ffi_call(L, 1);
ret = l_ffi_call_mod(L, 1);
}
module->lib = NULL;
/* Free the layer API wrapper (unconst it) */
......@@ -147,14 +155,14 @@ static int l_ffi_layer_begin(kr_layer_t *ctx)
{
LAYER_FFI_CALL(ctx, begin);
lua_pushlightuserdata(L, ctx->req);
return l_ffi_call(L, 2);
return l_ffi_call_layer(L, 2);
}
static int l_ffi_layer_reset(kr_layer_t *ctx)
{
LAYER_FFI_CALL(ctx, reset);
lua_pushlightuserdata(L, ctx->req);
return l_ffi_call(L, 2);
return l_ffi_call_layer(L, 2);
}
static int l_ffi_layer_finish(kr_layer_t *ctx)
......@@ -163,7 +171,7 @@ static int l_ffi_layer_finish(kr_layer_t *ctx)
LAYER_FFI_CALL(ctx, finish);
lua_pushlightuserdata(L, req);
lua_pushlightuserdata(L, req->answer);
return l_ffi_call(L, 3);
return l_ffi_call_layer(L, 3);
}
static int l_ffi_layer_consume(kr_layer_t *ctx, knot_pkt_t *pkt)
......@@ -174,7 +182,7 @@ static int l_ffi_layer_consume(kr_layer_t *ctx, knot_pkt_t *pkt)
LAYER_FFI_CALL(ctx, consume);
lua_pushlightuserdata(L, ctx->req);
lua_pushlightuserdata(L, pkt);
return l_ffi_call(L, 3);
return l_ffi_call_layer(L, 3);
}
static int l_ffi_layer_produce(kr_layer_t *ctx, knot_pkt_t *pkt)
......@@ -185,7 +193,7 @@ static int l_ffi_layer_produce(kr_layer_t *ctx, knot_pkt_t *pkt)
LAYER_FFI_CALL(ctx, produce);
lua_pushlightuserdata(L, ctx->req);
lua_pushlightuserdata(L, pkt);
return l_ffi_call(L, 3);
return l_ffi_call_layer(L, 3);
}
static int l_ffi_layer_checkout(kr_layer_t *ctx, knot_pkt_t *pkt, struct sockaddr *dst, int type)
......@@ -198,14 +206,14 @@ static int l_ffi_layer_checkout(kr_layer_t *ctx, knot_pkt_t *pkt, struct sockadd
lua_pushlightuserdata(L, pkt);
lua_pushlightuserdata(L, dst);
lua_pushboolean(L, type == SOCK_STREAM);
return l_ffi_call(L, 5);
return l_ffi_call_layer(L, 5);
}
static int l_ffi_layer_answer_finalize(kr_layer_t *ctx)
{
LAYER_FFI_CALL(ctx, answer_finalize);
lua_pushlightuserdata(L, ctx->req);
return l_ffi_call(L, 2);
return l_ffi_call_layer(L, 2);
}
#undef LAYER_FFI_CALL
......@@ -246,14 +254,6 @@ static kr_layer_api_t *l_ffi_layer_create(lua_State *L, struct kr_module *module
return api;
}
/** @internal Retrieve C layer api wrapper. */
static const kr_layer_api_t *l_ffi_layer(struct kr_module *module)
{
if (module) {
return (const kr_layer_api_t *)module->data;
}
return NULL;
}
#undef LAYER_REGISTER
int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name)
......@@ -263,7 +263,7 @@ int ffimodule_register_lua(struct engine *engine, struct kr_module *module, cons
lua_getglobal(L, "require");
lua_pushfstring(L, "kres_modules.%s", name);
if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
kr_log_error("error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
return kr_error(ENOENT);
}
......@@ -278,8 +278,9 @@ int ffimodule_register_lua(struct engine *engine, struct kr_module *module, cons
/* Bake layer API if defined in module */
lua_getfield(L, -1, "layer");
if (!lua_isnil(L, -1)) {
module->layer = &l_ffi_layer;
module->data = l_ffi_layer_create(L, module);
module->layer = l_ffi_layer_create(L, module);
/* most likely not needed, but compatibility for now */
module->data = (void *)module->layer;
}
module->lib = L;
lua_pop(L, 2); /* Clear the layer + module global */
......
......@@ -45,6 +45,9 @@ Modules
.. doxygenfile:: module.h
:project: libkres
.. doxygenfile:: layer.h
:project: libkres
Utilities
---------
......
......@@ -63,6 +63,9 @@ Module changes
``kres_modules.*``.
* ``kr_straddr_split()`` API has changed.
* C modules defining ``*_layer`` or ``*_props`` symbols need to use a different style, but it's typically a trivial change.
Instead of exporting the corresponding symbols, the module should assign pointers to its static structures inside its ``*_init()`` function. Example migration:
`bogus_log module <https://gitlab.labs.nic.cz/knot/knot-resolver/commit/2875a3970#9fa69cdc6ee1903dc22e3262f58996395acab364>`_.
.. _upgrade-from-2-to-3:
......
......@@ -18,14 +18,15 @@
#include "lib/cache/api.h"
/** Module implementation. */
const kr_layer_api_t *cache_layer(struct kr_module *module)
int cache_init(struct kr_module *self)
{
static const kr_layer_api_t _layer = {
static const kr_layer_api_t layer = {
.produce = &cache_peek,
.consume = &cache_stash,
};
return &_layer;
self->layer = &layer;
return kr_ok();
}
KR_MODULE_EXPORT(cache)
KR_MODULE_EXPORT(cache) /* useless for builtin module, but let's be consistent */
......@@ -1111,17 +1111,18 @@ static int resolve(kr_layer_t *ctx, knot_pkt_t *pkt)
}
/** Module implementation. */
const kr_layer_api_t *iterate_layer(struct kr_module *module)
int iterate_init(struct kr_module *self)
{
static const kr_layer_api_t _layer = {
static const kr_layer_api_t layer = {
.begin = &begin,
.reset = &reset,
.consume = &resolve,
.produce = &prepare_query
};
return &_layer;
self->layer = &layer;
return kr_ok();
}
KR_MODULE_EXPORT(iterate)
KR_MODULE_EXPORT(iterate) /* useless for builtin module, but let's be consistent */
#undef VERBOSE_MSG
......@@ -1116,21 +1116,17 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
VERBOSE_MSG(qry, "<= answer valid, OK\n");
return KR_STATE_DONE;
}
/** Module implementation. */
const kr_layer_api_t *validate_layer(struct kr_module *module)
int validate_init(struct kr_module *self)
{
static const kr_layer_api_t _layer = {
static const kr_layer_api_t layer = {
.consume = &validate,
};
/* Store module reference */
return &_layer;
}
int validate_init(struct kr_module *module)
{
self->layer = &layer;
return kr_ok();
}
KR_MODULE_EXPORT(validate)
KR_MODULE_EXPORT(validate) /* useless for builtin module, but let's be consistent */
#undef VERBOSE_MSG
......@@ -23,16 +23,21 @@
#include "lib/utils.h"
#include "lib/module.h"
/* List of embedded modules */
const kr_layer_api_t *iterate_layer(struct kr_module *module);
const kr_layer_api_t *validate_layer(struct kr_module *module);
const kr_layer_api_t *cache_layer(struct kr_module *module);
static const struct kr_module embedded_modules[] = {
{ "iterate", NULL, NULL, NULL, iterate_layer, NULL, NULL, NULL },
{ "validate", NULL, NULL, NULL, validate_layer, NULL, NULL, NULL },
{ "cache", NULL, NULL, NULL, cache_layer, NULL, NULL, NULL },
};
/* List of embedded modules. These aren't (un)loaded. */
int iterate_init(struct kr_module *self);
int validate_init(struct kr_module *self);
int cache_init(struct kr_module *self);
kr_module_init_cb kr_module_get_embedded(const char *name)
{
if (strcmp(name, "iterate") == 0)
return iterate_init;
if (strcmp(name, "validate") == 0)
return validate_init;
if (strcmp(name, "cache") == 0)
return cache_init;
return NULL;
}
/** Load prefixed symbol. */
static void *load_symbol(void *lib, const char *prefix, const char *name)
......@@ -60,30 +65,16 @@ static int load_library(struct kr_module *module, const char *name, const char *
return kr_error(ENOENT);
}
const struct kr_module * kr_module_embedded(const char *name)
{
for (unsigned i = 0; i < sizeof(embedded_modules)/sizeof(embedded_modules[0]); ++i) {
if (strcmp(name, embedded_modules[i].name) == 0)
return embedded_modules + i;
}
return NULL;
}
/** Load C module symbols. */
static int load_sym_c(struct kr_module *module, uint32_t api_required)
{
module->init = kr_module_get_embedded(module->name);
if (module->init) {
return kr_ok();
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" /* casts after load_symbol() */
/* Check if it's embedded first */
const struct kr_module *embedded = kr_module_embedded(module->name);
if (embedded) {
module->init = embedded->init;
module->deinit = embedded->deinit;
module->config = embedded->config;
module->layer = embedded->layer;
module->props = embedded->props;
return kr_ok();
}
/* Load dynamic library module */
auto_free char *m_prefix = kr_strcatdup(2, module->name, "_");
......@@ -102,9 +93,14 @@ static int load_sym_c(struct kr_module *module, uint32_t api_required)
ML(init);
ML(deinit);
ML(config);
ML(layer);
ML(props);
#undef ML
if (load_symbol(module->lib, m_prefix, "layer")
|| load_symbol(module->lib, m_prefix, "props")) {
/* In case someone re-compiled against new kresd
* but haven't actually changed the symbols. */
kr_log_error("[system] module %s needs to change API.\n", module->name);
return kr_error(ENOTSUP);
}
return kr_ok();
#pragma GCC diagnostic pop
......
......@@ -31,11 +31,11 @@ struct kr_prop;
/**
* Export module API version (place this at the end of your module).
*
* @param module module name (f.e. hints)
* @param module module name (e.g. policy)
*/
#define KR_MODULE_EXPORT(module) \
KR_EXPORT uint32_t module ## _api() { return KR_MODULE_API; }
#define KR_MODULE_API ((uint32_t) 0x20180401)
#define KR_MODULE_API ((uint32_t) 0x20190314)
typedef uint32_t (module_api_cb)(void);
......@@ -55,10 +55,10 @@ struct kr_module {
int (*deinit)(struct kr_module *self);
/** Configure with encoded JSON (NULL if missing). @return error code. */
int (*config)(struct kr_module *self, const char *input);
/** Get a pointer to packet processing API specs. See docs on that type. */
const kr_layer_api_t * (*layer)(struct kr_module *self);
/** Get a pointer to list of properties, terminated by { NULL, NULL, NULL }. */
const struct kr_prop * (*props)(void);
/** Packet processing API specs. May be NULL. See docs on that type. */
const kr_layer_api_t *layer;
/** List of properties. May be NULL. Terminated by { NULL, NULL, NULL }. */
const struct kr_prop *props;
void *lib; /**< Shared library handle or RTLD_DEFAULT */
void *data; /**< Custom data context. */
......@@ -103,9 +103,10 @@ int kr_module_load(struct kr_module *module, const char *name, const char *path)
KR_EXPORT
void kr_module_unload(struct kr_module *module);
typedef int (*kr_module_init_cb)(struct kr_module *);
/**
* Get embedded module prototype by name (or NULL).
* Get embedded module's init function by name (or NULL).
*/
KR_EXPORT
const struct kr_module * kr_module_embedded(const char *name);
kr_module_init_cb kr_module_get_embedded(const char *name);
......@@ -108,7 +108,7 @@ static int answer_finalize_yield(kr_layer_t *ctx) { return kr_ok(); }
for (size_t i = (from); i < (r)->ctx->modules->len; ++i) { \
struct kr_module *mod = (r)->ctx->modules->at[i]; \
if (mod->layer) { \
struct kr_layer layer = {.state = (r)->state, .api = mod->layer(mod), .req = (r)}; \
struct kr_layer layer = {.state = (r)->state, .api = mod->layer, .req = (r)}; \
if (layer.api && layer.api->func) { \
(r)->state = layer.api->func(&layer, ##__VA_ARGS__); \
if ((r)->state == KR_STATE_YIELD) { \
......@@ -127,8 +127,7 @@ static int answer_finalize_yield(kr_layer_t *ctx) { return kr_ok(); }
static inline size_t layer_id(struct kr_request *req, const struct kr_layer_api *api) {
module_array_t *modules = req->ctx->modules;
for (size_t i = 0; i < modules->len; ++i) {
struct kr_module *mod = modules->at[i];
if (mod->layer && mod->layer(mod) == api) {
if (modules->at[i]->layer == api) {
return i;
}
}
......
......@@ -766,7 +766,7 @@ static char *callprop(struct kr_module *module, const char *prop, const char *in
if (!module || !module->props || !prop) {
return NULL;
}
for (const struct kr_prop *p = module->props(); p && p->name; ++p) {
for (const struct kr_prop *p = module->props; p && p->name; ++p) {
if (p->cb != NULL && strcmp(p->name, prop) == 0) {
return p->cb(env, module, input);
}
......
......@@ -11,33 +11,31 @@ Modules API reference
Supported languages
===================
Currently modules written in C and LuaJIT are supported.
Currently modules written in C and Lua(JIT) are supported.
The anatomy of an extension
===========================
A module is a shared object or script defining specific functions, here's an overview.
*Note* |---| the :ref:`Modules <lib_api_modules>` header documents the module loading and API.
A module is a shared object or script defining specific functions/fields; here's an overview.
.. csv-table::
:header: "C/Go", "Lua", "Params", "Comment"
:header: "C", "Lua", "Params", "Comment"
"``X_api()`` [#]_", "", "", "API version"
"``X_init()``", "``X.init()``", "``module``", "Constructor"
"``X_deinit()``", "``X.deinit()``", "``module, key``", "Destructor"
"``X_config()``", "``X.config()``", "``module``", "Configuration"
"``X_layer()``", "``X.layer``", "``module``", ":ref:`Module layer <lib-layers>`"
"``X_props()``", "", "", "List of properties"
"``X_deinit()``", "``X.deinit()``", "``module``", "Destructor"
"``X_config()``", "``X.config()``", "``module, str``", "Configuration"
"``X_layer``", "``X.layer``", "", ":ref:`Module layer <lib-layers>`"
"``X_props``", "", "", "List of properties"
.. [#] Mandatory symbol.
.. [#] Mandatory symbol; defined by using :c:func:`KR_MODULE_EXPORT`.
The ``X`` corresponds to the module name, if the module name is ``hints``, then the prefix for constructor would be ``hints_init()``.
The ``X`` corresponds to the module name; if the module name is ``hints``, the prefix for constructor would be ``hints_init()``.
More details are in docs for the :c:type:`kr_module` and :c:type:`kr_layer_api` structures.
.. note::
The resolution context :c:type:`struct kr_context` holds loaded modules for current context. A module can be registered with :c:func:`kr_context_register`, which triggers module constructor *immediately* after the load. Module destructor is automatically called when the resolution context closes.
If the module exports a layer implementation, it is automatically discovered by :c:func:`kr_resolver` on resolution init and plugged in. The order in which the modules are registered corresponds to the call order of layers.
The modules get ordered -- by default in the same as the order in which they were loaded. The loading command can specify where in the order the module should be positioned.
Writing a module in Lua
=======================
......@@ -45,11 +43,10 @@ Writing a module in Lua
The probably most convenient way of writing modules is Lua since you can use already installed modules
from system and have first-class access to the scripting engine. You can also tap to all the events, that
the C API has access to, but keep in mind that transitioning from the C to Lua function is slower than
the other way round.
the other way round, especially when JIT-compilation is taken into account.
.. note:: The Lua functions retrieve an additional first parameter compared to the C counterparts - a "state".
There is no Lua wrapper for C structures used in the resolution context, until they're implemented
you can inspect the structures using the `ffi <http://luajit.org/ext_ffi.html>`_ library.
Most useful C functions and structures have lua FFI wrappers, sometimes with extra sugar.
The modules follow the `Lua way <http://lua-users.org/wiki/ModuleDefinition>`_, where the module interface is returned in a named table.
......@@ -80,9 +77,11 @@ The modules follow the `Lua way <http://lua-users.org/wiki/ModuleDefinition>`_,
return counter
.. tip:: The API functions may return an integer value just like in other languages, but they may also return a coroutine that will be continued asynchronously. A good use case for this approach is is a deferred initialization, e.g. loading a chunks of data or waiting for I/O.
.. vv Hmm, we do not use these coroutine returns anywhere, so it's unclear whether they still work OK. Splitting work over time is now typically done via the ``event`` timers.
.. code-block:: lua
.. The API functions may return an integer value just like in other languages, but they may also return a coroutine that will be continued asynchronously. A good use case for this approach is is a deferred initialization, e.g. loading a chunks of data or waiting for I/O.
.. .. code-block:: lua
function counter.init(module)
counter.total = 0
......@@ -117,13 +116,13 @@ doesn't provide any layer to capture events. The Lua module can however provide
}
There is currently an additional "feature" in comparison to C layer functions:
the ``consume``, ``produce`` and ``checkout`` functions do not get called at all
if ``state == kres.FAIL``;
note that ``answer_finalize`` and ``finish`` get called nevertheless.
some functions do not get called at all if ``state == kres.FAIL``;
see docs for details: :c:type:`kr_layer_api`.
Since the modules are like any other Lua modules, you can interact with them through the CLI and and any interface.
.. tip:: The module can be placed anywhere in the Lua search path, in the working directory or in the MODULESDIR.
.. tip:: Module discovery: ``kres_modules.`` is prepended to the module name and lua search path is used on that.
Writing a module in C
=====================
......@@ -133,9 +132,10 @@ As almost all the functions are optional, the minimal module looks like this:
.. code-block:: c
#include "lib/module.h"
/* Convenience macro to declare module API. */
/* Convenience macro to declare module ABI. */
KR_MODULE_EXPORT(mymodule)
.. TODO it's probably not a good idea to start C module tutorial by pthread_create()
Let's define an observer thread for the module as well. It's going to be stub for the sake of brevity,
but you can for example create a condition, and notify the thread from query processing by declaring
......@@ -190,7 +190,7 @@ Exposing C module properties
A module can offer NULL-terminated list of *properties*, each property is essentially a callable with free-form JSON input/output.
JSON was chosen as an interchangeable format that doesn't require any schema beforehand, so you can do two things - query the module properties
from external applications or between modules (i.e. `statistics` module can query `cache` module for memory usage).
from external applications or between modules (e.g. `statistics` module can query `cache` module for memory usage).
JSON was chosen not because it's the most efficient protocol, but because it's easy to read and write and interface to outside world.
.. note:: The ``void *env`` is a generic module interface. Since we're implementing daemon modules, the pointer can be cast to ``struct engine*``.
......@@ -205,9 +205,9 @@ Here's an example how a module can expose its property:
{
/* Get cache from engine. */
struct engine *engine = env;
struct kr_cache *cache = &engine->resolver.cache;
struct kr_cache *cache = &engine->resolver.cache;
/* Read item count */
int count = (cache->api)->count(cache->db);
int count = (cache->api)->count(cache->db);
char *result = NULL;
asprintf(&result, "{ \"result\": %d }", count);
......@@ -227,7 +227,7 @@ Here's an example how a module can expose its property:
KR_MODULE_EXPORT(cache)
Once you load the module, you can call the module property from the interactive console.
*Note* |---| the JSON output will be transparently converted to Lua tables.
*Note:* the JSON output will be transparently converted to Lua tables.
.. code-block:: bash
......@@ -238,7 +238,8 @@ Once you load the module, you can call the module property from the interactive
> cached.get_size()
[size] => 53
*Note* |---| this relies on function pointers, so the same ``static inline`` trick as for the ``Layer()`` is required for C/Go.
.. No idea what this talks about, but kept for now:
.. *Note:* this relies on function pointers, so the same ``static inline`` trick as for the ``Layer()`` is required for C.
Special properties
------------------
......@@ -246,4 +247,3 @@ Special properties
If the module declares properties ``get`` or ``set``, they can be used in the Lua interpreter as
regular tables.
.. |---| unicode:: U+02014 .. em dash
......@@ -105,6 +105,18 @@ static char* dump_frequent(void *env, struct kr_module *module, const char *args
KR_EXPORT
int bogus_log_init(struct kr_module *module)
{
static kr_layer_api_t layer = {
.consume = &consume,
};
layer.data = module;
module->layer = &layer;
static const struct kr_prop props[] = {
{ &dump_frequent, "frequent", "List most frequent queries.", },
{ NULL, NULL, NULL }
};
module->props = props;
struct stat_data *data = malloc(sizeof(*data));
if (!data) {
return kr_error(ENOMEM);
......@@ -126,25 +138,4 @@ int bogus_log_deinit(struct kr_module *module)
return kr_ok();
}
KR_EXPORT
const kr_layer_api_t *bogus_log_layer(struct kr_module *module)
{
static kr_layer_api_t _layer = {
.consume = &consume,
};
_layer.data = module;
return &_layer;
}
KR_EXPORT
struct kr_prop *bogus_log_props(void)
{
static struct kr_prop prop_list[] = {
{ &dump_frequent, "frequent", "List most frequent queries.", },
{ NULL, NULL, NULL }
};
return prop_list;
}
KR_MODULE_EXPORT(bogus_log)
......@@ -47,6 +47,22 @@ static char *cookies_config(void *env, struct kr_module *module,
KR_EXPORT
int cookies_init(struct kr_module *module)
{
/* The function answer_finalize() in resolver is called before any
* .finish callback. Therefore this layer does not use it. */
static kr_layer_api_t layer = {
.begin = &check_request,
.consume = &check_response
};
/* Store module reference */
layer.data = module;
module->layer = &layer;
static const struct kr_prop props[] = {
{ &cookies_config, "config", "Empty value to return current configuration.", },
{ NULL, NULL, NULL }
};
module->props = props;
struct engine *engine = module->data;
struct kr_cookie_ctx *cookie_ctx = &engine->resolver.cookie_ctx;
......@@ -72,29 +88,4 @@ int cookies_deinit(struct kr_module *module)
return kr_ok();
}
KR_EXPORT
const kr_layer_api_t *cookies_layer(struct kr_module *module)
{
/* The function answer_finalize() in resolver is called before any
* .finish callback. Therefore this layer does not use it. */
static kr_layer_api_t _layer = {
.begin = &check_request,
.consume = &check_response
};
/* Store module reference */
_layer.data = module;
return &_layer;
}
KR_EXPORT
struct kr_prop *cookies_props(void)
{
static struct kr_prop prop_list[] = {
{ &cookies_config, "config", "Empty value to return current configuration.", },
{ NULL, NULL, NULL }
};
return prop_list;
}
KR_MODULE_EXPORT(cookies)
......@@ -211,6 +211,13 @@ static int dnstap_log(kr_layer_t *ctx) {
KR_EXPORT
int dnstap_init(struct kr_module *module) {
static kr_layer_api_t layer = {
.finish = &dnstap_log,
};
/* Store module reference */
layer.data = module;
module->layer = &layer;
/* allocated memory for internal data */
struct dnstap_data *data = malloc(sizeof(*data));
if (!data) {
......@@ -368,15 +375,5 @@ int dnstap_config(struct kr_module *module, const char *conf) {
return kr_ok();
}
KR_EXPORT
const kr_layer_api_t *dnstap_layer(struct kr_module *module) {
static kr_layer_api_t _layer = {
.finish = &dnstap_log,
};
/* Store module reference */
_layer.data = module;
return &_layer;
}
KR_MODULE_EXPORT(dnstap)
......@@ -62,15 +62,13 @@ static int edns_keepalive_finalize(kr_layer_t *ctx)
return ctx->state;
}
KR_EXPORT
const kr_layer_api_t *edns_keepalive_layer(struct kr_module *module)
KR_EXPORT int edns_keeapalive_init(struct kr_module *self)
{
static kr_layer_api_t _layer = {
static const kr_layer_api_t layer = {
.answer_finalize = &edns_keepalive_finalize,
};
/* Store module reference */
_layer.data = module;
return &_layer;
self->layer = &layer;
return kr_ok();
}
KR_MODULE_EXPORT(edns_keepalive)
......
......@@ -600,26 +600,30 @@ static char* hint_ttl(void *env, struct kr_module *module, const char *args)
return result;
}
/*
* Module implementation.
*/
/** Basic initialization: get a memory pool, etc. */
KR_EXPORT
const kr_layer_api_t *hints_layer(struct kr_module *module)
int hints_init(struct kr_module *module)
{
static kr_layer_api_t _layer = {
static kr_layer_api_t layer = {
.produce = &query,
};
/* Store module reference */
_layer.data = module;
return &_layer;
}
layer.data = module;
module->layer = &layer;
static const struct kr_prop props[] = {
{ &hint_set, "set", "Set {name, address} hint.", },
{ &hint_del, "del", "Delete one {name, address} hint or all addresses for the name.", },
{ &hint_get, "get", "Retrieve hint for given name.", },
{ &hint_ttl, "ttl", "Set/get TTL used for the hints.", },
{ &hint_add_hosts, "add_hosts", "Load a file with hosts-like formatting and add contents into hints.", },