From: Marek VavruĊĦa Date: Wed, 8 Jul 2015 23:58:43 +0000 (+0200) Subject: doc: updated library doc for developers X-Git-Tag: v1.0.0-beta1~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=60fa1b3e99c9710c30856b05668485b6d65afd4b;p=thirdparty%2Fknot-resolver.git doc: updated library doc for developers --- diff --git a/doc/resolution.png b/doc/resolution.png new file mode 100644 index 000000000..65d50275e Binary files /dev/null and b/doc/resolution.png differ diff --git a/lib/README.rst b/lib/README.rst index 5828ce68a..b00b3bc46 100644 --- a/lib/README.rst +++ b/lib/README.rst @@ -7,8 +7,8 @@ Requirements * libknot_ 2.0 (Knot DNS high-performance DNS library.) -Library layout -============== +For users +========= .. contents:: :depth: 1 @@ -21,19 +21,30 @@ Resolving a name .. note:: Migrating from ``getaddrinfo`` -Using getdns API ----------------- +.. _lib-layers: -.. note:: These are not the droids you're looking for, move along. +For developers +============== -.. _lib-layers: +The resolution process starts with the functions in :ref:`resolve.c `, they are responsible for: + +* reacting to state machine state (i.e. calling consume layers if we have an answer ready) +* interacting with the user (i.e. asking caller for I/O, accepting queries) +* fetching assets needed by layers (i.e. zone cut, next best NS address or trust anchor) + +These we call as *driver*. The driver is not meant to know *"how"* the query is resolved, but rather *"when"* to execute *"what"*. Typically here you can modify or reorder the resolution plan, or request input from the caller. + +.. image:: ../doc/resolution.png + :align: center + +On the other side are *layers*. They are responsible for dissecting the packets and informing the driver about the results. For example, a produce layer can generate a sub-request, a consume layer can satisfy an outstanding query or simply log something, but they should **never** alter resolution plan directly, as it would change "current query" for next-in-line layers (appending to the resolution plan is fine). They also must not block, and may not be paused. + +.. tip:: Layers are executed asynchronously by the driver. If you need some asset beforehand, you can signalize the driver using returning state or current query flags. For example, setting a flag ``QUERY_AWAIT_CUT`` forces driver to fetch zone cut information before the packet is consumed; setting a ``QUERY_RESOLVED`` flag makes it pop a query after the current set of layers is finished; returning ``FAIL`` state makes it fail current query. The important thing is, these actions happen **after** current set of layers is done. Writing layers ============== -The resolver :ref:`library ` leverages the `processing API`_ from the libknot to separate packet processing code -into layers. In order to keep the core library sane and coverable, there are only two built-in layers: -the :c:func:`iterate_layer`, and the :c:func:`rrcache_layer`. +The resolver :ref:`library ` leverages the `processing API`_ from the libknot to separate packet processing code into layers. *Note* |---| This is only crash-course in the library internals, see the resolver :ref:`library ` documentation for the complete overview of the services. @@ -55,6 +66,8 @@ resolution context, resolution plan and also the final answer. You're likely to struct kr_query *query = kr_rplan_current(request->rplan); } +.. warning:: Never replace or push new queries onto the resolution plan, this is a job of the resolution driver. Single pass through layers expects *current query* to be constant. You can however signalize driver with requests using query flags, like ``QUERY_RESOLVED`` to mark it as resolved. + This is only passive processing of the incoming answer. If you want to change the course of resolution, say satisfy a query from a local cache before the library issues a query to the nameserver, you can use states (see the :ref:`Static hints ` for example). .. code-block:: c @@ -68,7 +81,7 @@ This is only passive processing of the incoming answer. If you want to change th if (can_satisfy(cur)) { /* This flag makes the resolver move the query * to the "resolved" list. */ - query->resolved = true; + query->flags |= QUERY_RESOLVED; return KNOT_STATE_DONE; } @@ -76,8 +89,7 @@ This is only passive processing of the incoming answer. If you want to change th return ctx->state; } -It is possible to not only act during the query resolution, but also to view the complete resolution plan afterwards. -This is useful for analysis-type tasks, or *"on-resolution"* hooks. +It is possible to not only act during the query resolution, but also to view the complete resolution plan afterwards. This is useful for analysis-type tasks, or *"per answer"* hooks. .. code-block:: c