- code documentation on the module interface.

git-svn-id: file:///svn/unbound/trunk@3074 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2014-02-06 13:18:32 +00:00
parent 3997b79936
commit 5865ec4067
2 changed files with 113 additions and 0 deletions

View file

@ -1,5 +1,6 @@
6 February 2014: Wouter
- sldns has type HIP.
- code documentation on the module interface.
5 February 2014: Wouter
- Fix sldns parse tests on osx.

View file

@ -37,6 +37,118 @@
* \file
*
* This file contains the interface for DNS handling modules.
*
* The module interface uses the DNS modules as state machines. The
* state machines are activated in sequence to operate on queries. Once
* they are done, the reply is passed back. In the usual setup the mesh
* is the caller of the state machines and once things are done sends replies
* and invokes result callbacks.
*
* The module provides a number of functions, listed in the module_func_block.
* The module is inited and destroyed and memory usage queries, for the
* module as a whole, for entire-module state (such as a cache). And per-query
* functions are called, operate to move the state machine and cleanup of
* the per-query state.
*
* Most per-query state should simply be allocated in the query region.
* This is destroyed at the end of the query.
*
* The module environment contains services and information and caches
* shared by the modules and the rest of the system. It also contains
* function pointers for module-specific tasks (like sending queries).
*
* *** Example module calls for a normal query
*
* In this example, the query does not need recursion, all the other data
* can be found in the cache. This makes the example shorter.
*
* At the start of the program the iterator module is initialised.
* The iterator module sets up its global state, such as donotquery lists
* and private address trees.
*
* A query comes in, and a mesh entry is created for it. The mesh
* starts the resolution process. The validator module is the first
* in the list of modules, and it is started on this new query. The
* operate() function is called. The validator decides it needs not do
* anything yet until there is a result and returns wait_module, that
* causes the next module in the list to be started.
*
* The next module is the iterator. It is started on the passed query and
* decides to perform a lookup. For this simple example, the delegation
* point information is available, and all the iterator wants to do is
* send a UDP query. The iterator uses env.send_query() to send the
* query. Then the iterator suspends (returns from the operate call).
*
* When the UDP reply comes back (and on errors and timeouts), the
* operate function is called for the query, on the iterator module,
* with the event that there is a reply. The iterator decides that this
* is enough, the work is done. It returns the value finished from the
* operate call, which causes the previous module to be started.
*
* The previous module, the validator module, is started with the event
* that the iterator module is done. The validator decides to validate
* the query. Once it is done (which could take recursive lookups, but
* in this example no recursive lookups are needed), it returns from the
* operate function with finished.
*
* There is no previous module from the validator module, and the mesh
* takes this to mean that the query is finally done. The mesh invokes
* callbacks and sends packets to queriers.
*
* If other modules had been waiting (recursively) on the answer to this
* query, then the mesh will tell them about it. It calls the inform_super
* routine on all the waiting modules, and once that is done it calls all of
* them with the operate() call. During inform_super the query that is done
* still exists and information can be copied from it (but the module should
* not really re-entry codepoints and services). During the operate call
* the modules can use stored state to continue operation with the results.
* (network buffers are used to contain the answer packet during the
* inform_super phase, but after that the network buffers will be cleared
* of their contents so that other tasks can be performed).
*
* *** Example module calls for recursion
*
* A module is called in operate, and it decides that it wants to perform
* recursion. That is, it wants the full state-machine-list to operate on
* a different query. It calls env.attach_sub() to create a new query state.
* The routine returns the newly created state, and potentially the module
* can edit the module-states for the newly created query (i.e. pass along
* some information, like delegation points). The module then suspends,
* returns from the operate routine.
*
* The mesh meanwhile will have the newly created query (or queries) on
* a waiting list, and will call operate() on this query (or queries).
* It starts again at the start of the module list for them. The query
* (or queries) continue to operate their state machines, until they are
* done. When they are done the mesh calls inform_super on the module that
* wanted the recursion. After that the mesh calls operate() on the module
* that wanted to do the recursion, and during this phase the module could,
* for example, decide to create more recursions.
*
* If the module decides it no longer wants the recursive information
* it can call detach_subs. Those queries will still run to completion,
* potentially filling the cache with information. Inform_super is not
* called any more.
*
* The iterator module will fetch items from the cache, so a recursion
* attempt may complete very quickly if the item is in cache. The calling
* module has to wait for completion or eventual timeout. A recursive query
* that times out returns a servfail rcode (servfail is also returned for
* other errors during the lookup).
*
* Results are passed in the qstate, the rcode member is used to pass
* errors without requiring memory allocation, so that the code can continue
* in out-of-memory conditions. If the rcode member is 0 (NOERROR) then
* the dns_msg entry contains a filled out message. This message may
* also contain an rcode that is nonzero, but in this case additional
* information (query, additional) can be passed along.
*
* The rcode and dns_msg are used to pass the result from the the rightmost
* module towards the leftmost modules and then towards the user.
*
* If you want to avoid recursion-cycles where queries need other queries
* that need the first one, use detect_cycle() to see if that will happen.
*
*/
#ifndef UTIL_MODULE_H