Commit a91694a4 authored by Jan Včelák's avatar Jan Včelák 🚀

move requestor from libknot to knot

parent 8b3fe591
......@@ -115,9 +115,6 @@ nobase_libknot_la_HEADERS = \
libknot/packet/pkt.h \
libknot/packet/rrset-wire.h \
libknot/packet/wire.h \
libknot/processing/layer.h \
libknot/processing/overlay.h \
libknot/processing/requestor.h \
libknot/rdata.h \
libknot/rdataset.h \
libknot/rrset-dump.h \
......@@ -153,9 +150,6 @@ libknot_la_SOURCES = \
libknot/packet/pkt.c \
libknot/packet/rrset-wire.c \
libknot/packet/wire.c \
libknot/processing/layer.c \
libknot/processing/overlay.c \
libknot/processing/requestor.c \
libknot/rdata.c \
libknot/rdataset.c \
libknot/rrset-dump.c \
......@@ -336,8 +330,14 @@ libknotd_la_SOURCES = \
knot/nameserver/update.h \
knot/query/capture.c \
knot/query/capture.h \
knot/query/layer.c \
knot/query/layer.h \
knot/query/overlay.c \
knot/query/overlay.h \
knot/query/query.c \
knot/query/query.h \
knot/query/requestor.c \
knot/query/requestor.h \
knot/common/evsched.c \
knot/common/evsched.h \
knot/common/fdset.c \
......
......@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libknot/processing/requestor.h"
#include "knot/query/requestor.h"
#include "knot/common/log.h"
#include "knot/modules/dnsproxy.h"
#include "knot/query/capture.h"
......
......@@ -25,7 +25,7 @@
#pragma once
#include "libknot/packet/pkt.h"
#include "libknot/processing/layer.h"
#include "knot/query/layer.h"
/* Query data (from query processing). */
struct query_data;
......
......@@ -24,7 +24,7 @@
#pragma once
#include "libknot/processing/layer.h"
#include "knot/query/layer.h"
#include "knot/server/server.h"
#include "knot/updates/acl.h"
#include "contrib/sockaddr.h"
......
......@@ -16,7 +16,7 @@
#pragma once
#include "libknot/processing/layer.h"
#include "knot/query/layer.h"
#include "libknot/packet/pkt.h"
/*!
......
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -17,7 +17,7 @@
#include <assert.h>
#include "libknot/attribute.h"
#include "libknot/processing/layer.h"
#include "knot/query/layer.h"
/*! \brief Helper for conditional layer call. */
#define LAYER_CALL(layer, func, ...) \
......
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file layer.h
*
* \author Marek Vavrusa <marek.vavrusa@nic.cz>
*
* \addtogroup query_processing
* @{
*/
#pragma once
......@@ -111,5 +103,3 @@ int knot_layer_consume(knot_layer_t *ctx, knot_pkt_t *pkt);
* \return Layer state.
*/
int knot_layer_produce(knot_layer_t *ctx, knot_pkt_t *pkt);
/*! @} */
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,7 @@
*/
#include "libknot/attribute.h"
#include "libknot/processing/overlay.h"
#include "knot/query/overlay.h"
#include "libknot/errcode.h"
#include "contrib/mempattern.h"
#include "contrib/ucw/lists.h"
......
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -13,18 +13,10 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file overlay.h
*
* \author Marek Vavrusa <marek.vavrusa@nic.cz>
*
* \addtogroup query_processing
* @{
*/
#pragma once
#include "libknot/processing/layer.h"
#include "knot/query/layer.h"
/*! \brief Processsing overlay (list of aggregated FSMs). */
struct knot_overlay {
......@@ -99,5 +91,3 @@ int knot_overlay_consume(struct knot_overlay *overlay, knot_pkt_t *pkt);
* \return Overlay state.
*/
int knot_overlay_produce(struct knot_overlay *overlay, knot_pkt_t *pkt);
/*! @} */
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -17,7 +17,7 @@
#include <assert.h>
#include "libknot/attribute.h"
#include "libknot/processing/requestor.h"
#include "knot/query/requestor.h"
#include "libknot/errcode.h"
#include "contrib/mempattern.h"
#include "contrib/net.h"
......
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,7 +19,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include "libknot/processing/overlay.h"
#include "knot/query/overlay.h"
#include "libknot/rrtype/tsig.h"
#include "libknot/mm_ctx.h"
......
......@@ -37,7 +37,7 @@
#include "knot/common/fdset.h"
#include "knot/common/log.h"
#include "knot/nameserver/process_query.h"
#include "libknot/processing/overlay.h"
#include "knot/query/overlay.h"
#include "contrib/macros.h"
#include "contrib/mempattern.h"
#include "contrib/net.h"
......
......@@ -48,9 +48,6 @@
#include "libknot/packet/pkt.h"
#include "libknot/packet/rrset-wire.h"
#include "libknot/packet/wire.h"
#include "libknot/processing/layer.h"
#include "libknot/processing/overlay.h"
#include "libknot/processing/requestor.h"
#include "libknot/rrtype/aaaa.h"
#include "libknot/rrtype/dnskey.h"
#include "libknot/rrtype/ds.h"
......
# libknot processing interface
libknot provides generic interfaces for producer/consumer type problems and a way to layer them.
This is heavily leveraged for packet processing and modules, and enables us to build independent
data processors and state machines driving them.
## Building blocks
### layer.h
layer represents a set of functions implementing an interface, with 5 possible callbacks:
```c
int begin(knot_layer_t *ctx, void *layer_param);
int reset(knot_layer_t *ctx);
int finish(knot_layer_t *ctx);
int consume(knot_layer_t *ctx, knot_pkt_t *pkt);
int produce(knot_layer_t *ctx, knot_pkt_t *pkt);
int fail(knot_layer_t *ctx, knot_pkt_t *pkt);
```
An good example of the layer is a [query processor](../../knot/nameserver/process_query.c), where, to give you an example,
an action `consume` represents query-parsing step, `produce` represents answer generator and `fail` an error response generator.
*Note that*, a layer does not assume anything about the driver, but may enforce call order by requiring the context to be in a specific
processing state, see `knot_layer_t.state`, and move the driver to next desired state.
For example, operation `consume` may require the driver to be in `KNOT_STATE_NOOP` and emit:
* `KNOT_STATE_FAIL` if the query is wrong
* `KNOT_STATE_DONE` if the query doesn't warrant an answer
* `KNOT_STATE_PRODUCE` if it found an answer
* `KNOT_STATE_CONSUME` if it requires more queries
*Note that*, I'm using terms "state" and "action" very loosely. State is usually written capitalized and action in lowercase.
They are named similarly as they're usually cause and effect, a `CONSUME` state leads to `consume` reaction, but that's not always the case.
### overlay.h
An overlay is a stack of layers. It provides similar interface as layer, but their actions are chained.
The call order goes from the first to the last for all actions. The state emitted from the previous action is
given as an input to the next action. Example:
```c
/* Stack layers. */
knot_overlay_add(overlay, first, param1);
knot_overlay_add(overlay, second, param2);
knot_overlay_add(overlay, third, param3);
/* Execute */
knot_overlay_consume(overlay, pkt);
```
Leads to following execution:
```
consume(first, pkt)
=> consume(second, pkt)
=> consume(third, pkt) => FINAL_STATE
```
*Note that*, an overlay calls `begin` operation as soon as a layer is added into the overlay.
### requestor.h
A requestor is a specific state-machine that in general:
1. prepares a query by passing it to the `produce` overlay action
2. sends the query and receives response
3. consumes the response by passing it to the `consume` overlay action
The query may not always be produced, and the I/O or `consume` action may fail,
so we get a state machine roughly like this:
![Requestor state machine](doc/requestor.png)
The actual requestor also resets the overlay after each failed attempt, so for example a query may be retransmitted,
but you get the idea.
The requestor is used for various tasks from server-initiated connections to forwarding queries, and the system of modules
allows you to extend these operations by adding new layers. A query log might be a good example, as you can monitor not only the
sent queries and received responses, but also the state of the query processor.
## Example
### Query log
Here's an example of a query log, that can track incoming queries and error responses.
```c
/*! Track incoming queries. */
static int dnstrack_query(knot_layer_t *ctx, knot_pkt_t *pkt)
{
char qname[KNOT_DNAME_MAXLEN];
knot_dname_to_str(qname, knot_pkt_qname(pkt), sizeof(qname));
printf("=> query '%s', parser state: %d\n", qname, ctx->state);
return ctx->state; /* Pass-through */
}
/*! Track error responses. */
static int dnstrack_fail(knot_layer_t *ctx, knot_pkt_t *pkt)
{
char qname[KNOT_DNAME_MAXLEN];
knot_dname_to_str(qname, knot_pkt_qname(pkt), sizeof(qname));
printf("=> answer to '%s', rcode: %d\n",
qname, knot_wire_get_rcode(pkt->wire));
return ctx->state;
}
/*! Module implementation. */
const knot_layer_api_t *dnstrack_layer(void)
{
static const knot_layer_api_t api = {
.consume = &dnstrack_query,
.fail = &dnstrack_fail
};
return &api;
}
```
Now you can try it in an overlay. The following is a simplified snippet from the UDP query processor,
to showcase the real-world usage:
```c
/* Prepare overlay */
struct knot_overlay overlay;
knot_overlay_init(&overlay, NULL);
knot_overlay_add(&overlay, process_query_layer(), &param);
knot_overlay_add(&overlay, dnstrack_layer(), NULL);
/* Process packet */
int state = knot_overlay_consume(&overlay, query);
while (state & (KNOT_STATE_PRODUCE|KNOT_STATE_FAIL)) {
state = knot_overlay_produce(&overlay, answer);
}
/* Finalize. */
knot_overlay_finish(&overlay);
knot_overlay_deinit(&overlay);
```
......@@ -22,8 +22,8 @@
#include <fcntl.h>
#include "knot/conf/conf.h"
#include "libknot/processing/layer.h"
#include "libknot/processing/requestor.h"
#include "knot/query/layer.h"
#include "knot/query/requestor.h"
#include "contrib/mempattern.h"
#include "contrib/net.h"
#include "contrib/sockaddr.h"
......
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