Przeglądaj źródła

SIP Express Router Developer's Guide

Jan Janak 23 lat temu
rodzic
commit
8a6a19fa12
1 zmienionych plików z 5083 dodań i 0 usunięć
  1. 5083 0
      doc/serdev/serdev.sgml

+ 5083 - 0
doc/serdev/serdev.sgml

@@ -0,0 +1,5083 @@
+<!DOCTYPE Book SYSTEM "/usr/share/sgml/docbook/dtd-4.2/docbook.dtd">
+
+<book label="serdev" id="serdev" lang="EN">
+    <title>SIP Express Router</title>
+    <subtitle>The Developer's Guide</subtitle>
+    <bookinfo>
+	<authorgroup>
+	    <author>
+		<firstname>Jan</firstname>
+		<surname>Janak</surname>
+		<email>[email protected]</email>
+	    </author>
+	</authorgroup>
+	
+	<copyright>
+	    <year>2001</year>
+	    <year>2002</year>
+	    <holder>FhG Fokus</holder>
+	</copyright>
+	<legalnotice>
+	    <para>
+		This documentation is free software; you can redistribute
+		it and/or modify it under the terms of the GNU General Public
+ 		License as published by the Free Software Foundation; either
+		version 2 of the License, or (at your option) any later
+		version.
+	    </para>
+	    
+	    <para>
+		This program is distributed in the hope that it will be
+		useful, but WITHOUT ANY WARRANTY; without even the implied
+		warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+		See the GNU General Public License for more details.
+	    </para>
+	    
+	    <para>
+		You should have received a copy of the GNU General Public
+		License along with this program; if not, write to the Free
+		Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+		MA 02111-1307 USA
+	    </para>
+	    
+	    <para>
+		For more details see the file COPYING in the source
+		distribution of SER.
+	    </para>	    
+	</legalnotice>
+
+	<abstract>
+	    <para>
+		The document describes the SIP Express Router internals and algorithms. It describes
+		overall server architecture, request processing, configuration, memory management,
+		interprocess locking, module interface and selected modules in detail.
+	    </para>
+
+	    <para>
+		The document is intended mainly for module developers wishing to implement
+		a new module for the server. Other people like developers of SIP related
+		software or students might be interested too.
+	    </para>
+	</abstract>
+
+    </bookinfo>
+    
+    <toc></toc>
+    
+    <chapter id="server-startup">
+	<title>The Server Startup</title>
+	<para>
+	    The <function moreinfo="none">main</function> function in file <filename moreinfo="none">main.c</filename>
+	    is the first function called when the server is started. It's purpose is to initialize the server and
+	    enter main loop. The server initialization will be described in the following sections.
+	</para>
+	
+	<para>
+	    The particular initialization steps are describe in order in which they appear in the 
+	    <function>main</function> function.
+	</para>
+	
+	<section id="signal-installation">
+	    <title>Installation Of New Signal Handlers</title>
+	    <para>
+		The first step in the initialization process is the installation of new signal handlers. We need
+		our own signal handlers to be able to do gracefull shutdown, print statistics and so on. There is
+		only one signal handler function which is function <function moreinfo="none">sig_usr</function> in
+		file <filename moreinfo="none">main.c</filename>.
+	    </para>
+	    <para>
+		The following signals are handled by the function: SIGINT, SIGPIPE, SIGUSR1, SIGCHLD, SIGTERM, SIGHUP and
+		SIGUSR2.
+	    </para>
+	</section> <!-- signal-installation -->
+	
+	<section id="cmd-line-params">
+	    <title>Processing Command Line Parameters</title>
+	    <para>
+		<acronym>SER</acronym> utilizes <acronym>GNU</acronym><function moreinfo="none">getopt</function>function to 
+		parse command line parameters.
+		The function is extensively described in the man pages.
+	    </para>
+	</section> <!-- cmd-line-params -->
+	
+	<section id="parser-init">
+	    <title>Parser Initialization</title>
+	    <para>
+		<acronym>SER</acronym> contains fast 32-bit parser. The parser uses precalculated hash table that needs to be
+		filled in upon startup. The initialization is done here, there are two functions that do the
+		job. Function <function moreinfo="none">init_hfname_parser</function> initializes hash table
+		in header field name parser and function <function moreinfo="none">init_digest_parser</function>
+		initializes hash table in digest authentication parser. The parsers' internals will be described
+		later.
+	    </para>
+	</section> <!-- parser-init -->
+	
+	<section id="hash-init">
+	    <title>Hash Table Initialization</title>
+	    <para>TBD.</para>
+	</section> <!-- hash-init -->
+	
+	<section id="malloc-init">
+	    <title>Malloc Initialization</title>
+	    <para>
+		To make <acronym>SER</acronym> even faster we decided to reimplement memory allocation routines. The new 
+		<function moreinfo="none">malloc</function>
+		better fits our needs and speeds up the server a lot. The memory management subsystem needs
+		to be initialized upon server startup. The initialization mainly creates internal data
+		structures and allocates memory region to be partitioned.
+	    </para>
+	    
+	    <important>
+		<para>
+		    The memory allocation code must be initialized <emphasis>BEFORE</emphasis> any of its function is called !
+		</para>
+	    </important>
+	</section> <!-- malloc-init -->
+	
+	<section id="timer-init">
+	    <title>Timer Initialization</title>
+	    <para>
+		Various subsystems of the server must be called periodically regardless of the incoming
+		requests. That's what timer is for. Function <function moreinfo="none">init_timer</function>
+		initializes the timer subsystems. The function is called from <filename moreinfo="none">main.c</filename>
+		and can be found in <filename moreinfo="none">timer.c</filename> The timer subsystem will
+		be described later.
+	    </para>
+	    <warning>
+		<para>
+		    Timer subsystem must be initialize before config file is parsed !
+		</para>
+	    </warning>
+	</section> <!-- timer-init -->
+
+	<section id="fifo-init">
+	    <title><acronym>FIFO</acronym> initialization</title>
+	    <para>
+		<acronym>SER</acronym> has built-in support for <acronym>FIFO</acronym> control. It means that the 
+		running server can accept
+		commands over a fifo device. Function <function moreinfo="none">register_core_fifo</function> 
+		initializes <acronym>FIFO</acronym> subsystem and registers basic commands, that are processed by the core
+		itself. The function can be found in file <filename moreinfo="none">fifo_server.c</filename>.
+	    </para>
+	    <para>
+		The <acronym>FIFO</acronym> server will be described later.
+	    </para>
+	</section> <!-- fifo-init -->
+	
+	<section id="builtin-mod-reg">
+	    <title>Builtin Module Initialization</title>
+	    <para>
+		Modules can be either loaded dynamically at runtime or compiled in statically. When a module
+		is loaded at runtime, it is registered
+		<footnote id="regfoot">
+		    <para>
+			Module registration is a process when the core tries to find what functions and
+			parameters are offered by the module.
+		    </para>
+		</footnote>
+		immediatelly with the 
+		core. When the module is compiled in statically, the registration<footnoteref linkend="regfoot"> 
+		must be performed upon server startup. Function 
+		<function moreinfo="none">register_buildin_modules</function> does the job.
+	    </para>
+	</section> <!-- builtin-mod-reg -->
+
+	<section id="ser-config">
+	    <title>Server Configuration</title>
+	    <para>
+		The server is configured using a configuration file. The configuration file
+		is C-Shell like script which defines how incoming requests should be processed.
+		
+		The file cannot be interpreted directly because that would be very slow. Instead
+		of that the file is translated into an internal binary representation. The process
+		is called compilation and will be described in the following sections.
+	    </para>
+	    <note>
+		<para>
+		    The following sections only describe how the internal binary representation is
+		    being constructed from the config file. The way how the binary representation is used
+		    upon a request arrival will be described later.
+		</para>
+	    </note>
+	    <para>The compilation can be divided in several steps:</para>
+	    
+	    <section id="lex-analysis">
+		<title>Lexical Analysis</title>
+		<para>
+		    Lexical analysis is a process of converting the input (the configuration file in this
+		    case) into a stream of tokens. A token is a set of characters that
+		    'belong' together. Program, that can turn the input into stream of tokens is
+		    called scanner. For example, when scanner encounters a number in the config
+		    file, it will produce token NUMBER.
+		</para>
+		<para>
+		    There is no need to implement the scanner from scratch, it can be done automatically.
+		    There is a utility called flex. Flex accepts a configuration file and generates
+		    scanner according to the configuration file. The configuration file for flex consists
+		    of several lines - each line describing one token. The tokens are described using
+		    regular expressions. For more details, see flex manual page or info documentation.
+		</para>
+		<para>
+		    The input file for the <acronym>SER</acronym> config file is in file 
+		    <filename moreinfo="none">cfg.lex</filename>. The file is processed by flex when the
+		    server is being compiled and the result is written in file 
+		    <filename moreinfo="none">lex.yy.c</filename>. The output file contains the scanner
+		    implemented in C language.
+		</para>
+	    </section> <!-- lex-analysis -->
+	    
+	    <section id="syntax-analysis">
+		<title>Syntactical Analysis</title>
+		<para>
+		    The second stage of configuration file processing is called syntactical analysis. Purpose
+		    of syntactical analysis is to check if the configuration file has been well formed, doesn't
+		    contain syntactical errors and perform various actions at various stages of the analysis.
+		    Program performing syntactical analysis is called parser.
+		</para>
+		<para>
+		    Structure of the configuration file is described using grammar. Grammar is a set of rules
+		    describing valid 'order' or 'combination' of tokens. If the file doesn't conform with it's
+		    grammar, it is syntactically invalid and cannot be further processed. In that case an error
+		    will be issued.
+		</para>
+		<para>
+		    There is a utility called Bison. Input of the utility is a file containing the grammar of
+		    the configuration file, in addition to the grammar, you can describe what action the parser
+		    should do at various stages of parsing. For example, you can instruct the parser to create a
+		    structure describing an IP address every time it finds the IP address in the configuration
+		    file and convert the address to binary representation.
+		</para>
+		<para>For more information see Bison documentation.</para>
+		<para>
+		    Bison creates the parser when the server is being compiled from the sources.
+		    Input file for bison is <filename moreinfo="none">cfg.y</filename>. The file contains grammar
+		    of the config file along with actions that create the binary representation of the file.
+		    Bison will write its result into file <filename moreinfo="none">cfg.tab.c</filename>. The
+		    file contains function <function moreinfo="none">yyparse</function> which will parse the whole
+		    configuration file and construct the binary representation. For more information about the
+		    bison input file syntax see bison documentation.
+		</para>
+	    </section> <!-- syntax-analysis -->
+
+	    <section id="config-file-struct">
+		<title>Config File Structure</title>
+		<para>
+		    The configuration file consist of three sections, each of the sections will be
+		    described separately.
+		</para>
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>Route Statement</emphasis> - The statement describes how incoming requests 
+			    will be processed.
+			    When a request is received, commands in one or more route sections will be executed
+			    in turn. The config file must always contain one main route statement and may contain
+			    several additional route statemens. Request processing always starts at the beginning
+			    of the main route statement. Additional route statements can be called from the main
+			    one or another additional route statements (It it simmilar to function calling).
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>Assign Statement</emphasis> - There are many configuration variables across 
+			    the server and this
+			    statement makes it possible to change their value. Generally it is a list of assignments,
+			    each assignment on a separate line.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>Module Statement</emphasis> - Additional funcionality of the server is 
+			    available through separate
+			    modules. Each module is a shared object that can be loaded at runtime. Modules can
+			    export functions, that can be called from the configuration file and variables, that
+			    can be configured from the config file. The module statement makes it possible to load
+			    modules and configure them. There are two commands in the statement - 
+			    <function moreinfo="none">loadmodule</function> and <function moreinfo="none">loadparam</function>. 
+			    The first can load a module. The second one can configure module's internal
+			    variables.
+			</para>
+		    </listitem>
+		</itemizedlist>
+		<para>
+		    In the following sections we will describe in detail how the three sections are being processed 
+		    upon server startup.
+		</para>
+
+		<section id="route-stm">
+		    <title>Route Statement</title>
+		    <para>The following grammar snippet describes how the route statement is constructed</para>
+		    <programlisting format="linespecific">
+route_stm = "route" "{" actions "}"  { $$ = push($3, &amp;rlist[DEFAULT_RT]); ) }
+			
+actions   = actions action           { $$ = append_action($1, $2}; }
+	  | action                   { $$ = $1; }
+
+action    = cmd SEMICOLON            { $$ = $1; }
+	  | SEMICOLON                { $$ = 0; }
+
+cmd       = "forward" "(" host ")"   { $$ = mk_action(FORWARD_T, STRING_ST, NUMBER_ST, $3, 0);
+	  | ...
+</programlisting>
+
+		    <para>
+			A config file can contain one or more "route" statements. "route" statement without
+			number will be executed first and is called the main route statement. There can be
+			additional route statements identified by number, these additional route statements
+			can be called from the main route statement or another additional route statements.
+		    </para>
+		    <para>
+			Each route statement consists of a set of actions. Actions in the route statement are
+			executed step by step in the same order they appear in the config file. Actions in the 
+			route statement are delimited by semicolon.
+		    </para>
+		    <para>
+			Each action consists of one and only one command (cmd in the grammar). There are many types
+			of commands defined. We don't list all of them here because the list would be too long and all the
+			commands are processed in the same way. Therefore we show only one example (forward) and
+			interested readers might look in <filename moreinfo="none">cfg.y</filename> file for
+			full list of available commands.
+		    </para>
+		    <para>
+			Each rule in the grammar contains a section enclosed in curly braces. The section is C code
+			snippet that will be executed every time the parser recognizes that rule in the config file.
+		    </para>
+		    <para>
+			For example, when the parser finds <function moreinfo="none">forward</function> command, 
+			<function moreinfo="none">mk_action</function> function (as specified in the
+			grammar snippet above) will be called. The function creates a new structure of type FORWARD_T
+			representing the command. Pointer to the structure will be returned as the return value of the
+			rule.
+		    </para>
+		    <para>
+			The pointer propagates through action rule to actions rule. Actions rule will create linked
+			list of all commands. The linked list will be then inserted into route table.
+			(Function <function moreinfo="none">push</function> in rule route_stm).
+			Each element of the table represents one route statement of the config file.
+		    </para>
+		    <para>
+			Each route statement of the configuration file will be represented by a linked list of all
+			actions in the statement. Pointers to all the lists will be stored in rlist array. Additional
+			route statements are identified by number. The number also serves as index to the table.
+		    </para>
+		    <para>
+			When the core is about to execute route statement with number n, it will look in the table
+			at position n. If the element at position n is not null then there is a linked list of
+			commands and the commands will be executed in sequence.
+		    </para>
+		    <para>
+			Reply-Route statement is translated in the same way. Main differences are:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    Reply-Route statement is executed when a <emphasis>REPLY</emphasis> comes 
+				    (not <emphasis>REQUEST</emphasis>).
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    Only subset of commands is allowed in the reply-route statement.
+				    (See file <filename moreinfo="none">cfg.y</filename> for more details).
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>Reply-route statement has it's own array of linked-lists.</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>		    
+		</section> <!-- route-stm -->
+		
+		<section id="assign-stm">
+		    <title>Assign Statement</title>
+		    <para>
+			The server contains many configuration variables. There is a section of the
+			config file in which the variables can be assigned new value. The section
+			is called The Assign Statement. The following grammar snippet describes how the section
+			is constructed (only one example will be shown):
+		    </para>
+		    <programlisting format="linespecific">
+assign_stm = "children" '=' NUMBER { children_no=$3; }
+	   | "children" '=' error  { yyerror("number expected"); } 
+...
+</programlisting>
+		    <para>
+			The number in the config file is assigned to <varname>children_no</varname> variable. 
+			The second statement will be executed if the parameter is not number or is in invalid 
+			format and will issue a warning.
+		    </para>
+		</section> <!-- assign-stm -->
+		
+		<section id="module-stm">
+		    <title>Module Statement</title>
+		    <para>
+			The module statement allows module loading and configuration. There are two commands:
+		    </para>
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>loadmodule</emphasis> - load the specified module in form of shared object. 
+				The shared object will be loaded using <function moreinfo="none">dlopen</function>.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>modparam</emphasis> - It is possible to configure a module using this 
+				command. The command accepts 3 parameters: module name, variable name and variable value.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		    <para>The following grammar snippet describes the module statement:</para>
+		    <programlisting format="linespecific">
+module_stm = "loadmodule" STRING { DBG("loading module %s\n", $2);
+                                   if (load_module($2)!=0) {
+                                       yyerror("failed to load module");
+                                   }
+                                 }
+	   | "loadmodule" error	 { yyerror("string expected");  }
+	   | "modparam" "(" STRING "," STRING "," STRING ")" 
+			{
+			    if (set_mod_param($3, $5, STR_PARAM, $7) != 0) {
+			        yyerror("Can't set module parameter");
+			    }
+			}
+	   | "modparam" "(" STRING "," STRING "," NUMBER ")" 
+			{
+			    if (set_mod_param($3, $5, INT_PARAM, (void*)$7) != 0) {
+			        yyerror("Can't set module parameter");
+			    }
+			}
+	   | MODPARAM error { yyerror("Invalid arguments"); }
+</programlisting>
+		    <para>
+			When the parser finds <function moreinfo="none">loadmodule</function> command, it will execute 
+			statement in curly braces.
+			The statemen will call <function moreinfo="none">load_module</function> function.
+			The function will load the specified filename using <function moreinfo="none">dlopen</function>.
+			If <function moreinfo="none">dlopen</function> was successfull, the server will look for
+			<structname>exports</structname> structure describing the module interface and register the 
+			module. For more details see module section.
+		    </para>
+		    <para>
+			If the parser finds <function moreinfo="none">modparam</function> command, it will try to configure 
+			the specified variable in the
+			specified module. The module must be loaded using <function moreinfo="none">loadmodule</function>
+			before <function moreinfo="none">modparam</function> for the module can be used !
+			Function <function moreinfo="none">set_mod_param</function> will be called and will
+			configure the variable in the specified module.
+		    </para>
+		</section> <!-- module-stm -->
+	    </section> <!-- config-file-struct -->
+	</section> <!-- ser-config -->
+	
+	<section id="iface-config">
+	    <title>Interface Configuration</title>
+	    <para>
+		The server will try to obtain list of all configured interfaces of the host it is running on. If it
+		fails the server tries to convert hostname to IP address and will use interface with the IP address
+		only.
+	    </para>
+	    <para>
+		Function <function moreinfo="none">add_interfaces</function> will add all configured interfaces to the
+		array.
+	    </para>
+	    <para>
+		Try to convert all interface names to IP addresses, remove duplicates...
+	    </para>
+	</section> <!-- iface-config -->
+	
+	<section id="daemon">
+	    <title>Turning into a Daemon</title>
+	    <para>
+		When configured so, ser becomes a daemon during startup. A process is called daemon
+		when it hasn't associated controlling terminal. See function 
+		<function moreinfo="none">daemonize</function> in file 
+		<filename moreinfo="none">main.c</filename> for more details.
+		The function does the following:
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<emphasis>chroot</emphasis> is performed if neccessary. That ensures that the server will have
+			access to a particular directory and subdirectories only.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			Server's working directory is changed if the new working directory was
+			specified.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			If command line parameter -g was used, the server's group ID is changed
+			to that value.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			If command line parameter -u was used, the server's user ID is changed
+			to that value.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			Perform <emphasis>fork</emphasis>, let the parent process exit. This ensures that we 
+			are not a group leader.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			Perform <emphasis>setsid</emphasis> to become a session leader and drop the controlling 
+			terminal.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			Fork again to drop group leadership.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>Create a pid file.</para>
+		</listitem>
+		<listitem>
+		    <para>Close all opened file descriptors.</para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- daemon -->
+	
+	<section id="module-init">
+	    <title>Module Initialization</title>
+	    <para>
+		The whole config file was parsed, all modules were loaded already and can
+		be initialized now. A module can tell the core that it needs to be initialized
+		by exporting <function moreinfo="none">mod_init</function> function.
+		<function moreinfo="none">mod_init</function> function of all loaded modules
+		will be called now.
+	    </para>
+	</section> <!-- module-init -->
+
+	<section id="rt-list-fix">
+	    <title>Routing List Fixing</title>
+	    <para>
+		After the whole routing list was parsed, there might be still places that can be
+		further processed to speed-up the server. For example, several commands accept
+		regular expression as one of their parameters. The regular expression can be compiled
+		too and processing of compiled expression will be much faster.
+	    </para>
+	    <para>
+		Another example might be string as parameter of a function. For example if you call
+		<function moreinfo="none">append_hf("Server: SIP Express Router\r\n")</function> from the routing 
+		script, the function will 
+		append a new header field after the last one. In this case, the function needs to know length 
+		of the string parameter. It could call <function moreinfo="none">strlen</function> every time it is
+		called, but that is not a very good idea because <function moreinfo="none">strlen</function> would
+		be called every time a message is processed and that is not neccessary.
+	    </para>
+	    <para>
+		Instead of that the length of the string parameter could be precalculated upon server startup, saved
+		and reused later. The processing of the request will be faster because 
+		<function moreinfo="none">append_hf</function> doesn't need
+		to call <function moreinfo="none">strlen</function> every time, I can just reuse the saved value.
+	    </para>
+	    <para>
+		This can be used also for string to int conversions, hostname lookups, expression evaluation and so on.
+	    </para>
+	    <para>
+		This process is called Routing List Fixing and will be done as one of last steps of the server startup.
+	    </para>
+	    <para>
+		Every loaded module can export one or more functions. Each such function can have associated a fixup
+		function, which should do fixing as described in this section. All such fixups of all loaded modules
+		will be called here. That makes it possible for module functions to fix their parameters too.
+	    </para>
+	</section> <!-- rt-list-fix -->
+
+	<section id="stat-init">
+	    <title>Statistics Initialization</title>
+	    <para>
+		If compiled-in, the core can produce some statistics about itself and traffic processed. The statistics
+		subsystem gets initialized here, see function <function moreinfo="none">init_stats</function>.
+	    </para>
+	</section> <!-- stat-init -->
+
+	<section id="socket-init">
+	    <title>Socket Initialization</title>
+	    <para>
+		UDP socket initialization depends on <varname>dont_fork</varname> variable. If this variable is set 
+		(only one process will
+		be processing requests) and there are multiple listen interfaces, only the first one will be used. This
+		mode is mainly for debugging.
+	    </para>
+	    <para>
+		If the variable is not set, then sockets for all configured interfaces will be created and initialized.
+		See function <function moreinfo="none">udp_init</function> in file
+		<filename moreinfo="none">udp_server.c</filename> for more details.
+	    </para>
+	</section> <!-- socke-init -->
+	
+	<section id="forking">
+	    <title>Forking</title>
+	    <para>
+		The rest of the initialization process depends on value of <varname>dont_fork</varname> variable. 
+		We will describe both variants separatelly.
+	    </para>
+
+	    <section id="dont-fork-set">
+		<title><varname>dont_fork</varname> is set (not zero)</title>
+		<para>
+		    If <varname>dont_fork</varname> variable is set, the server will be operating in special mode. 
+		    There will be only one process processing incoming requests. This is very slow and was intended mainly 
+		    for debugging purposes. The main process will be proccessing all incoming requests itself.
+		</para>
+		<para>
+		    The server still needs additional children:
+		</para>
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    One child is for the timer subsystem, the child will be processing timers independently of 
+			    the main process.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <acronym>FIFO</acronym> server will spawn another child if enabled. The child will be 
+			    processing all commands comming through the fifo interface.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>If <acronym>SNMP</acronym> support was enabled, another child will be created.</para>
+		    </listitem>
+		</itemizedlist>
+		
+		<para>
+		    The following initialization will be performed in dont fork mode.
+		    (look into function <function moreinfo="none">main_loop</function> in file 
+		    <filename moreinfo="none">main.c</filename>.
+		</para>
+
+		<itemizedlist>
+		    <listitem>
+			<para>Another child will be forked for the timer subsystem.</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    Initialize the <acronym>FIFO</acronym> server if enabled, this will fork another child.
+			    For more info about the <acronym>FIFO</acronym> server, 
+			    see section <acronym>FIFO</acronym> server.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    Call <function moreinfo="none">init_child(0).</function>
+			    The function performs per-child specific initialization of all loaded modules.
+			    A module can be initialized though <function moreinfo="none">mod_init</function> function.
+			    The function is called <emphasis>BEFORE</emphasis> the server forks and thus is common for all 
+			    children.
+			</para>
+			<para>
+			    If there is anything, that needs to be initialized in every child separately (for example
+			    if each child needs to open its own filedescriptor), it cannot be done in 
+			    <function>mod_init</function>.
+			    To make such initialization possible, a module can export another initialization function
+			    called <function moreinfo="none">init_child</function>. The function will be called in
+			    all children <emphasis>AFTER</emphasis> fork of the server.
+			</para>
+			<para>
+			    And since we are in dont fork mode and there will no children processing requests (remember
+			    the main process will be processing all requests), the 
+			    <function moreinfo="none">init_child</function> wouldn't be called.
+			</para>
+			<para>
+			    That would be bad, because <function moreinfo="none">child_init</function> might do some
+			    initialization that must be done otherwise modules might not work properly.
+			</para>
+			<para>
+			    To make sure that module initialization is complete we will call 
+			    <function moreinfo="none">init_child</function> here for the main process even if we
+			    are not going to fork.
+			</para>
+		    </listitem>
+		</itemizedlist>
+		<para>
+		    That's it. Everything has been initialized properly and as the last step we will call
+		    <function moreinfo="none">udp_rcv_loop</function> which is the main loop function. The function
+		    will be described later.
+		</para>
+	    </section> <!-- dont-fork-set -->
+
+	    <section id="dont-fork-not-set">
+		<title><varname>dont_fork</varname> is not set (zero)</title>
+		<para>
+		    <varname>dont_fork</varname> is not set. That means that the server will fork children and the children
+		    will be processing incoming requests. How many childrens will be created depends on
+		    the configuration (<varname>children</varname> variable). The main process will be sleeping and 
+		    handling signals only.
+		</para>
+
+		<para>
+		    The main process will then initialize <acronym>FIFO</acronym> server. The <acronym>FIFO</acronym> server 
+		    needs another child to handle communication over <acronym>FIFO</acronym> and thus another child will be 
+		    created. The <acronym>FIFO</acronym> server will be described in more detail later.
+		</para>
+
+		<para>
+		    Then the main process will perform another fork for the timer attendand. The child will
+		    take care of timer lists and execute specified function when a timer hits.
+		</para>
+		<para>
+		    The main process is now completely initialized, it will sleep in <function moreinfo="none">pause</function>
+		    function untill a signal comes and call <function moreinfo="none">handle_sigs</function> when such
+		    condition occurs.
+		</para>
+		
+		<para>
+		    The following initialization will be performed by each child separately:
+		</para>
+		<para>
+		    Each child executes <function moreinfo="none">init_child</function> function. The function
+		    will in turn call <function moreinfo="none">child_init</function> functions of all loaded modules.
+		</para>
+		<para>
+		    Becuase the function is called in each child separately, it can initialize per-child
+		    specific data. For example if a module needs to communicate with database, it must open
+		    a database connection. If the connection would be opened in <function moreinfo="none">mod_init</function>
+		    function, all the children would share the same connection and locking would be neccessary
+		    to avoid conflicts. In contrast if the connection was opened in
+		    <function moreinfo="none">child_init</function> function, each child will have its own
+		    connection and concurrency conflicts will be handled by the database server.
+		</para>
+		<para>
+		    And last, but not least, each child executes <function moreinfo="none">udp_rcv_loop</function> function
+		    which contains the main loop logic.
+		</para>
+		
+	    </section> <!-- dont-fork-not-set -->
+	</section> <!-- forking -->
+    </chapter> <!-- server-startup -->
+    
+    <chapter id="main-loop">
+	<title>Main Loop</title>
+	<para>
+	    Upon startup, all children execute <function moreinfo="none">recvfrom</function> function. The process will
+	    enter the kernel mode. When there is no data to be processed at the moment, the kernel will put the process on
+	    list of processes waiting for data and the process will be put asleep. 
+	</para>
+	<para>
+	    When data to be processed was received, the first process on the list will be removed from the list and woken
+	    up. After the process finished processing of the data, it will call <function moreinfo="none">recvfrom</function>
+	    again and will be put by the kernel at the end of the list.
+	</para>
+	<para>
+	    When next data arrives, the first process on the list will be removed, processes the data and will be put on the
+	    end of the list again. And so on...
+	</para>
+
+	<para>
+	    The main loop logic can be found in function <function moreinfo="none">udp_rcv_loop</function> in file
+	    <filename moreinfo="none">udp_server.c</filename>.
+	</para>
+	<para>
+	    The message is received using <function moreinfo="none">recvfrom</function> function. The received data is
+	    stored in buffer and null terminated. 
+	</para>
+	<para>
+	    If configured so, basic sanity checks over the received message will be performed.
+	</para>
+	<para>
+	    The message is then processed by <function moreinfo="none">receive_msg</function> function and 
+	    <function moreinfo="none">recvfrom</function> is called again.
+	</para>
+	
+	<section id="recv-message">
+	    <title><function moreinfo="none">receive_msg</function> Function</title>
+	    <para>
+		The function can be found in <filename moreinfo="none">receive.c</filename> file.
+	    </para>
+	    
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			In the server, a request or response is represented by <structname>sip_msg</structname>
+			structure. The structure is allocated in this function. The original message is stored in buf 
+			attribute of the structure and is zero terminated. Then, another copy of the received message will be
+			created and the copy will be stored in orig attribute. The original copy will be not
+			modified during the server operation. All changes will be made to the copy in buf
+			attribute. The second copy of the message will be removed in the future.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			The message will be parsed (function <function moreinfo="none">parse_msg</function>). We don't
+			need the whole message header to be parsed at this stage. Only the first line and first Via
+			header need to be parsed. The server needs to know if the message is request or response - hence
+			the first line. The server also needs the first Via to be able to send a response back - hence
+			the first Via. Nothing else will be parsed at the moment - this saves time. (Message parser
+			as well as <structname>sip_msg</structname> structure will be described later).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			A module may register callbacks. Each callback have associated an event, that
+			will trigger the callback. One such callback is <emphasis>pre-script</emphasis> callback. Such 
+			callback will be called immediatelly before the routing part of the config file will be run. 
+			If there are such callbacks registered, they will be executed now.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			As the next step we will determine the message type. If the message being processed is a REQUEST
+			then basic sanity checks will be performed (make sure that there is the first Via and parsing was
+			successfull) and the message will be passed to routing engine.
+			The routing engine is one of the most complicated parts of the server and will be in detail
+			described in section ...
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			If the message is a RESPONSE, it will be simply forwarded to its destination.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			After all, <emphasis>post-script</emphasis> callbacks will be executed if any and the 
+			structure representing the message will be released.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			Processing of the message is done now and the process is ready for another 
+			<acronym>SIP</acronym> message.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- recv-message -->
+    </chapter> <!-- main-loop -->
+
+    <chapter id="server-shutdown">
+	<title>Server Shutdown</title>
+	<para>
+	    Server shutdown can be triggered by sending a signal to the server. The server will behave differently upon 
+	    receiving various types of signals, here is a brief summary:
+	</para>
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    <emphasis>SIGINT, SIGPIPE, SIGTERM, SIGCHLD</emphasis> will terminate the server.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <emphasis>SIGUSR1</emphasis> will print statistics and let the server continue.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <emphasis>SIGHUP, SIGUSR2</emphasis> will be ignored.
+		</para>
+	    </listitem>
+	</itemizedlist>
+	
+	<para>
+	    There is only one common signal handler for all signals - function <function moreinfo="none">sig_usr</function>
+	    in file <filename moreinfo="none">main.c</filename>.
+	</para>
+
+	<para>
+	    In normal mode of operation (<varname>dont_fork</varname> is not set), the main server is not processing any 
+	    requests, it calls <function moreinfo="none">pause</function> function and will be waiting for signals only. What
+	    happens when a signal arrives is shown in the previous paragraph.
+	</para>
+	<para>
+	    When in normal mode (<varname>dont_fork</varname> is not set), the signal handler of the main process will 
+	    only store number of the signal received.
+	    All the processing logic will be executed by the main process outside the signal handler (function
+	    <function moreinfo="none">handle_sigs</function>) The function will be called immediately after the signal
+	    handler finish. The main
+	    process usually does some cleanup and running such things outside the signal handler is much
+	    more safe than doing it from the handler itself. Children only print statistics and exit
+	    or ignore the signal completely, that is quite safe and can be done directly from the signal handler of
+	    children.
+	</para>
+	<para>
+	    When <varname>dont_fork</varname> is set, all the cleanup will be done directly from the signal handler, 
+	    because there is only one process - the main process. This is not so safe as the previous case, but this mode 
+	    should be  used for debugging only and such shortcomming doesn't harm in that case.
+	</para>
+	<para>
+	    Upon receipt of SIGINT, SIGPIPE or SIGTERM <function moreinfo="none">destroy_modules</function> will be called.
+	    Each module may register so-called destroy function if it needs to do some cleanup when the server is
+	    terminating (flush of cache to disk  for example). <function moreinfo="none">destroy_modules</function> will
+	    call destroy funtion of all loaded modules.
+	</para>
+
+	<para>
+	    If you need to terminate the server and all of its children, the best way how to do it is to send SIGTERM
+	    to the main process, the main process will in turn send the same signal to its children.
+	</para>
+
+	<para>
+	    The main process and its children are in the same process group. Therefore the main process can kill all
+	    its children simply by sending a signal to pid 0, sending to pid 0 will send the signal to all processes
+	    in the same process group as the sending process. This is how the main process will terminate all children 
+	    when it is going to shut down.
+	</para>
+
+	<para>
+	    If one child exited during normal operation, the whole server will be shut down. This is better than let
+	    the server continue - a dead child might hold a lock and that could block the whole server, such situation
+	    cannot be avoided easily. Instead of that it is better to shutdown the whole server and have it restarted.
+	</para>
+    </chapter> <!-- server-shutdown -->
+
+    <chapter id="internal-data-struct">
+	<title>Internal Data Structures</title>
+	<para>
+	    There are some data structures that are important and widely used in the server. We will describe them
+	    in this section.
+	</para>
+	
+	<note>
+	    <para>
+		There are many more structures and types defined across the server and modules. We will describe
+		only the most important and common data structure here. The rest will be described in other sections
+		where it will be needed.
+	    </para>
+	</note>
+
+	<section id="str">
+	    <title>Type <type>str</type></title>
+	    <para>
+		One of our main goals was to make <acronym>SER</acronym> really fast. There are many functions across
+		the server that need to work with strings. Usually these functions need to know string length. We wanted
+		to avoid using of <function moreinfo="none">strlen</function> becase the function is relatively slow. It
+		must scan the whole string and find the first occurence of zero character. To avoid this, we created
+		<type>str</type> type. The type has 2 fields, field <structfield>s</structfield> is pointer
+		to the beginning of the string and field <structfield>len</structfield> is length of the string. We then
+		calculate length of the string only once and later reuse saved value.
+	    </para>
+	    <note>
+		<para>
+		    <type>str</type> structure is quite important because it is widely used in
+		    <acronym>SER</acronym> (most functions accept <type>str</type> instead of <type>char*</type>).
+		</para>
+	    </note>
+
+	    <para><emphasis><type>str</type> Type Declaration</emphasis></para>
+	    <programlisting format="linespecific">
+struct _str{
+    char* s;
+    int len;
+};
+
+typedef struct _str str;		    
+</programlisting>
+
+	    <para>
+		The declaration can be found in header file <filename moreinfo="none">str.h</filename>.
+	    </para>
+
+	    <warning>
+		<para>
+		    Because we store string lengths, there is no need to zero terminate them. Some strings in the
+		    server are still zero terminated, some are not. Be carefull when using functions like 
+		    <function moreinfo="none">snprintf</function> that rely on the ending zero. You can print 
+		    variable of type <type>str</type> this way:
+		    <programlisting format="linespecific">
+printf("%.*s", mystring->len, mystring->s);
+</programlisting>
+		    That ensures that the string will be printed correctly even if there is no zero character at
+		    the end.
+		</para>
+	    </warning>
+	</section> <!-- str -->
+	
+	<section id="hdr-field">
+	    <title>Structure <structname>hdr_field</structname></title>
+	    <para>
+		The structure represents a header field of a <acronym>SIP</acronym> message. A header field
+		consist of <emphasis>name</emphasis> and <emphasis>body</emphasis> separated by a double colon.
+		For example: <quote>Server: SIP Express Router\r\n</quote> is one header field. <quote>Server</quote> 
+		is header field name and <quote>SIP Express Router\r\n</quote> is header field body.
+	    </para>
+	    <para>
+		The structure is defined in file <filename moreinfo="none">hf.h</filename> under
+		<filename moreinfo="none">parser</filename> subdirectory.
+	    </para>
+	    <para>
+		<emphasis>Structure Declaration</emphasis>
+	    </para>
+	    <programlisting format="linespecific">
+struct hdr_field {   
+    int type;                /* Header field type */
+    str name;                /* Header field name */
+    str body;                /* Header field body */
+    void* parsed;            /* Parsed data structures */
+    struct hdr_field* next;  /* Next header field in the list */
+};
+</programlisting>
+	    <para>
+		<emphasis>Field Description:</emphasis>
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>type</structfield> - Type of the header field, the following header field
+			types are defined (and recognized by the parser): 
+		    </para>
+		    <para>
+			HDR_VIA1, HDR_VIA2, HDR_TO, HDR_FROM,
+			HDR_CSEQ, HDR_CALLID, HDR_CONTACT, HDR_MAXFORWARDS, HDR_ROUTE, HDR_RECORDROUTE, HDR_CONTENTTYPE,
+			HDR_CONTENTLENGTH, HDR_AUTHORIZATION, HDR_EXPIRES, HDR_PROXYAUTH, HDR_WWWAUTH, HDR_SUPPORTED,
+			HDR_REQUIRE, HDR_PROXYREQUIRE, HDR_UNSUPPORTED, HDR_ALLOW, HDR_EVENT, HDR_OTHER.
+		    </para>
+		    <para>
+			Their meaning is selfexplanatory. HDR_OTHER marks header field not recognized by the parser.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>name</structfield> - Name of the header field (part before doublecolon)
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>body</structfield> - body of the header field (part after doublecolon)
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>parsed</structfield> - Each header field body can be further parsed. The field
+			contains pointer to parsed structure if the header field was parsed already. The pointer is
+			of type void* because it can point to different types of structure depending on the header
+			field type.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>next</structfield> - Pointer to the next header field in linked list.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- hdr-field -->
+
+	<section id="sip-uri"> 
+	    <title>Structure <structname>sip_uri</structname></title>
+	    <para>This structure represents parsed <acronym>SIP</acronym> <acronym>URI</acronym>.</para>
+	    <programlisting format="linespecific">
+struct sip_uri {
+    str user;     /* Username */
+    str passwd;   /* Password */
+    str host;     /* Host name */
+    str port;     /* Port number */
+    str params;   /* Parameters */
+    str headers;  
+};
+</programlisting>
+	    <para><emphasis>Field Description:</emphasis></para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>user</structfield> - Username if found in the <acronym>URI</acronym>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>passwd</structfield> - Password if found in the <acronym>URI</acronym>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>host</structfield> - Hostname of the <acronym>URI</acronym>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>params</structfield> - Parameters of the <acronym>URI</acronym> if any.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>headers</structfield> - See the <acronym>SIP</acronym> <acronym>RFC</acronym>.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- sip-uri -->
+	
+	<section id="via-body">
+	    <title>Structure <structname>via_body</structname></title>
+	    <para>
+		The structure represents parsed Via header field. See file <filename moreinfo="none">parse_via.h</filename>
+		under <filename moreinfo="none">parser</filename> subdirectory for more details.
+	    </para>
+	    <programlisting format="linespecific">
+struct via_body { 
+    int error;
+    str hdr;                      /* Contains "Via" or "v" */
+    str name;
+    str version;   
+    str transport;
+    str host;
+    int port;
+    str port_str;
+    str params;
+    str comment;
+    int bsize;                    /* body size, not including hdr */
+    struct via_param* param_lst;  /* list of parameters*/
+    struct via_param* last_param; /*last via parameter, internal use*/
+
+    /* shortcuts to "important" params*/
+    struct via_param* branch;
+    struct via_param* received;
+
+    struct via_body* next;        /* pointer to next via body string if
+    compact via or null */
+};
+</programlisting>
+	    <para><emphasis>Field Description:</emphasis></para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>error</structfield> - The field contains error code when the parser was unable
+			to parse the header field
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>hdr</structfield>- Header field name, it can be <quote>Via</quote> or <quote>v</quote>
+			in this case
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>name</structfield> - Protocol name (<quote>SIP</quote> in this case).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>version</structfield> - Protocol version (for example <quote>2.0</quote>).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>transport</structfield> - Transport protocol name (<quote>TCP</quote>, <quote>UDP</quote>
+			and so on).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>host</structfield> - Hostname or IP address contained in the Via header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>port</structfield> - Port number as integer.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>port_str</structfield> - Port number as string.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>params</structfield> - Unparsed parameters (as one string containing all the parameters).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>comment</structfield> - Comment.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>bsize</structfield> - Size of the body (not including hdr).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>param_lst</structfield> - Linked list of all parameters.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>last_param</structfield> - Last parameter in the list.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>branch</structfield> - Branch parameter.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>received</structfield> - Received parameter.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>next</structfield> - If the via is in compact form (more Vias in the same header
+			field), this field contains pointer to the next via.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- via-body -->
+
+	<section id="ip-addr">
+	    <title>Structure <structname>ip_addr</structname></title>
+	    <para>
+		The structure represents <acronym>IPv4</acronym> or <acronym>IPv6</acronym> address. It is defined in 
+		<filename moreinfo="none">ip_addr.h</filename>.
+	    </para>
+	    <programlisting format="linespecific">
+struct ip_addr{
+    unsigned int af;     /* address family: AF_INET6 or AF_INET */
+    unsigned int len;    /* address len, 16 or 4 */
+		
+    /* 64 bits alligned address */
+    union {
+        unsigned int   addr32[4];
+        unsigned short addr16[8];
+	unsigned char  addr[16];
+    }u;
+};
+</programlisting>
+	</section> <!-- ip-addr -->
+
+	<section id="lump">
+	    <title>Structure <structname>lump</structname></title>
+	    <para>
+		The structure describes modifications that should be made to the message before
+		the message will be sent. 
+	    </para>
+	    <para>
+		The structure will be described in more detail later.
+	    </para>
+	</section> <!-- lump -->
+	
+	<section id="lump-rpl">
+	    <title>Structure <structname>lump_rpl</structname></title>
+	    <para>
+		The structure represents text that should be added to reply. List of such data is
+		kept in the request and processed when the request is being turned into reply. 
+	    </para>
+	    <para>
+		The structure will be described in more detail later.
+	    </para>
+	</section> <!-- lump-rpl -->
+
+	<section id="msg-start">
+	    <title>Structure <structname>msg_start</structname></title>
+	    <para>
+		The structure represents the first line of a <acronym>SIP</acronym> request or response. 
+	    </para>
+	    <para>
+		The structure is defined in file <filename moreinfo="none">parse_fline.h</filename> under 
+		<filename moreinfo="none">parser</filename> subdirectory.
+	    </para>
+
+	    <para>
+		<emphasis>Structure Declaration</emphasis>
+	    </para>
+	    <programlisting format="linespecific">
+struct msg_start {
+    int type;                        /* Type of the Message - Request/Response */
+    union {
+        struct {
+	    str method;              /* Method string */
+	    str uri;                 /* Request URI */
+	    str version;             /* SIP version */
+	    int method_value;        /* Parsed method */
+        } request;
+	struct {
+	    str version;             /* SIP version */
+	    str status;              /* Reply status */
+	    str reason;              /* Reply reason phrase */
+	    unsigned int statuscode; /* Status code */
+        } reply;
+    }u;
+};
+</programlisting>
+	    
+	    <para>
+		<emphasis>Description of Request Related Fields:</emphasis>
+	    </para>
+
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>type</structfield> - Type of the message - REQUEST or RESPONSE.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>method</structfield> - Name of method (same as in the message).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>uri</structfield> - Request <acronym>URI</acronym>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>version</structfield> - Version string.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>method_value</structfield> - Parsed method. Field method which is of
+			type str will be converted to integer and stored here. This is good for comparison,
+			integer comparison is much faster then string comparison.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+
+	    <para>
+		<emphasis>Description of Response Related Fields:</emphasis>
+	    </para>
+
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>version</structfield> - Version string.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>status</structfield> - Response status code as string.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>reason</structfield> - Response reason string as in the message.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>statuscode</structfield> - Response status code converted to integer.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+
+	</section> <!-- msg-start -->
+
+	<section id="sip-msg">
+	    <title>Structure <structname>sip_msg</structname></title>
+	    <para>
+		This is the most important structure in the whole server. This structure represents
+		a <acronym>SIP</acronym> message. When a message is received, it is immediately converted
+		into this structure and all operations are performed over the structure. After the server
+		finished processing, this structure is converted back to character array
+		buffer and the buffer is sent out.
+	    </para>
+	    <para><emphasis>Structure Declaration:</emphasis></para>
+	    <programlisting format="linespecific">
+struct sip_msg {
+    unsigned int id;               /* message id, unique/process*/
+    struct msg_start first_line;   /* Message first line */
+    struct via_body* via1;         /* The first via */
+    struct via_body* via2;         /* The second via */
+    struct hdr_field* headers;     /* All the parsed headers*/
+    struct hdr_field* last_header; /* Pointer to the last parsed header*/
+    int parsed_flag;               /* Already parsed header field types */
+
+    /* Via, To, CSeq, Call-Id, From, end of header*/
+    /* first occurance of it; subsequent occurances saved in 'headers' */
+
+    struct hdr_field* h_via1;
+    struct hdr_field* h_via2;
+    struct hdr_field* callid;
+    struct hdr_field* to;
+    struct hdr_field* cseq;
+    struct hdr_field* from;
+    struct hdr_field* contact;
+    struct hdr_field* maxforwards;
+    struct hdr_field* route;
+    struct hdr_field* record_route;
+    struct hdr_field* content_type;
+    struct hdr_field* content_length;
+    struct hdr_field* authorization;
+    struct hdr_field* expires;
+    struct hdr_field* proxy_auth;
+    struct hdr_field* www_auth;
+    struct hdr_field* supported;
+    struct hdr_field* require;
+    struct hdr_field* proxy_require;
+    struct hdr_field* unsupported;
+    struct hdr_field* allow;
+    struct hdr_field* event;
+
+    char* eoh;        /* pointer to the end of header (if found) or null */
+    char* unparsed;   /* here we stopped parsing*/
+
+    struct ip_addr src_ip;
+    struct ip_addr dst_ip;
+		
+    char* orig;       /* original message copy */
+    char* buf;        /* scratch pad, holds a modfied message,
+                       *  via, etc. point into it 
+		       */
+    unsigned int len; /* message len (orig) */
+
+    /* modifications */
+		
+    str new_uri;               /* changed first line uri*/
+    int parsed_uri_ok;         /* 1 if parsed_uri is valid, 0 if not */
+    struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/
+		
+    struct lump* add_rm;         /* used for all the forwarded requests */
+    struct lump* repl_add_rm;    /* used for all the forwarded replies */
+    struct lump_rpl *reply_lump; /* only for localy generated replies !!!*/
+
+    char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
+    int add_to_branch_len;
+		
+    /* index to TM hash table; stored in core to avoid unnecessary calcs */
+    unsigned int  hash_index;
+		
+    /* allows to set various flags on the message; may be used for 
+     * simple inter-module communication or remembering processing state
+     * reached 
+     */
+    flag_t flags;	
+};
+</programlisting>
+	    <para>
+		<emphasis>Field Description:</emphasis>
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>id</structfield> - Unique ID of the message within a process context.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>first_line</structfield> - Parsed first line of the message.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>via1</structfield> - The first Via - parsed.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>via2</structfield> - The second Via - parsed.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>headers</structfield> - Linked list of all parsed headers.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>last_header</structfield> - Pointer to the last parsed header (parsing is incremental,
+			that means that the parser will stop if all requested headers were found and next time it will
+			continue at the place where it stopped previously. Therefore this field will not point to the
+			last header of the message if the whole message hasn't been parsed yet).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>parsed_flag</structfield> - Already parsed header field types (bitwise OR).
+		    </para>
+		</listitem>
+	    </itemizedlist>
+
+	    <para>
+		The following fields are set to zero if the corresponding header field was not found in the
+		message or hasn't been parsed yet. (These fields are called hooks - they always point to the first
+		occurence if there is more than one header field of the same type).
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>h_via1</structfield> - Pointer to the first Via header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>h_via2</structfield> - Pointer to the second Via header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>callid</structfield> - Pointer to the first Call-ID header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>to</structfield> - Pointer to the first To header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>cseq</structfield> - Pointer to the first CSeq header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>from</structfield> - Pointer to the first From header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>contact</structfield> - Pointer to the first Contact header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>maxforwards</structfield> - Pointer to the first Max-Forwards header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>route</structfield> - Pointer to the first Route header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>record_route</structfield> - Pointer to the first Record-Route header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>content_type</structfield> - Pointer to the first Content-Type header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>content_length</structfield> - Pointer to the first Content-Length header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>authorization</structfield> - Pointer to the first Authorization header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>expires</structfield> - Pointer to the first Expires header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>proxy_auth</structfield> - Pointer to the first Proxy-Authorize header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>www_auth</structfield> - Pointer to the first WWW-Authorize header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>supported</structfield> - Pointer to the first Supported header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>require</structfield> - Pointer to the first Require header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>proxy_require</structfield> - Pointer to the first Proxy-Require header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>unsupported</structfield> - Pointer to the first Unsupported header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>allow</structfield> - Pointer to the first Allow header field.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>event</structfield> - Pointer to the first Event header field.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+
+	    <para>
+		The following fields are mostly used internally by the server and should be modified through dedicated
+		functions only.
+	    </para>
+
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>eoh</structfield> - Pointer to the End of Header or null if not found yet (the field
+			will be set if and only if the whole message was parsed already).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>unparsed</structfield> - Pointer to the first unparsed character in the message.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>src_ip</structfield> - Sender's <acronym>IP</acronym> address.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>dst_ip</structfield> - Destination <acronym>IP</acronym> address.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>orig</structfield> - Original (unmodified) message copy, this field will hold
+			unmodified copy of the message during the whole message lifetime.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>buf</structfield> - Message scratch-pad (modified copy of the message) - All modifications
+			made to the message will be done here.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>len</structfield> - Length of the message (unmodified).
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>new_uri</structfield> - New Request-URI to be used when forwarding the message.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>parsed_uri_ok</structfield> - 1 if <structfield>parsed_uri</structfield> is 
+			valid, 0 if not.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>parsed_uri</structfield> - The original parsed Request <acronym>URI</acronym>, sometimes 
+			it might be necessary to revert changes made to the Request <acronym>URI</acronym> and therefore we
+			store the original <acronym>URI</acronym> here.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>add_rm</structfield> - Linked list describing all modifications that will be made to
+			<emphasis>REQEST</emphasis> before it will be forwarded. The list will be processed when the request
+			is being converted to character array (i.e. immediately before the request will be send out).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>repl_add_rm</structfield> - Linked list describing all modifications 
+			that will be made to
+			<emphasis>REPLY</emphasis> before it will be forwarded. the list will be processed when the reply
+			is being converted to character array (i.e. immediately before the request will be send out).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>reply_lump</structfield> - This is list of data chunks that should be appended to 
+			localy generated reply, i.e. when the server is generating local reply out of the request. A local
+			reply is reply generated by the server. For example, when processing of a request fails for some
+			reason, the server might generate an error reply and send it back to sender.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>add_to_branch_s</structfield> - String to be appended to branch parameter.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>add_to_branch_len</structfield> - Length of the string.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>hash_index</structfield> - Index to a hash table in TM module.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>flags</structfield> - Allows to set various flags on the message. May be used 
+			for simple inter-module communication or remembering processing state reached.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- sip_msg -->
+    </chapter> <!-- internal-data-struct -->
+	
+    <chapter id="routing-engine">
+	<title>The Routing Engine</title>
+	<para>
+	    In a previous section we discussed how routing part of a config file gets translated into binary
+	    representation. In this section, we will discuss how the binary representation is used during
+	    message processing.
+	</para>
+	<para>
+	    Upon a <acronym>SIP</acronym> message receipt, the server performs some basic sanity checks and converts
+	    the message into <structname>sip_msg</structname> structure. After that the Routing Engine will start
+	    processing the message.
+	</para>
+	<para>
+	    The routing engine can be found in file <filename moreinfo="none">action.c</filename>.
+	</para>
+	<para>
+	    The main function is <function moreinfo="none">run_actions.</function> The 
+	    function accepts two parameters. The first parameter is list of actions to
+	    be processed (Remember, the config file gets translated into array of linked
+	    lists. Each linked list in the array represents one "route" part of the config
+	    file). The second parameter is <structname>sip_msg</structname> structure
+	    representing the message to be routed.
+	</para>
+	<para>
+	    Upon a receipt of a request, the linked list representing the main route
+	    part will be processed so the first parameter will be rlist[0]. (The linked
+	    list of main route part is always at index 0).
+	</para>
+	<para>
+	    The function will then sequentially call 
+	    <function moreinfo="none">do_action</function> function for each element
+	    of the linked list. Return value of the function is important. If the function
+	    returns 0, processing of the list will be stopped. By returning 0 a command
+	    can indicate that processing of the message should be stopped.
+	</para>
+	<para>
+	    Modules may export so-called <emphasis>on_break handlers</emphasis>.
+	    <emphasis>on_break</emphasis> handler is a function, that will be called when
+	    processing of the linked-list is interrupted (ret == 0). All such handlers
+	    will be called when processing of the linked-list is finished and ret == 0.
+	</para>
+	<section id="do-action">
+	    <title><function moreinfo="none">do_action</function> Function</title>
+	    <para>
+		<function moreinfo="none">do_action</function> function is core of the
+		routing engine. There is a big <function moreinfo="none">switch</function>
+		statement. Each case of the statements is one command handled by the
+		server core itself.
+	    </para>
+	    <para>
+		The following commands are handled by the <acronym>SER</acronym> core
+		itself: 
+		<function moreinfo="none">drop</function>,
+		<function moreinfo="none">forward</function>,
+		<function moreinfo="none">send</function>,
+		<function moreinfo="none">log</function>,
+		<function moreinfo="none">append_branch</function>,
+		<function moreinfo="none">len_gt</function>,
+		<function moreinfo="none">setflag</function>,
+		<function moreinfo="none">resetflag</function>,
+		<function moreinfo="none">isflagset</function>,
+		<function moreinfo="none">error</function>,
+		<function moreinfo="none">route</function>,
+		<function moreinfo="none">exec</function>,
+		<function moreinfo="none">revert_uri</function>,
+		<function moreinfo="none">set_host</function>,
+		<function moreinfo="none">set_hostport</function>,
+		<function moreinfo="none">set_user</function>,
+		<function moreinfo="none">set_userpass</function>,
+		<function moreinfo="none">set_port</function>,
+		<function moreinfo="none">set_uri</function>,
+		<function moreinfo="none">prefix</function>,
+		<function moreinfo="none">strip</function>,
+		<function moreinfo="none">if</function>,
+		<function moreinfo="none">module</function>,
+	    </para>
+	    <para>
+		Each of the commands is represented by a case statement in the switch.
+		(For example, if you are interested in implementation of 
+		<function>drop</function> command,
+		look at <quote>case DROP_T:</quote> statement in the function.
+	    </para>
+	    <para>
+		The respective commands will be described now.
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<function moreinfo="none">drop</function> - This command is very
+			simple, it simply returns 0 which will result in abortion of
+			processing of the request. No other commands after
+			<function moreinfo="none">drop</function> will be executed.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">forward</function> - The function will
+			forward the message further. The message will be either forwarded
+			to the request <acronym>URI</acronym> of the message or to 
+			<acronym>IP</acronym> or host given as parameter.
+		    </para>
+		    <para>
+			In the first case, host in the Request <acronym>URI</acronym>
+			must be converted into corresponding <acronym>IP</acronym> address.
+			Function <function moreinfo="none">mk_proxy</function> converts
+			hostname to corresponding <acronym>IP</acronym> address.
+			The message is then sent out using 
+			<function moreinfo="none">forward_request</function> function.
+		    </para>
+		    <para>
+			In the second case, hostname was converted to <acronym>IP</acronym>
+			address in fixup i.e. immediately after the config file was compiled
+			into its binary representation. The first parameter is pointer to
+			<structname>proxy</structname> structure created in the fixup and
+			therefore we only need to call 
+			<function moreinfo="none">forward_request</function> here to
+			forward the message further.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">send</function> - This functions sends
+			the message to a third-party host. The message will be sent out
+			as is - i.e. without Request <acronym>URI</acronym> and Via
+			processing.
+		    </para>
+		    <para>
+			Hostname or <acronym>IP</acronym> address of the third-party host
+			is specified as a parameter of the function.
+		    </para>
+		    <para>
+			The message will be sent out using 
+			<function moreinfo="none">udp_send</function> directly.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">log</function> - The message given as
+			a parameter will be logged using system logger. It can be either
+			syslog or stderr (depends on configuration). The message is logged
+			using <function moreinfo="none">LOG</function> which is a macro
+			defined in <filename moreinfo="none">dprint.h</filename> header
+			file.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">append_branch</function> - Append a new
+			<acronym>URI</acronym> for forking.
+		    </para>
+		    <para>
+			More than one destinations may be associated with a single
+			<acronym>SIP</acronym> request. If the server was configured so,
+			it will use all the destination and fork the request. 
+		    </para>
+		    <para>
+			The server keeps a array of all destinations, that should be
+			used when forking. The array and related functions can be found
+			in file <filename moreinfo="none">dset.c</filename>. There is
+			function append_branch which adds a new destination to the set.
+		    </para>
+		    <para>
+			This command simply calls 
+			<function moreinfo="none">append_branch</function> function and
+			adds a new destination to the destination set.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">len_gt</function> - The command accepts
+			one number as a parameter. It then compares the number with length
+			of the message. If the message length is greater or equal then
+			the number - 1 will be returned otherwise the function returns -1.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">setflag</function> - Sets a flag in the
+			message. The command simply 
+			calls <function moreinfo="none">setflags</function> function that
+			will set the flag. Fore more information see file
+			<filename moreinfo="none">flag.c</filename> or chapter regarding
+			to flags.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">resetflag</function> - Same as command
+			<function moreinfo="none">setflag</function> - only resetflag
+			will be called instead of setflag.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">isflagset</function> - Test if the flag
+			is set or not.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">error</function> - Log a message with
+			NOTICE log level.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">route</function> - Execute another
+			route statement.
+		    </para>
+		    <para>
+			As we mentioned previously, there can be more that one route
+			statement in the config file. One of them is main (without
+			number), the other are additional. This commands makes it possible
+			to execute an additional route statement.
+		    </para>
+		    <para>
+			The command accepts one parameter which is route statement number.
+			First sanity checks over the parameter will be performed. If
+			the checks passed, function 
+			<function moreinfo="none">run_actions</function> will be called.
+			The function accepts two parameters. The first one is linked list
+			to execute, the second one is <structname>sip_msg</structname>
+			structure representing the message to be routed.
+		    </para>
+		    <para>
+			As you might remember, each route statement was compiled into
+			linked list of commands to be executed and head of the linked
+			list was stored in rlist array. For example, head of linked list
+			representing route statement with number 4 will be stored at
+			position 4 in the array (position 0 is reserved for the main
+			route statement).
+		    </para>
+		    <para>
+			So the command will simply call 
+			<function moreinfo="none">run_actions(rlist[a->p1.number], msg)</function>
+			and that will execute route statement with number given as parameter.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">exec</function> - Execute a shell command.
+		    </para>
+		    <para>
+			The command accepts one parameter of type string. The string given as
+			parameter will be passed to <function moreinfo="none">system</function>
+			function which will in turn execute
+			<function moreinfo="none">/bin/sh -c string</function>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">revert_uri</function> - Revert changes made to
+			the Request <acronym>URI</acronym>.
+		    </para>
+		    <para>
+			If there is a new <acronym>URI</acronym> stored in 
+			<structfield>new_uri</structfield> of <structname>sip_msg</structname> structure,
+			it will be freed. The original Request <acronym>URI</acronym> will be used
+			when forwarding the message.
+		    </para>
+		    <para>
+			If there is a valid <acronym>URI</acronym> in 
+			<structfield>parsed_uri</structfield> field of <structname>sip_msg</structname>
+			structure (indicated by <structfield>parsed_uri_ok</structfield> field), it
+			will be freed too.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">set_host</function> - Change hostname of Request
+			<acronym>URI</acronym> to value given as parameter.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">set_hostport</function> - change hostname and port
+			of Request <acronym>URI</acronym> to value given as string parameter.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>			
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">set_user</function> - Set username part of Request
+			<acronym>URI</acronym> to string given as parameter.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">set_userpass</function> - Set username and password
+			part of Request <acronym>URI</acronym> to string given as parameter.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>			
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">set_port</function> - Set port of Request
+			<acronym>URI</acronym> to value given as parameter.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>			
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">set_uri</function> - Set a new Request
+			<acronym>URI</acronym>.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield> field,
+			it will be freed. If there is a valid <acronym>URI</acronym> in 
+			<structfield>parsed_uri</structfield> field, it will be freed.
+		    </para>
+		    <para>
+			Then, <acronym>URI</acronym> given as parameter will be stored in 
+			<structfield>new_uri</structfield> field. (If <structfield>new_uri</structfield>
+			contains a <acronym>URI</acronym> it will be used instead of Request
+			<acronym>URI</acronym> when forwarding the message).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">prefix</function> - Set the parameter as username
+			prefix.
+		    </para>
+		    <para>
+			The string will be put immediately after <quote>sip:</quote> part of the 
+			Request <acronym>URI</acronym>.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>			
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">strip</function> - Remove first n characters of
+			username in Request <acronym>URI</acronym>.
+		    </para>
+		    <para>
+			If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
+			field, it will be modified, otherwise the original Request
+			<acronym>URI</acronym> will be modified.
+		    </para>			
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">if</function> - if Statement.
+		    </para>
+		    <para>
+			There is an expression associated with the command and one or two linked lists of
+			comands. The expression is a regular expression compiled into binary form
+			in the fixup when the config file was compiled.
+		    </para>
+		    <para>
+			The expression will be evaluated now. If the result is &gt; 0, the first linked
+			list will be executed using <function moreinfo="none">run_action</function>
+			function. The linked list represents command enclosed in curly braces of 
+			<function moreinfo="none">if</function> command.
+		    </para>
+		    <para>
+			Otherwise, if there is second list, it will be executed in the same way. The
+			second list represents commads of <function moreinfo="none">else</function>
+			statement.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">module</function> - Execute a function exported by
+			a module.
+		    </para>
+		    <para>
+			When a command in a route statement is not recognized by the core itself
+			(i.e. it is not one of commands handled by the core itself), list of exported
+			functions of all loaded modules will be searched for a function with corresponding
+			name and corresponding number of parameters.
+		    </para>
+		    <para>
+			If the function was found, <function moreinfo="none">module</function> command
+			(this one) will be created and pointer to the function will be stored in 
+			<structfield>p1.data</structfield> field.
+		    </para>
+		    <para>
+			So, this command will simply call function whose pointer is in
+			<structfield>p1.data</structfield> field and will pass 2 parameters to the
+			function. If one or both of the parameters were not used, 0 will be passed
+			instead. 
+		    </para>
+		    <para>
+			Return value of the function will be returned as return value of
+			<function moreinfo="none">module</function> command.
+		    </para>
+		    <para>
+			This command makes <acronym>SER</acronym> pretty extensible while the core
+			itself is still reasonably small and clean. Additional functionality is put
+			in modules and loaded only when needed.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- do-action -->
+    </chapter> <!-- routing-engine -->
+    
+    <chapter id="memory-management">
+	<title>Memory Management</title>
+	<para>
+	    This section should be written by somebody who really knows how it works. Any volunteers ?
+	    TBD by Andrei or Jiri.
+	</para>
+    </chapter> <!-- memory-management -->
+
+    <chapter id="msg-parser">
+	<title>The Message Parser</title>
+	<para>
+	    In this section we will discuss internals of the <acronym>SIP</acronym> message header
+	    parser implemented in the server. Message parsing is very important and one of the most
+	    time consuming operations of a <acronym>SIP</acronym> server. We have been trying to
+	    make the parser as fast as possible.
+	</para>
+	
+	<para>
+	    A header field parser can be either in the server core or in a module. By convention,
+	    parser that is needed by the core itself or is needed by at least two modules will be
+	    in the core. Parsers contained in modules will be not described in this section.
+	</para>
+	<para>
+	    There is a <filename moreinfo="none">parser</filename> subdirectory that contains all
+	    the parsers and related stuff.
+	</para>
+	<para>
+	    The following parsers can be found under <filename moreinfo="none">parser</filename>
+	    subdirectory:
+	</para>
+
+	<section id="sip-msg-structure">
+	    <title>Structure of a <acronym>SIP</acronym> Message</title>
+	    <para>
+		a <acronym>SIP</acronym> message consists of message header and optional message body. 
+		The header is separated from the body with a empty line (containing CRLF only).
+	    </para>
+	    <para>
+		Message header consists of the first line and one or more header fields. The first line
+		determines type of the message. Header fields provide additional information that is
+		needed by clients and server to be able to process the message.
+	    </para>
+	    <para>
+		Each header field consists of header field name and header field body. Header field name
+		is delimited from header field body by a colon (<quote>:</quote>). For example,
+		<quote>Server: SIP Express Router</quote> - in this case <quote>Server</quote> is 
+		header field name and <quote>SIP Express Router</quote> is header field body.
+	    </para>
+	</section> <!-- sip-msg-structure -->
+	
+	<section>
+	    <title>TBD</title>
+	    <itemizedlist>
+		<listitem>
+		    <para>First Line Parser - Parses the first line of a <acronym>SIP</acronym> message.</para>
+		</listitem>
+		<listitem>
+		    <para>Header Name Parser- Parsers Name part of a header field (part before colon).</para>
+		</listitem>		
+		<listitem>
+		    <para>To Header Parser - Parses body of To header field.</para>
+		</listitem>
+		<listitem>
+		    <para>From Header Parser - Parses body of From header field.</para>
+		</listitem>
+		<listitem>
+		    <para>CSeq Header Parser - Parses body of CSeq header field.</para>
+		</listitem>
+		<listitem>
+		<para>Event Header Parser - Parses body of Event header field.</para>
+		</listitem>
+		<listitem>
+		    <para>Expires Header Parser - Parses body of Expires header field.</para>
+		</listitem>
+		<listitem>
+		    <para>Via Header Parser - Parses body of Via header field.</para>
+		</listitem>
+		<listitem>
+		    <para>Contact Header Parser - Parses body of Contact header field.</para>
+		</listitem>
+		<listitem>
+		    <para>Digest Parser - Parses digest response.</para>
+		</listitem>
+	    </itemizedlist>
+	    
+	    <para>
+		The server implements what we call <emphasis>incremental parsing</emphasis>. It means that
+		a header field will be not parsed unless it is really needed. There is a minimal set of
+		header that will be parsed every time. The set includes:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    The first line - the server must know if the message is request or response
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    Via header field - Via will be needed for sure. We must add ourself to Via
+			    list when forwarding the message.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	</section>
+	
+	<section id="parser-organization">
+	    <title>The Parser Organization</title>
+	    <section id="fline-parser">
+		<title>The First Line Parser</title>
+		<para>
+		    Purpose of the parser is to parse the first line of a <acronym>SIP</acronym>
+		    message. The first line is represented by <structname>msg_start</structname>
+		    structure define in file <filename moreinfo="none">parse_fline.h</filename>
+		    under <filename moreinfo="none">parser</filename> subdirectory.
+		</para>
+		<para>
+		    The main function of the first line parser is 
+		    <function moreinfo="none">parse_first_line</function>, the function will fill in
+		    <structname>msg_start</structname> structure.
+		</para>
+		<para>
+		    Follow inline comments in the function if you want to add support for a new
+		    message type.
+		</para>
+	    </section> <!-- fline-parser -->
+	    <section id="hfname-parser">
+		<title>The Header Field Name Parser</title>
+		<para>
+		    The purpose of the header field type parser is to recognize type of a header field.
+		    The following types of header field will be recognized:
+		</para>
+		<para>
+		    Via, To, From, CSeq, Call-ID, Contact, Max-Forwards, Route, Record-Route,
+		    Content-Type, Content-Length, Authorization, Expires, Proxy-Authorization,
+		    WWW-Authorization, supported, Require, Proxy-Require, Unsupported, Allow, Event.
+		</para>
+		<para>
+		    All other header field types will be marked as HDR_OTHER.
+		</para>
+		<para>
+		    Main function of header name parser is <function moreinfo="none">parse_hname2</function>. The
+		    function can be found in file <filename moreinfo="none">parse_hname.c</filename>. The function
+		    accepts pointers to begin and end of a header field and fills in <structname>hdf_field</structname>
+		    structure. <structfield>name</structfield> field will point to the header field name,
+		    <structfield>body</structfield> field will point to the header field body and 
+		    <structfield>type</structfield> field will contain type of the header field if known and HDR_OTHER
+		    if unknown.
+		</para>
+		<para>
+		    The parser is 32-bit, it means, that it processes 4 characters of header field name at time. 4
+		    characters of a header field name are converted to an integer and the integer is then compared. This
+		    is much faster than comparing byte by byte. Because the server is compiled on at least 32-bit architectures,
+		    such comparsion will be compiled into one instruction instead of 4 instructions.
+		</para>
+		<para>
+		    We did some performance measurement and 32-bit parsing is about 3 times faster for a typical 
+		    <acronym>SIP</acronym> message than corresponding automaton comparing byte by byte. Performance may vary
+		    depending on the message size, parsed header fields and header fields type. Test showed that it was always
+		    as fast as corresponding 1-byte comparing automaton.
+		</para>
+		<para>
+		    Since comparison must be case insensitive in case of header field names, it is necessary to convert it
+		    to lower case first and then compare. Since converting byte by byte would slow down the parser a lot, we
+		    have implemented a hash table, that can again convert 4 bytes at once. Since set of keys that need to be
+		    converted to lowercase is known (the set consists of all possible 4-byte parts of all recognized header
+		    field names) we can precalculate size of the hash table to be synonym-less. That will simplify (and speed
+		    up) the lookup a lot. The hash table must be initialized upon the server startup (function
+		    <function moreinfo="none">init_hfname_parser</function>).
+		</para>
+		<para>
+		    The header name parser consists of several files, all of them are under 
+		    <filename moreinfo="none">parser</filename> subdirectory. Main file is 
+		    <filename moreinfo="none">parse_hname2.c</filename> - this files contains the parser itself and functions
+		    used to initialize and lookup the hash table. File <filename moreinfo="none">keys.h</filename> contains
+		    automatically generated set of macros. Each macro is a group of 4 bytes converted to integer. The macros
+		    are used for comparison and the hash table initialization. For example, for Max-Forwards header field
+		    name, the following macros are defined in the file: 
+		</para>
+		<programlisting>
+#define _max__ 0x2d78616d   /* "max-" */
+#define _maX__ 0x2d58616d   /* "maX-" */
+#define _mAx__ 0x2d78416d   /* "mAx-" */
+#define _mAX__ 0x2d58416d   /* "mAX-" */
+#define _Max__ 0x2d78614d   /* "Max-" */
+#define _MaX__ 0x2d58614d   /* "MaX-" */
+#define _MAx__ 0x2d78414d   /* "MAx-" */
+#define _MAX__ 0x2d58414d   /* "MAX-" */
+
+#define _forw_ 0x77726f66   /* "forw" */
+#define _forW_ 0x57726f66   /* "forW" */
+#define _foRw_ 0x77526f66   /* "foRw" */
+#define _foRW_ 0x57526f66   /* "foRW" */
+#define _fOrw_ 0x77724f66   /* "fOrw" */
+#define _fOrW_ 0x57724f66   /* "fOrW" */
+#define _fORw_ 0x77524f66   /* "fORw" */
+#define _fORW_ 0x57524f66   /* "fORW" */
+#define _Forw_ 0x77726f46   /* "Forw" */
+#define _ForW_ 0x57726f46   /* "ForW" */
+#define _FoRw_ 0x77526f46   /* "FoRw" */
+#define _FoRW_ 0x57526f46   /* "FoRW" */
+#define _FOrw_ 0x77724f46   /* "FOrw" */
+#define _FOrW_ 0x57724f46   /* "FOrW" */
+#define _FORw_ 0x77524f46   /* "FORw" */
+#define _FORW_ 0x57524f46   /* "FORW" */
+
+#define _ards_ 0x73647261   /* "ards" */
+#define _ardS_ 0x53647261   /* "ardS" */
+#define _arDs_ 0x73447261   /* "arDs" */
+#define _arDS_ 0x53447261   /* "arDS" */
+#define _aRds_ 0x73645261   /* "aRds" */
+#define _aRdS_ 0x53645261   /* "aRdS" */
+#define _aRDs_ 0x73445261   /* "aRDs" */
+#define _aRDS_ 0x53445261   /* "aRDS" */
+#define _Ards_ 0x73647241   /* "Ards" */
+#define _ArdS_ 0x53647241   /* "ArdS" */
+#define _ArDs_ 0x73447241   /* "ArDs" */
+#define _ArDS_ 0x53447241   /* "ArDS" */
+#define _ARds_ 0x73645241   /* "ARds" */
+#define _ARdS_ 0x53645241   /* "ARdS" */
+#define _ARDs_ 0x73445241   /* "ARDs" */
+#define _ARDS_ 0x53445241   /* "ARDS" */
+</programlisting>
+		<para>
+		    As you can see, Max-Forwards name was divided into three 4-byte chunks: Max-, Forw, ards. The file
+		    contains macros for every possible lower and upper case character combination of the chunks. Because
+		    the name (and therefore chunks) can contain colon (<quote>:</quote>), minus or space and these 
+		    characters are not allowed in macro name, they must be substituted. Colon is substituted by 
+		    <quote>1</quote>, minus is substituted by underscore (<quote>_</quote>) and space is substituted
+		    by <quote>2</quote>.
+		</para>
+
+		<para>
+		    When initializing the hash table, all these macros will be used as keys to the hash table. One of
+		    each upper and lower case combinations will be used as value. Which one ?
+		</para>
+		<para>
+		    There is a convention that each word of a header field name starts with a upper case character. For
+		    example, most of user agents will send <quote>Max-Forwards</quote>, messages containing some other 
+		    combination of upper and lower case characters (for example: <quote>max-forwards</quote>,
+		    <quote>MAX-FORWARDS</quote>, <quote>mAX-fORWARDS</quote>) are very rare (but it is possible).
+		</para>
+		<para>
+		    Considering the previous paragraph, we optimized the parser for the most common case. When all header
+		    fields have upper and lower case characters according to the convention, there is no need to do hash
+		    table lookups, which is another speed up.
+		</para>
+		<para>
+		    For example suppose we are trying to figure out if the header field name is Max-Forwards and the
+		    header field name is formed according to the convention (i.e. <quote>Max-Forwards</quote>):
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				Get the first 4 bytes of the header field name (<quote>Max-</quote>), convert it to an 
+				integer and compare to <quote>_Max__</quote> macro. Comparison succeeded, continue
+				with the next step.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				Get next 4 bytes of the header field name (<quote>Forw</quote>), convert it to an
+				integer and compare to <quote>_Forw_</quote> macro. Comparison succeeded, continue
+				with the next step.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				Get next 4 bytes of the header field name (<quote>ards</quote>), convert it to an
+				integer and compare to <quote>_ards_</quote> macro. Comparison succeeded, continue
+				with the next step.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				If the following characters are spaces and tabs followed by a colon (or colon directly
+				without spaces and tabs), we found Max-Forwards header field name and can set
+				<structfield>type</structfield> field to HDR_MAXFORWARDS. Otherwise (other characters
+				than colon, spaces and tabs) it is some other header field and set 
+				<structfield>type</structfield> field to HDR_OTHER.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    As you can see, there is no need to do hash table lookups if the header field was formed according
+		    to the convention and the comparison was very fast (only 3 comparisons needed !).
+		</para>
+		<para>
+		    Now lets consider another example, the header field was not formed according to the convention, for
+		    example <quote>MAX-forwards</quote>:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				Get the first 4 bytes of the header field name (<quote>MAX-</quote>), convert it to an
+				integer and compare to <quote>_Max__</quote> macro.
+			    </para>
+			    <para>
+				Comparison failed, try to lookup <quote>MAX-</quote> converted to integer in the hash
+				table. It was found, result is <quote>Max-</quote> converted to integer.
+			    </para>
+			    <para>
+				Try to compare the result from the hash table to <quote>_Max__</quote> macro. Comparison
+				succeeded, continue with the next step.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				Compare next 4 bytes of the header field name (<quote>forw</quote>), convert it to an
+				integer and compare to <quote>_Max__</quote> macro.
+			    </para>
+			    <para>
+				Comparison failed, try to lookup <quote>forw</quote> converted to integer in the hash
+				table. It was found, result is <quote>Forw</quote> converted to integer.
+			    </para>
+			    <para>
+				Try to compare the result from the hash table to <quote>Forw</quote> macro. Comparison
+				succeeded, continue with the next step.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				Compare next 4 bytes of the header field name (<quote>ards</quote>), convert it to
+				integer and compare to <quote>ards</quote> macro. Comparison succeeded, continue
+				with the next step.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				If the following characters are spaces and tabs followed by a colon (or colon directly
+				without spaces and tabs), we found Max-Forwards header field name and can set
+				<structfield>type</structfield> field to HDR_MAXFORWARDS. Otherwise (other characters
+				than colon, spaces and tabs) it is some other header field and set 
+				<structfield>type</structfield> field to HDR_OTHER.				    
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    In this example, we had to do 2 hash table lookups and 2 more comparisons. Even this variant is still
+		    very fast, because the hash table lookup is synonym-less, lookups are very fast.
+		</para>
+	    </section> <!-- hfname-parser -->
+
+	    <section id="body-parsers">
+		<title>The Header Field Body Parsers</title>
+		<section id="to-parser">
+		    <title>To HF Body Parser</title>
+		    <para>
+			Purpose of this parser is to parse body of To header field. The parser can be found in file
+			<filename moreinfo="none">parse_to.c</filename> under <filename moreinfo="none">parser</filename>
+			subdirectory.
+		    </para>
+		    <para>
+			Main function is <function moreinfo="none">parse_to</function> but there is no need to call the
+			function explicitly. Every time the parser finds a To header field, this function will be called
+			automatically. Result of the parser is <structname>to_body</structname> structure. Pointer to the
+			structure will be stored in <structfield>parsed</structfield> field of 
+			<structname>hdr_field</structname> structure. Since the pointer is <type>void*</type>, there is a
+			convenience macro <function moreinfo="none">get_to</function> in file 
+			<filename moreinfo="none">parse_to.h</filename> that will do the necessary type-casting and will
+			return pointer to <structname>to_body</structname> structure.
+		    </para>
+		    <para>
+			The parser itself is a finite state machine that will parse To body according to the grammar defined
+			in <acronym>RFC3261</acronym> and store result in <structname>to_body</structname> structure.
+		    </para>
+		    <para>
+			The parser gets called automatically from function <function moreinfo="none">get_hdr_field</function>
+			in file <filename moreinfo="none">msg_parser.c</filename>. The function first creates and initializes 
+			an instance of <structname>to_body</structname> structure, then calls 
+			<function moreinfo="none">parse_to</function> function with the structure as a parameter and if
+			everything went OK, puts the pointer to the structure in <structfield>parsed</structfield> field of
+			<structname>hdr_field</structname> structure representing the parsed To header field.
+		    </para>
+		    <para>
+			The newly created structure will be freed when the message is being destroyed, see function
+			<function moreinfo="none">clean_hdr_field</function> in file <filename moreinfo="none">hf.c</filename>
+			for more details.
+		    </para>
+		    
+		    <section id="to-body-struct">
+			<title>Structure <structname>to_body</structname></title>
+			<para>
+			    The structure represents parsed To body. The structure is declared in 
+			    <filename moreinfo="none">parse_to.h</filename> file.
+			</para>
+			<para><emphasis>Structure Declaration:</emphasis></para>
+			<programlisting format="linespecific">
+			    struct to_param{
+			    int type;              /* Type of parameter */
+			    str name;              /* Name of parameter */
+			    str value;             /* Parameter value */
+			    struct to_param* next; /* Next parameter in the list */
+			    };
+
+
+			    struct to_body{
+			    int error;                    /* Error code */
+			    str body;                     /* The whole header field body */
+			    str uri;                      /* URI */
+			    str tag_value;                /* Value of tag */
+			    struct to_param *param_lst;   /* Linked list of parameters */
+			    struct to_param *last_param;  /* Last parameter in the list */
+			    };
+			</programlisting>
+			<para>
+			    Structure <structname>to_param</structname> is a temporary structure representing
+			    a To <acronym>URI</acronym> parameter. Right now only TAG parameter will be marked
+			    in <structfield>type</structfield> field. All other parameters will have the same
+			    type.
+			</para>
+			<para><emphasis>Field Description:</emphasis></para>
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>error</structfield> - Error code will be put here when parsing of To
+				    body fails.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>body</structfield> - The whole header field body.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>uri</structfield> - <acronym>URI</acronym> of the To header field.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>tag_value</structfield> - Value of tag parameter if present.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>param_lst</structfield> - Linked list of all parameters.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>last_param</structfield> - Pointer to the last parameter in the linked list.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </section> <!-- to-body-struct -->
+		    
+		</section> <!-- to-parser -->
+
+		<section id="from-parser"> 
+		    <title>From HF Body Parser</title>
+		    <para>
+			This parser is only a wrapper to the To header field parser. Since bodies of both header fields
+			are identical, From parser only calls To parser.
+		    </para>
+		    <para>
+			The wrapper can be found in file <filename moreinfo="none">parse_from.c</filename> under
+			<filename moreinfo="none">parser</filename> subdirectory. There is only one function called
+			<function moreinfo="none">parse_from_header</function>. The function accepts one parameter which
+			is pointer to structure representing the From header field to be parsed. The function creates an
+			instance of <structname>to_body</structname> structure and initializes it. It then calls
+			<function moreinfo="none">parse_to</function> function and if everything went OK, the pointer to
+			the newly created structure will be put in <structfield>parsed</structfield> field of the structure
+			representing the parsed header field.
+		    </para>
+		    <para>
+			The newly created structure will be freed when the whole message is being destroyed. 
+			(See To header field parser description for more details).
+		    </para>
+		    <para>
+			From parser <emphasis>must be called explicitly</emphasis> !
+		    </para>
+		    <para>
+			If the main parser finds a From header field, it will not parse the header field body
+			automaticaly. It is up to you to call the 
+			<function moreinfo="none">parse_from_header</function> when you want to parse a From
+			header field body.
+		    </para>
+		</section> <!-- from-parser -->
+
+		<section id="cseq-parser">
+		    <title>CSeq HF Body Parser</title>
+		    <para>
+			Purpose of this parser is to parse body of CSeq header field. The parser can be found in file
+			<filename moreinfo="none">parse_cseq.c</filename> under <filename moreinfo="none">parser</filename>
+			subdirectory.
+		    </para>
+		    <para>
+			Main function is <function moreinfo="none">parse_cseq</function> but there is no need to call the
+			function explicitly. Every time the parser finds a CSeq header field, this function will be called
+			automatically. Result of the parser is <structname>cseq_body</structname> structure. Pointer to the
+			structure will be stored in <structfield>parsed</structfield> field of 
+			<structname>hdr_field</structname> structure. Since the pointer is <type>void*</type>, there is a
+			convenience macro <function moreinfo="none">get_cseq</function> in file 
+			<filename moreinfo="none">parse_cseq.h</filename> that will do the necessary type-casting and will
+			return pointer to <structname>cseq_body</structname> structure.
+		    </para>
+		    <para>
+			The parser will parse CSeq body according to the grammar defined in <acronym>RFC3261</acronym> and 
+			store result in <structname>cseq_body</structname> structure.
+		    </para>
+		    <para>
+			The parser gets called automatically from function <function moreinfo="none">get_hdr_field</function>
+			in file <filename moreinfo="none">msg_parser.c</filename>. The function first creates and initializes 
+			an instance of <structname>cseq_body</structname> structure, then calls 
+			<function moreinfo="none">parse_cseq</function> function with the structure as a parameter and if
+			everything went OK, puts the pointer to the structure in <structfield>parsed</structfield> field of
+			<structname>hdr_field</structname> structure representing the parsed CSeq header field.
+		    </para>
+		    <para>
+			The newly created structure will be freed when the message is being destroyed, see function
+			<function moreinfo="none">clean_hdr_field</function> in file <filename moreinfo="none">hf.c</filename>
+			for more details.
+		    </para>
+		    
+		    <section id="cseq-body-struct">
+			<title>Structure <structname>cseq_body</structname></title>
+			<para>
+			    The structure represents parsed CSeq body. The structure is declared in 
+			    <filename moreinfo="none">parse_cseq.h</filename> file.
+			</para>
+			<para><emphasis>Structure Declaration:</emphasis></para>
+			<programlisting format="linespecific">
+struct cseq_body{
+    int error;  /* Error code */
+    str number; /* CSeq number */
+    str method; /* Associated method */
+};
+</programlisting>
+			<para><emphasis>Field Description:</emphasis></para>
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>error</structfield> - Error code will be put here when parsing of CSeq
+				    body fails.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>number</structfield> - CSeq number as string.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>method</structfield> - CSeq method.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </section> <!-- cseq-body-struct -->
+		</section> <!-- cseq-parser -->
+
+		<section id="event-parser">
+		    <title>Event HF Body Parser</title>
+		    <para>
+			Purpose of this parser is to parse body of an Event Header field. The parser can be found in
+			file <filename moreinfo="none">parse_event.c</filename> under
+			<filename moreinfo="none">parser</filename> subdirectory.
+		    </para>
+		    <note>
+			<para>
+			    This is <emphasis>NOT</emphasis> fully featured Event body parser ! The parser was written
+			    for Presence Agent module only and thus can recognize Presence package only. No subpackages
+			    will be recognized. All other packages will be marked as <quote>OTHER</quote>.
+			</para>
+			<para>
+			    The parser should be replace by a more generic parser if subpackages or parameters should be
+			    parsed too.
+			</para>
+		    </note>
+		    <para>
+			Main function is <function moreinfo="none">parse_event</function> in file 
+			<filename moreinfo="none">parse_event.c</filename>. The function will create an instance of
+			<structname>event_t</structname> structure and call the parser. If everything went OK, pointer
+			to the newly created structure will be stored in <structfield>parsed</structfield> field of 
+			<structname>hdr_field</structname> structure representing the parsed header field.
+		    </para>
+		    <para>
+			As usually, the newly created structure will be freed when the whole message is being destroyed.
+			See function <function moreinfo="none">clean_hdr_field</function> in file 
+			<filename moreinfo="none">hf.c</filename>.
+		    </para>
+		    <para>
+			The parser will be not called automatically when the main parser finds an Event header field.
+			It is up to you to call the parser when you really need the body of the header field to be
+			parsed (call <function moreinfo="none">parse_event</function> function).
+		    </para>
+
+		    <section id="event-struct">
+			<title>Structure <structname>event_t</structname></title>
+			<para>
+			    The structure represents parsed Event body. The structure is declared in 
+			    <filename moreinfo="none">parse_event.h</filename> file.
+			</para>
+			<para><emphasis>Structure Declaration:</emphasis></para>
+			<programlisting format="linespecific">
+#define EVENT_OTHER    0
+#define EVENT_PRESENCE 1
+
+typedef struct event {
+    str text;   /* Original string representation */
+    int parsed; /* Parsed variant */
+} event_t;
+</programlisting>
+			<para><emphasis>Field Description:</emphasis></para>
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>text</structfield> - Package name as text.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>parsed</structfield> - Package name as integer. It will be EVENT_PRESENCE
+				    for presence package and EVENT_OTHER for rest.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </section> <!-- event-struct -->			
+		</section> <!-- event-parser -->
+		<section id="expires-parser"> 
+		    <title>Expires HF Body Parser</title>
+		    <para>
+			The parser parses body of Expires header field. The body is very simple, it consists of number only.
+			so the parser only removes any leading tabs and spaces and converts the number from string to
+			integer. That's it.
+		    </para>
+		    <para>
+			The parser can be found in file <filename moreinfo="none">parse_expires.c</filename> under
+			<filename moreinfo="none">parser</filename> subdirectory. Main function is
+			<function moreinfo="none">parse_expires</function>. The function is not called automaticaly
+			when an Expires header field was found. It is up to you to call the function if you need the body
+			to be parsed.
+		    </para>
+		    <para>
+			The function creates a new instance of <structname>exp_body_t</structname> structure and calls the
+			parser. If everything went OK, pointer to the newly created structure will be saved in
+			<structfield>parsed</structfield> field of the <structname>hdr_field</structname> structure representing
+			the parsed header field.
+		    </para>
+		    <section id="exp-body-struct">
+			<title>Structure <structname>exp_body_t</structname></title>
+			<para>
+			    The structure represents parsed Expires body. The structure is declared in 
+			    <filename moreinfo="none">parse_expires.h</filename> file.
+			</para>
+			<para><emphasis>Structure Declaration:</emphasis></para>
+			<programlisting format="linespecific">
+typedef struct exp_body {
+    str text;   /* Original text representation */
+    int val;    /* Parsed value */
+} exp_body_t;
+</programlisting>
+			<para><emphasis>Field Description:</emphasis></para>
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>text</structfield> - Expires value as text.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>val</structfield> - Expires value as integer.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </section> <!-- exp-body-struct -->	
+		</section> <!-- expires-parser -->
+
+		<section id="via-parser">
+		    <title>Via HF Body Parser</title>
+		    <para>
+			Purpose of this parser is to parse body of Via header field. The parser can be found in file
+			<filename moreinfo="none">parse_via.c</filename> under <filename moreinfo="none">parser</filename>
+			subdirectory.
+		    </para>
+		    <para>
+			Main function is <function moreinfo="none">parse_via</function> but there is no need to call the
+			function explicitly. Every time the parser finds a Via header field, this function will be called
+			automatically. Result of the parser is <structname>via_body</structname> structure. Pointer to the
+			structure will be stored in <structfield>parsed</structfield> field of 
+			<structname>hdr_field</structname> structure representing the parsed header field.
+		    </para>
+		    <para>
+			The parser itself is a finite state machine that will parse Via body according to the grammar defined
+			in <acronym>RFC3261</acronym> and store result in <structname>via_body</structname> structure.
+		    </para>
+		    <para>
+			The parser gets called automatically from function <function moreinfo="none">get_hdr_field</function>
+			in file <filename moreinfo="none">msg_parser.c</filename>. The function first creates and initializes 
+			an instance of <structname>via_body</structname> structure, then calls 
+			<function moreinfo="none">parse_via</function> function with the structure as a parameter and if
+			everything went OK, puts the pointer to the structure in <structfield>parsed</structfield> field of
+			<structname>hdr_field</structname> structure representing the parsed Via header field.
+		    </para>
+		    <para>
+			The newly created structure will be freed when the message is being destroyed, see function
+			<function moreinfo="none">clean_hdr_field</function> in file <filename moreinfo="none">hf.c</filename>
+			for more details.
+		    </para>
+		    <para>
+			Structure <structname>via_body</structname> is described in section 
+			<link linkend="via-body">Structure <structname>via_body</structname></link>.
+		    </para>
+		</section> <!-- via-parser -->
+
+		<section id="contact-parser">
+		    <title>Contact HF Body Parser</title>
+		    <para>
+			The parser is located under <filename moreinfo="none">parser/contact</filename> subdirectory. The
+			parser is not called automaticaly when the main parser finds a Contact header field. It is your
+			responsibility to call the parser if you want a Contact header field body to be parsed.
+		    </para>
+		    <para>
+			Main function is <function moreinfo="none">parse_contact</function> in file
+			<filename moreinfo="none">parse_contact.c</filename>. The function accepts one parameter which
+			is structure <structname>hdr_field</structname> representing the header field to be parsed. A single
+			Contact header field may contain multiple contacts, the parser will parse all of them and will create
+			linked list of all such contacts.
+		    </para>
+		    <para>
+			The function creates and initializes an instance of <structname>contact_body</structname> structure.
+			Then function <function moreinfo="none">contact_parser</function> will be called. If everything went
+			OK, pointer to the newly created structure will be stored in <structfield>parsed</structfield> field
+			of the <structname>hdr_field</structname> structure representing the parsed header field.
+		    </para>
+		    <para>
+			Function <function moreinfo="none">contact_parser</function> will then check if the contact is star, if
+			not it will call <function moreinfo="none">parse_contacts</function> function that will parse all 
+			contacts of the header field.
+		    </para>
+		    <para>
+			Function <function moreinfo="none">parse_contacts</function> can be found in file
+			<filename moreinfo="none">contact.c</filename>. It extracts <acronym>URI</acronym> and parses all
+			contact parameters.
+		    </para>
+		    <para>
+			The Contact parameter parser can be found in file <filename moreinfo="none">cparam.c</filename>.
+		    </para>
+		    <para>
+			The following structures will be created during parsing:
+		    </para>
+		    <note>
+			<para>
+			    Mind that none of string in the following structures is zero terminated ! Be very carefull
+			    when processing the strings with functions that require zero termination (printf for example) !
+			</para>
+		    </note>
+		    <programlisting format="linespecific">
+typedef struct contact_body {
+    unsigned char star;    /* Star contact */
+    contact_t* contacts;   /* List of contacts */
+} contact_body_t;
+</programlisting>
+		    <para>
+			This is the main structure. Pointer to instance of this structure will be stored in 
+			<structfield>parsed</structfield> field of structure representing the header field to be parsed.
+			The structure contains two field:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>star</structfield> field - This field will contain 1 if the Contact
+				    was star (see <acronym>RFC3261</acronym> for more details).
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>contacts</structfield> field - This field contains pointer to linked
+				    list of all contacts found in the Contact header field.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+
+		    <programlisting format="linespecific">
+typedef struct contact {
+    str uri;              /* contact uri */
+    cparam_t* q;          /* q parameter hook */
+    cparam_t* expires;    /* expires parameter hook */
+    cparam_t* method;     /* method parameter hook */
+    cparam_t* params;     /* List of all parameters */
+    struct contact* next; /* Next contact in the list */
+} contact_t;
+</programlisting>
+		    <para>
+			This structure represents one Contact (Mind that there might be several contacts in one Contact
+			header field delimited by a comma). Its fields have the following meaning:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>uri</structfield> - This field contains pointer to begin of 
+				    <acronym>URI</acronym> and its length.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>q</structfield> - This is a hook to structure representing q parameter.
+				    If there is no such parameter, the hook contains 0.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>expires</structfield> - This is a hook to structure representing expires
+				    parameter. If there is no such parameter, the hook contains 0.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>method</structfield> - This is a hook to structure representing method
+				    parameter. If there is no such parameter, the hook contains 0.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>params</structfield> - Linked list of all parameters.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>next</structfield> - Pointer to the next contact that was in the same
+				    header field.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		    <programlisting format="linespecific">
+typedef enum cptype {
+    CP_OTHER = 0,  /* Unknown parameter */
+    CP_Q,          /* Q parameter */
+    CP_EXPIRES,    /* Expires parameter */
+    CP_METHOD      /* Method parameter */
+} cptype_t;
+</programlisting>
+		    <para>
+			This is an enum of recognized types of contact parameters. Q parameter will have type set to
+			CP_Q, Expires parameter will have type set to CP_EXPIRES and Method parameter will have type set
+			to CP_METHOD. All other parameters will have type set to CP_OTHER.
+		    </para>
+
+		    <programlisting format="linespecific">
+/*
+ * Structure representing a contact
+ */
+typedef struct cparam {
+    cptype_t type;       /* Type of the parameter */
+    str name;            /* Parameter name */
+    str body;            /* Parameter body */
+    struct cparam* next; /* Next parameter in the list */
+} cparam_t;
+</programlisting>
+
+		    <para>
+			This structure represents a contact parameter. Field description follows:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>type</structfield> - Type of the parameter, see <structname>cptype</structname>
+				    enum for more details.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>name</structfield> - Name of the parameter (i.e. the part before 
+				    <quote>=</quote>).
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>body</structfield> - Body of the parameter (i.e. the part after
+				    <quote>=</quote>).
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>next</structfield> - Next parameter in the linked list.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		</section> <!-- contact-parser -->
+
+		<section id="digest-parser">
+		    <title>Digest Body Parser</title>
+		    <para>
+			Purpose of this parser is to parse digest response. The parser can be found under
+			<filename moreinfo="none">parser/digest</filename> subdirectory. There might be several header
+			fields containing digest response, for example Proxy-Authorization or WWW-Authorization. The parser
+			can be used for all of them.
+		    </para>
+		    <para>
+			The parser is not called automaticaly when by the main parser. It is your responsibility to call the
+			parser when you want a digest response to be parsed.
+		    </para>
+		    <para>
+			Main function is <function moreinfo="none">parse_credentials</function> defined in
+			<filename moreinfo="none">digest.c</filename>. The function accepts one parameter which is header
+			field to be parsed. As result the function will create an instance of 
+			<structname>auth_body_t</structname> structure which will represent the parsed digest credentials.
+			Pointer to the structure will be put in <structfield>parsed</structfield> field of the
+			<structname>hdr_field</structname> structure representing the parsed header field. It will be freed
+			when the whole message is being destroyed.
+		    </para>
+
+		    <para>
+			The digest parser contains 32-bit digest parameter parser. The parser was in detail described in
+			section <link linkend="hfname-parser">Header Field Name Parser</link>. See that section for more
+			details about the digest parameter parser algorithm, they work in the same way.
+		    </para>
+
+		    <para>
+			Description of digest related stuctures follows:
+		    </para>
+
+		    <programlisting format="linespecific">			
+typedef struct auth_body {
+    /* This is pointer to header field containing
+     * parsed authorized digest credentials. This
+     * pointer is set in sip_msg->{authorization,proxy_auth}
+     * hooks.
+     *
+     * This is necessary for functions called after
+     * {www,proxy}_authorize, these functions need to know
+     * which credentials are authorized and they will simply
+     * look into 
+     * sip_msg->{authorization,proxy_auth}->parsed->authorized
+     */
+    struct hdr_field* authorized;
+    dig_cred_t digest;           /* Parsed digest credentials */
+    unsigned char stale;         /* Flag is set if nonce is stale */
+    int nonce_retries;           /* How many times the nonce was used */
+} auth_body_t;
+</programlisting>
+		    <para>
+			This is the <quote>main</quote> stucture. Pointer to the structure will be stored in
+			<structfield>parsed</structfield> field of <structname>hdr_field</structname> structure. Detailed
+			description of its fields follows:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>authorized</structfield> - This is a hook to header field containing
+				    authorized credentials.
+				</para>
+				<para>
+				    A <acronym>SIP</acronym> message may contain several credentials. They are distinguished
+				    using realm parameter. When the server is trying to authorize the message, it must first
+				    find credentials with corresponding realm and than authorize the credentials. To authorize
+				    credentials server calculates response string and if the string matches to response string
+				    contained in the credentials, credentials are authorized (in fact it means that the user
+				    specified in the credentials knows password, nothing more, nothing less).
+				</para>
+				<para>
+				    It would be good idea to remember which credentials contained in the message are authorized,
+				    there might be other functions interested in knowing which credentials are authorized.
+				</para>
+				<para>
+				    That is what is this field for. A function that sucessfully authorized credentials
+				    (currenty there is only one such function in the server, it is function 
+				    <function moreinfo="none">authorize</function> in auth module) will put pointer to header
+				    field containing the authorized credentials in this field. Because there might be several
+				    header field containing credentials, the pointer will be put in 
+				    <structfield>authorized</structfield> field in the first header field in the message
+				    containg credentials. That means that it will be either header field whose pointer is
+				    in <structfield>www_auth</structfield> or <structfield>proxy_auth</structfield> field
+				    of <structname>sip_msg</structname> structure representing the message.
+				</para>
+				<para>
+				    When a function wants to find authorized credentials, it will simply look in 
+				    <structfield>msg->www_auth->parsed->authorized</structfield> or
+				    <structfield>msg->proxy_auth->parsed->authorized</structfield>, 
+				    where <structfield>msg</structfield> is variable containing pointer to 
+				    <structname>sip_msg</structname> structure.
+				</para>
+				<para>
+				    To simplify the task of saving and retrieving pointer to authorized credentials, there
+				    are two convenience functions defined in <filename moreinfo="none">digest.c</filename> file.
+				    They will be described later.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>digest</structfield> - Structure containing parsed digest credentials. The
+				    structure will be described in detail later.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>stale</structfield> - This field will be set to 1 if the server received
+				    a stale nonce. Next time when the server will be sending another challenge, it will use
+				    <quote>stale=true</quote> parameter. <quote>stale=true</quote> indicates to the client
+				    that username and password used to calculate response were correct, but nonce was stale.
+				    The client should recalculate response with the same username and password (without
+				    disturbing user) and new nonce. For more details see <acronym>RFC2617</acronym>.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>nonce_retries</structfield> - This fields indicates number of authorization
+				    attempts with same nonce.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		    <programlisting format="linespecific">
+/*
+ * Errors returned by check_dig_cred
+ */
+typedef enum dig_err {
+    E_DIG_OK = 0,        /* Everything is OK */
+    E_DIG_USERNAME  = 1, /* Username missing */
+    E_DIG_REALM = 2,     /* Realm missing */
+    E_DIG_NONCE = 4,     /* Nonce value missing */
+    E_DIG_URI = 8,       /* URI missing */
+    E_DIG_RESPONSE = 16, /* Response missing */
+    E_DIG_CNONCE = 32,   /* CNONCE missing */
+    E_DIG_NC = 64,       /* Nonce-count missing */
+} dig_err_t;			
+</programlisting>
+		    <para>
+			This is enum of all possible errors returned by <function moreinfo="none">check_dig_cred</function>
+			function.
+			<itemizedlist>
+			    <listitem>
+				<para><emphasis>E_DIG_OK</emphasis> - No error found.</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>E_DIG_USERNAME</emphasis> - Username parameter missing in digest response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para><emphasis>E_DIG_REALM</emphasis> - Realm parameter missing in digest response.</para>
+			    </listitem>
+			    <listitem>
+				<para><emphasis>E_DIG_NONCE</emphasis> - Nonce parameter missing in digest response.</para>
+			    </listitem>
+			    <listitem>
+				<para><emphasis>E_DIG_URI</emphasis> - Uri parameter missing in digest response.</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>E_DIG_RESPONSE</emphasis> - Response parameter missing in digest response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para><emphasis>E_DIG_CNONCE</emphasis> - Cnonce parameter missing in digest response.</para>
+			    </listitem>
+			    <listitem>
+				<para><emphasis>E_DIG_NC</emphasis> - Nc parameter missing in digest response.</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		    <programlisting format="linespecific">
+/* Type of algorithm used */
+typedef enum alg {
+    ALG_UNSPEC = 0,   /* Algorithm parameter not specified */
+    ALG_MD5 = 1,      /* MD5 - default value*/
+    ALG_MD5SESS = 2,  /* MD5-Session */
+    ALG_OTHER = 4     /* Unknown */
+} alg_t;
+</programlisting>
+		    <para>
+			This is enum of recognized algorithm types. (See description of <structname>algorithm</structname>
+			structure for more details).
+			<itemizedlist>
+			    <listitem>
+				<para><emphasis>ALG_UNSPEC</emphasis> - Algorithm was not specified in digest response.</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>ALG_MD5</emphasis> - <quote>algorithm=MD5</quote> was found in digest response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>ALG_MD5SESS</emphasis> - <quote>algorithm=MD5-Session</quote> was found in
+				    digest response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>ALG_OTHER</emphasis> - Unknown algorithm parameter value was found in
+				    digest response.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		    <programlisting format="linespecific">
+/* Quality Of Protection used */
+typedef enum qop_type { 
+    QOP_UNSPEC = 0,   /* QOP parameter not present in response */
+    QOP_AUTH = 1,     /* Authentication only */
+    QOP_AUTHINT = 2,  /* Authentication with integrity checks */
+    QOP_OTHER = 4     /* Unknown */
+} qop_type_t;
+</programlisting>
+		    <para>
+			This enum lists all recognized qop parameter values.
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <emphasis>QOP_UNSPEC</emphasis> - qop parameter was not found in digest response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>QOP_AUTH</emphasis> - <quote>qop=auth</quote> was found in digest response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>QOP_AUTHINT</emphasis> - <quote>qop=auth-int</quote> was found in digest
+				    response.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>QOP_OTHER</emphasis> - Unknow qop parameter value was found in digest response.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+
+		    <programlisting format="linespecific">
+/* Algorithm structure */
+struct algorithm {
+    str alg_str;       /* The original string representation */
+    alg_t alg_parsed;  /* Parsed value */
+};
+</programlisting>
+		    <para>
+			The structure represents <quote>algorithm</quote> parameter of digest response. Description of fields
+			follows:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>alg_str</structfield> - Algorithm parameter value as string.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>alg_parsed</structfield> - Parsed algorithm parameter value.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+
+		    <programlisting format="linespecific">
+/* QOP structure */
+struct qp {
+    str qop_str;           /* The original string representation */
+    qop_type_t qop_parsed; /* Parsed value */
+};
+</programlisting>
+		    <para>
+			This structure represents <quote>qop</quote> parameter of digest response. Description of fields
+			follows:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>qop_str</structfield> - Qop parameter value as string.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>qop_parsed</structfield> - Parsed <quote>qop</quote> parameter value.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		    <programlisting format="linespecific">
+/*
+ * Parsed digest credentials
+ */
+typedef struct dig_cred {
+    str username;         /* Username */
+    str realm;            /* Realm */
+    str nonce;            /* Nonce value */
+    str uri;              /* URI */
+    str response;         /* Response string */
+    str algorithm;        /* Algorithm in string representation */
+    struct algorithm alg; /* Type of algorithm used */
+    str cnonce;           /* Cnonce value */
+    str opaque;           /* Opaque data string */
+    struct qp qop;        /* Quality Of Protection */
+    str nc;               /* Nonce count parameter */
+} dig_cred_t;
+</programlisting>
+		    <para>
+			This structure represents set of digest credentials parameters. Description of field follows:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <structfield>username</structfield> - Value of <quote>username</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>realm</structfield> - Value of <quote>realm</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>nonce</structfield> - Value of <quote>nonce</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>uri</structfield> - Value of <quote>uri</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>response</structfield> - Value of <quote>response</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>algorithm</structfield> - Value of <quote>algorithm</quote> parameter
+				    as string.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>alg</structfield> - Parsed value of <quote>algorithm</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>cnonce</structfield> - Value of <quote>cnonce</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>opaque</structfield> - Value of <quote>opaque</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>qop</structfield> - Value of <quote>qop</quote> parameter.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <structfield>nc</structfield> - Value of <quote>nc</quote> parameter.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		    <section id="other-funcs">
+			<title>Other Functions Of the Digest Body Parser</title>
+			<para>
+			    There are some other mainly convenience functions defined in the parser. The function will be
+			    in detail described in this section. All the functions are defined in 
+			    <filename moreinfo="none">digest.c</filename> file.
+			</para>
+			
+			<funcsynopsis>
+			    <funcprototype>
+				<funcdef>dig_err_t <function moreinfo="none">check_dig_cred</function></funcdef>
+				<paramdef>dig_cred_t* <parameter moreinfo="none">_c</parameter></paramdef>
+			    </funcprototype>
+			</funcsynopsis>
+			
+			<para>
+			    This function performs some basic sanity check over parsed digest credentials. The following
+			    conditions must be met for the checks to be successfull:
+			    <itemizedlist>
+				<listitem>
+				    <para>
+					There must be non-empty <quote>username</quote> parameter in the credentials.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					There must be non-empty <quote>realm</quote> parameter in the credentials.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					There must be non-empty <quote>nonce</quote> parameter in the credentials.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					There must be non-empty <quote>uri</quote> parameter in the credentials.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					There must be non-empty <quote>response</quote> parameter in the credentials.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					If qop parameter is set to QOP_AUTH or QOP_AUTHINT, then there must be also
+					non-empty <quote>cnonce</quote> and <quote>nc</quote> parameters in the digest.
+				    </para>
+				</listitem>
+			    </itemizedlist>
+			</para>
+			<note>
+			    <para>
+				It is recommended to call <function moreinfo="none">check_dig_cred</function> before you
+				try to authorize the credentials. If the function fails, there is no need to try to authorize
+				the credentials because the authorization will fail for sure.
+			    </para>
+			</note>
+
+			<funcsynopsis>
+			    <funcprototype>
+				<funcdef>int <function moreinfo="none">mark_authorized_cred</function></funcdef>
+				<paramdef>struct sip_msg* <parameter moreinfo="none">_m</parameter></paramdef>
+				<paramdef>struct hdr_field* <parameter moreinfo="none">_h</parameter></paramdef>
+			    </funcprototype>
+			</funcsynopsis>
+
+			<para>
+			    This is convenience function. The function saves pointer to the authorized credentials. For
+			    more info see description of <structfield>authorized</structfield> field in
+			    <structname>auth_body</structname> structure.
+			</para>
+
+			<funcsynopsis>
+			    <funcprototype>
+				<funcdef>int <function moreinfo="none">get_authorized_cred</function></funcdef>
+				<paramdef>struct sip_msg* <parameter moreinfo="none">_m</parameter></paramdef>
+				<paramdef>struct hdr_field** <parameter moreinfo="none">_h</parameter></paramdef>
+			    </funcprototype>
+			</funcsynopsis>
+			
+			<para>
+			    This is convenience function. The function will retrieve pointer to authorized credentials 
+			    previously saved  using <function moreinfo="none">mark_authoized_cred</function> function.
+			    If there is no such credentials, 0 will be stored in variable pointed to by the second
+			    parameter. The function returns always zero. For more information see description of
+			    <structfield>authorized</structfield> field in <structname>auth_body</structname> structure.
+			</para>
+		    </section> <!-- other-funcs -->
+		</section> <!-- digest-parser -->
+	    </section> <!-- body-parsers -->
+	</section> <!-- parser-organization -->
+    </chapter> <!-- msg-parser -->
+
+    <chapter id="module-interface">
+	<title>Module Interface</title>
+	<para>
+	    The server can load additional functionality through modules. Module loading related functions and module
+	    interface will be described in this section.
+	</para>
+	<para>
+	    All the data structures and functions mentioned in this section can be found in files
+	    <filename moreinfo="none">sr_module.h</filename> and <function moreinfo="none">sr_module.c</function>.
+	</para>
+
+	<section id="sr-module-struct">
+	    <title>Structure <structname>sr_module</structname></title>
+	    <para>
+		Each loaded module is represented by an instance of <structname>sr_module</structname> structure. All
+		the instances are linked. There is a global variable <varname>modules</varname> defined in file
+		<filename moreinfo="none">sr_module.c</filename> which is head of linked-list of all loaded modules.
+	    </para>
+	    <para>
+		Detailed description of the structure follows:
+	    </para>
+	    <programlisting format="linespecific">
+struct sr_module{
+    char* path;
+    void* handle;
+    struct module_exports* exports;
+    struct sr_module* next;
+};
+</programlisting>
+	    <para>
+		Field and their description:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <structfield>path</structfield> - Path to the module. This is the path you pass as parameter
+			    to <function moreinfo="none">loadmodule</function> function in the config file.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <structfield>handle</structfield> - Handle returned by <function moreinfo="none">dlopen</function>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <structfield>exports</structfield> - Pointer to structure describing interface of the module (will
+			    be described later).
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <structfield>next</structfield> - Pointer to the next <structname>sr_module</structname> structure
+			    in the linked list.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	</section> <!-- sr-module-struct -->
+
+	<section id="module-exports-struct">
+	    <title>Structure <structname>module_exports</structname></title>
+	    <para>
+		This structure describes interface that must be exported by each module. Every module must have a global
+		variable named <varname>exports</varname> which is of type <structname>struct module_exports</structname>.
+	    </para>
+	    <para>
+		Immediately after <function moreinfo="none">dlopen</function> the server will try to find symbol named
+		<varname>exports</varname> in the module to be loaded. This symbol is a structure describing interface
+		of the module. Pointer to the symbol will be then put in <structfield>exports</structfield> field of 
+		<structname>sr_module</structname> structure representing the module in the server.
+	    </para>
+	    <para>
+		Detailed description of the structure follows:
+	    </para>
+	    <programlisting format="linespecific">
+struct module_exports{
+    char* name;                     /* null terminated module name */
+    char** cmd_names;               /* cmd names registered by this modules */
+    cmd_function* cmd_pointers;     /* pointers to the corresponding functions */
+    int* param_no;                  /* number of parameters used by the function */
+    fixup_function* fixup_pointers; /* pointers to functions called to "fix"
+	                             * the params, e.g: precompile a re 
+		                     */
+    int cmd_no;                     /* number of registered commands
+		                     * (size of cmd_{names,pointers} 
+		                     */
+
+    char** param_names;      /* parameter names registered by this modules */
+    modparam_t* param_types; /* Type of parameters */
+    void** param_pointers;   /* Pointers to the corresponding memory locations */
+    int par_no;              /* number of registered parameters */
+
+    init_function init_f;         /* Initilization function */
+    response_function response_f; /* function used for responses,
+		                   * returns yes or no; can be null 
+		                   */
+    destroy_function destroy_f;   /* function called when the module should
+		                   * be "destroyed", e.g: on ser exit;
+		                   * can be null 
+		                   */
+    onbreak_function onbreak_f;
+    child_init_function init_child_f;  /* function called by all processes after the fork */
+};
+</programlisting>
+	    <para>
+		Fields and their description:
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<structfield>name</structfield> - Name of the module.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>cmd_names</structfield> - Array of names of exported commands.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>cmd_pointers</structfield> - Array of pointers to functions implementing
+			commands specified in <structfield>cmd_names</structfield> array.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>int <function moreinfo="none">cmd_function</function></funcdef>
+			    <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
+			    <paramdef>char* <parameter moreinfo="none">param1</parameter></paramdef>
+			    <paramdef>char* <parameter moreinfo="none">param2</parameter></paramdef>
+			</funcprototype>
+		    </funcsynopsis>
+		    <para>
+			The first parameter is <structname>sip_msg</structname> currently being processed.
+			Remaining parameters are parameters from the config file. If the function accepts only
+			one parameter, <parameter moreinfo="none">param2</parameter> will be set to zero, if the 
+			function accepts no parameters, <parameter moreinfo="none">param1</parameter> and
+			<parameter moreinfo="none">param2</parameter> will be set to zero.
+		    </para>
+		    <para>
+			The function should return number &gt; 0 if everything went OK and processing of the message should
+			contine. The function should return 0 if processing of the message should be stopped.
+			The function should return number &lt; 0 on an error.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>param_no</structfield> - Array of number of parameters of exported commands.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>fixup_pointer</structfield> - Array of pointers to fixup functions, each fixup
+			function for one exported command. If there is no fixup function for a particular exported
+			function, corresponding field in the array will contain zero.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>int <function moreinfo="none">fixup_function</function></funcdef>
+			    <paramdef>void** <parameter moreinfo="none">param</parameter></paramdef>
+			    <paramdef>int <parameter moreinfo="none">param_no</parameter></paramdef>
+			</funcprototype>
+		    </funcsynopsis>
+		    <para>
+			The first parameter is pointing to variable to be fixed. The second parameter
+			is order of the variable.
+		    </para>
+		    <para>
+			The function should return 0 if everything went OK and number &lt; 0 on an error.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>cmd_no</structfield> - Number of exported commands.
+		    </para>
+		    <important>
+			<para>
+			    <structfield>cmd_names</structfield>, <structfield>cmd_pointers</structfield>,
+			    <structfield>param_no</structfield> and <structfield>fixup_pointer</structfield> arrays must
+			    have at least <structfield>cmd_no</structfield> elements ! (It might even kill your cat if you
+			    fail to fullfill this condition).
+			</para>
+		    </important>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>param_names</structfield> - Array of names of exported parameters.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>param_types</structfield> - Array of types of parameters, each field of the array
+			can be either STR_PARAM or INT_PARAM (currently only two parameter types are defined).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>param_pointers</structfield> - Array of pointers to variables, that hold values of the
+			parameters.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>param_no</structfield> - Number of exported parameters.
+		    </para>
+		    <important>
+			<para>
+			    <structfield>param_names</structfield>, <structfield>param_types</structfield> and
+			    <structfield>param_pointers</structfield> arrays must have at least
+			    <structfield>param_no</structfield> elements ! (Remember the previous note about your cat ? The
+			    same might happen to your dog if you fail to fulfill the condition second time !).
+			</para>
+		    </important>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>init_f</structfield> - Pointer to module's initialization function, 0 if the module
+			doesn't need initialization function.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>int <function moreinfo="none">init_function</function></funcdef>
+			    <void>
+			</funcprototype>
+		    </funcsynopsis>
+		    <para>
+			The function should return 0 if everything went OK and number &lt; 0 on an error;
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>response_f</structfield> - If a module is interested in seeing responses, it will provide
+			pointer to a function here. The function will be called when a response comes. The field will contain
+			0 if the module doesn't want to see responses.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>int <function moreinfo="none">response_function</function></funcdef>
+			    <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
+			</funcprototype>
+		    </funcsynopsis>
+		    <para>
+			The function accepts one parameter which is stucture representing the response currently
+			being processed.
+		    </para>
+		    <para>
+			The function should return 0 if the response should be dropped. 
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>destroy_f</structfield> - Destroy function. The function will be called when the server
+			is shutting down. Can be 0 if the module doesn't need destroy function.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>void <function moreinfo="none">destroy_function</function></funcdef>
+			    <void>
+			</funcprototype>
+		    </funcsynopsis>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>onbreak_f</structfield> - On break function. The function will be called when processing
+			of a route statement was aborted. Can be 0 if module doesn't need this function.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>void <function moreinfo="none">onbreak_function</function></funcdef>
+			    <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
+			</funcprototype>
+		    </funcsynopsis>
+		    <para>
+			The function accepts one parameter which is message currently being processed.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<structfield>init_child_f</structfield> - Child init function. This is an additonal initialization
+			function. <structfield>init_f</structfield> will be called from the main process 
+			<emphasis>BEFORE</emphasis> the main process forks children. <structfield>init_child_f</structfield>
+			will be called from all children <emphasis>AFTER</emphasis> the fork.
+		    </para>
+		    <para>
+			Per-child specific initialization can be done here. For example, each child can open its own database
+			connection in the function, and so on.
+		    </para>
+		    <para>
+			Function Prototype:
+		    </para>
+		    <funcsynopsis>
+			<funcprototype>
+			    <funcdef>int <function moreinfo="none">child_init_function</function></funcdef>
+			    <paramdef>int <parameter moreinfo="none">rank</parameter></paramdef>
+			</funcprototype>
+		    </funcsynopsis>
+		    <para>
+			The function accepts one parameter, which is rank (starting from 0) of child executing the function.
+		    </para>
+		    <para>
+			The function should return 0 if everything went OK and number &lt; 0 on an error.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- module-exports-struct -->
+	
+	<section id="module-loading">
+	    <title>Module Loading</title>
+	    <para>
+		Modules are compiled and stored as shared objects. Shared objects have usually appendix <quote>.so</quote>.
+		Shared objects can be loaded at runtime.
+	    </para>
+	    <para>
+		When you instruct the server to load a module using <function moreinfo="none">loadmodule</function> command
+		in the config file, it will call function <function moreinfo="none">load_module</function>. The function
+		will do the following:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    It will try to open specified file using <function moreinfo="none">dlopen</function>. For example
+			    if you write loadmodule "/usr/lib/ser/modules/auth.so" in the config file, the server will try
+			    to open file <quote>/usr/lib/ser/modules/auth.so</quote> using 
+			    <function moreinfo="none">dlopen</function> function.
+			</para>
+			<para>
+			    If <function moreinfo="none">dlopen</function> failed, the server will issue an error and abort.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    As the next step, list of all previously loaded modules will be searched for the same module.
+			    If such module is found, it means, that user is trying to load the same module twice. In such
+			    case an warning will be issued and server will abort.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    The server will try to find pointer to <quote>exports</quote> symbol using 
+			    <function moreinfo="none">dlsym</function> in the module. If that fails, server will issue an 
+			    error and abort.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    And as the last step, function <function moreinfo="none">register_module</function> will register
+			    the module with the server core and loading of the module is complete.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	    <para>
+		Function <function moreinfo="none">register_module</function> registers a module with the server core. By
+		registration we mean the following set of steps (see function 
+		<function moreinfo="none">register_module</function> in file <filename moreinfo="none">sr_module.c</filename>
+		for more details):
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    The function creates and initializes new instance of <structname>sr_module</structname>
+			    structure.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <structfield>path</structfield> field will be set to path of the module.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <structfield>handle</structfield> field will be set to handle previously retuned by
+			    <function moreinfo="none">dlopen</function>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <structfield>exports</structfield> field will be set to pointer to module's
+			    <varname>exports</varname> structure previously obtained through 
+			    <function moreinfo="none">dlsym</function> in <function moreinfo="none">load_module</function>
+			    function.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    As the last step, the newly created structure will be inserted into linked list of all 
+			    loaded modules and registration is complete.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	</section> <!-- module-loading -->
+
+	<section id="module-config">
+	    <title>Module Configuration</title>
+	    <para>
+		In addition to set of functions each module can export set of configuration variables.
+		Value of a module's configuration variable can be changed in the config file using
+		<function moreinfo="none">modparam</function> function. Module configuration will be described in this
+		section.
+	    </para>
+	    <section id="modparam-func">
+		<title>Function <function moreinfo="none">modparam</function></title>
+		<para>
+		    <function moreinfo="none">modparam</function> function accepts three parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>module name</emphasis> - Name of module as exported in <structfield>name</structfield>
+				field of <varname>exports</varname> global variable.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>variable name</emphasis> - Name of variable to be set - it must be one of names
+				specified in <structfield>param_names</structfield> field of <varname>exports</varname>
+				variable of the module.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>value</emphasis> - New value of the variable. There are two types of variables:
+				string and integer. If the last parameter (value) of 
+				<function moreinfo="none">modparam</function>
+				function is enclosed in quotes, it is string paramater and server will try to find the
+				corresponding variable among string parameters only.
+			    </para>
+			    <para>
+				Otherwise it is integer parameter and server will try to find corresponding variable among
+				integer parameters only.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+	    </section> <!-- modparam-func -->
+
+	    <section id="set-mod-param-func">
+		<title>Function <function moreinfo="none">set_mod_param</function></title>
+		<para>
+		    When the server finds <function moreinfo="none">modparam</function> function in the config file, it
+		    will call <function moreinfo="none">set_mod_param</function> function. The function can be found
+		    in <filename moreinfo="none">modparam.c</filename> file. The function will do the following:
+		</para>
+		
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    It tries to find corresponding variable using <function moreinfo="none">find_param_export</function>
+			    function.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    If it is string parameter, a new copy of the string will be obtained using 
+			    <function moreinfo="none">strdup</function> function and pointer to the copy will be stored in the
+			    variable.
+			</para>
+			<para>
+			    If it is integer parameter, its value will be simply copied in the variable.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </section> <!-- set-mod-param-func -->
+
+	    <section id="find-param-export-func">
+		<title>Function <function moreinfo="none">find_param_export</function></title>
+		<para>
+		    This function accepts 3 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>module</emphasis> - Name of module.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>parameter</emphasis> - Name of parameter to be found.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>type</emphasis> - Type of the parameter.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    The function will search list of all modules until it find module with given name.
+		    Then it will search throught all module's exported parameters until it finds parameter
+		    with corresponding name and type. If such parameter was found, pointer to variable holding
+		    the parameter's value will be returned. If the function failed to find either module or
+		    parameter with given name and type then zero will be returned.
+		</para>
+	    </section> <!-- find-param-export-func -->
+	</section> <!-- module-config -->
+
+	<section id="finding-exported">
+	    <title>Finding an Exported Function</title>
+	    <para>This section describes how to find an exported function.</para>
+
+	    <para>
+		If you need to find exported function with given name and number parameters, 
+		<function moreinfo="none">find_export</function> function is what you need. The function
+		is defined in <filename moreinfo="none">sr_module.c</filename> file.
+		The function accepts two parameters:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>name</emphasis> - Name of function to be found.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>param_no</emphasis> - Number of parameters of the function.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	    <para>
+		The function will search throught list of all loaded modules and in each module through
+		array of all exported functions until it find function with given name and number of
+		parameter. If such exported function was found, <function moreinfo="none">find_exported</function>
+		will return pointer to the function, otherwise zero will be returned.
+	    </para>
+	</section> <!--finding-exported -->
+
+	<section id="additional-functions">
+	    <title>Additional Functions</title>
+	    <para>
+		There are several additional functions defined in file <filename moreinfo="none">sr_module.c</filename>.
+		There functions are mostly internal and shouldn't be used directly by user. We will shortly describe
+		them here.
+	    </para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<function moreinfo="none">register_builtin_modules</function> - Some modules might be linked
+			statically with main executable, this is handy for debugging. This function will register all
+			such modules upon server startup.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">init_child</function> - This function will call child-initialization
+			function of all loaded modules. The function will be called by the server core immediately after
+			the fork.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">find_module</function> - The function accepts pointer to an exported
+			function and number of parameters as parameters and returns pointer to corresponding module that
+			exported the function.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">destroy_modules</function> - The function will call destroy function
+			of all loaded modules. This function will be called by the server core upon shut down.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<function moreinfo="none">init_modules</function> - The function will call initialization function
+			of all loaded modules. The function will be called by the server before the fork.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section> <!-- additional-functions -->
+    </chapter> <!-- module-interface -->
+	
+
+    <chapter id="db-interface">
+	<title>The Database Interface</title>
+	<para>
+	    This is a generic database interface for modules that need to utilize a 
+	    database. The interface should be used by all modules that access database.
+	    The interface will be independent of the underlying database server.
+	</para>
+	<note>
+	    <para>
+		If possible, use predefined macros if you need to access any structure 
+		attributes.  
+	    </para>
+	    <para>
+		For additional description, see comments in sources of mysql module.
+	    </para>
+	    <para>
+		If you want to see more complicated examples of how the API could be used, 
+		see sources of dbexample, usrloc or auth modules.
+	    </para>
+	</note>
+	
+	<section id="data-types">
+	    <title>Data types</title>
+	    <para>
+		There are several new data types. All of them are defined in header file db.h,
+		a client must include the header file to be able to use them.
+	    </para>
+	    <section id="type-db-con">
+		<title>Type <type>db_con_t</type></title>
+		<para>
+		    This type represents a database connection, all database functions (described 
+		    below) use a variable of this type as one argument. In other words, variable 
+		    of db_con_t type serves as a handle for a particular database connection.
+		</para>
+		<programlisting format="linespecific">
+typedef struct db_con {
+    char* table;     /* Default table to use */
+    void* con;       /* Database connection */
+    void* res;       /* Result of previous operation */
+    void* row;       /* Internal, not for public use */
+    int connected;   /* 1 if connection is established */
+} db_con_t;
+</programlisting>
+		<para>
+		    There are no macros defined for <type>db_con_t</type> type.
+		</para>
+	    </section> <!-- type-db-con -->
+
+	    <section id="type-db-key">
+		<title>Type <type>db_key_t</type></title>
+		<para>
+		    This type represents a database key. Every time you need to specify a key 
+		    value, this type should be used. In fact, this type is identical to const 
+		    char*.
+		</para>
+		<programlisting format="linespecific">
+		    typedef const char* db_key_t;
+		</programlisting>
+		<para>
+		    There are no macros defined (they are not needed).
+		</para>
+	    </section> <!-- type-db-key -->
+
+	    <section id="type-db-type">
+		<title>Type <type>db_type_t</type></title>
+		<para>
+		    Each cell in a database table can be of a different type. To distinguish
+		    among these types, the <type>db_type_t</type> enumeration is used. Every 
+		    value of the enumeration represents one datatype that is recognized by the 
+		    database <acronym>API</acronym>. This enumeration is used in conjunction 
+		    with <type>db_type_t</type>. For more information, see the next section.
+		</para>
+		<programlisting format="linespecific">
+typedef enum {
+    DB_INT,       /* Integer number */
+    DB_DOUBLE,    /* Decimal number */
+    DB_STRING,    /* String */
+    DB_STR,       /* str structure */
+    DB_DATETIME   /* Date and time */
+    DB_BLOB       /* Binary large object */
+} db_type_t;
+</programlisting>
+		<para>
+		    There are no macros defined.
+		</para>
+	    </section> <!-- type-db-type -->
+
+	    <section id="type-db-val">
+		<title>Type <type>db_val_t</type></title>
+		<para>
+		    This structure represents a value in the database. Several datatypes are
+		    recognized and converted by the database <acronym>API</acronym>:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>DB_INT</emphasis> - Value in the database represents an integer number.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>DB_DOUBLE</emphasis> - Value in the database represents a decimal number.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>DB_STRING</emphasis> - Value in the database represents a string.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>DB_STR</emphasis> - Value in the database represents a string.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>DB_DATETIME</emphasis> - Value in the database represents date and time.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>DB_BLOB</emphasis> - Value in the database represents binary large object.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		    These datatypes are automaticaly recognized, converted from internal database
+		    representation and stored in the variable of corresponding type.
+		</para>
+		<programlisting format="linespecific">
+typedef struct db_val {
+    db_type_t type;              /* Type of the value */
+    int nul;                     /* NULL flag */
+    union {                      
+        int int_val;             /* Integer value */
+        double double_val;       /* Double value */
+	time_t time_val;         /* Unix time_t value */
+	const char* string_val;  /* Zero terminated string */
+	str str_val;             /* str structure */
+	str blob_val;            /* Structure describing blob */
+    } val;
+} db_val_t;
+</programlisting>
+		<note>
+		    <para>
+			All macros expect reference to <type>db_val_t</type> variable as a parameter.
+		    </para>
+		</note>
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_TYPE(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to set/get the type of the value
+			</para>
+			<example>
+			    <title>VAL_TYPE Macro Example</title>
+			    <programlisting format="linespecific">
+...
+VAL_TYPE(val) = DB_INT;
+if (VAL_TYPE(val) == DB_FLOAT)
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_NULL(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to set/get the null flag. Non-zero flag means that 
+			    the corresponding cell in the database contained no data (NULL value in <acronym>MySQL</acronym>
+			    terminology).
+			</para>
+			<example>
+			    <title>VAL_NULL Macro Example</title>
+			    <programlisting format="linespecific">
+...
+if (VAL_NULL(val) == 1) {
+    printf("The cell is NULL");
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_INT(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to access integer value in the <type>db_val_t</type> structure.
+			</para>
+			<example>
+			    <title>VAL_INT Macro Example</title>
+			    <programlisting format="linespecific">
+...
+if (VAL_TYPE(val) == DB_INT) {
+    printf("%d", VAL_INT(val));
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_DOUBLE(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to access double value in the <type>db_val_t</type> structure.
+			</para>
+			<example>
+			    <title>VAL_DOUBLE Macro Example</title>
+			    <programlisting format="linespecific">
+...
+if (VAL_TYPE(val) == DB_DOUBLE) {
+    printf("%f", VAL_DOUBLE(val));
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_TIME(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to access <type>time_t</type> value ind <type>b_val_t</type> structure.
+			</para>
+			<example>
+			    <title>VAL_TIME Macro Example</title>
+			    <programlisting format="linespecific">
+...
+time_t tim;
+if (VAL_TYPE(val) == DB_DATETIME) {
+    tim = VAL_TIME(val);
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_STRING(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to access string value in <type>db_val_t</type> structure.
+			</para>
+			<example>
+			    <title>VAL_STRING Macro Example</title>
+			    <programlisting format="linespecific">
+...
+if (VAL_TYPE(val) == DB_STRING) {
+    printf("%s", VAL_STRING(val));
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_STR(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to access <type>str</type> structure in <type>db_val_t</type> structure.
+			</para>
+			<example>
+			    <title>VAL_STR Macro Example</title>
+			    <programlisting format="linespecific">
+...
+if (VAL_TYPE(val) == DB_STR) {
+    printf("%.*s", VAL_STR(val).len, VAL_STR(val).s);
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">VAL_BLOB(value)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to access blob value in <type>db_val_t</type> structure.
+			</para>
+			<example>
+			    <title>VAL_STR Macro Example</title>
+			    <programlisting format="linespecific">
+...
+if (VAL_TYPE(val) == DB_BLOB) {
+    printf("%.*s", VAL_BLOB(val).len, VAL_BLOB(val).s);
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+		</itemizedlist>
+	    </section> <!-- type-db-val -->
+
+	    <section id="type-db-row">
+		<title>Type <type>db_row_t</type></title>
+		<para>
+		    This type represents one row in a database table. In other words, the row is an
+		    array of <type>db_val_t</type> variables, where each <type>db_val_t</type> variable 
+		    represents exactly one cell in the table.
+		</para>
+		<programlisting format="linespecific">
+typedef struct db_row {
+    db_val_t* values;    /* Array of values in the row */
+    int n;               /* Number of values in the row */
+} db_val_t;
+</programlisting>
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <function moreinfo="none">ROW_VALUES(row)</function> Macro.
+			</para>
+			<para>
+			    Use this macro to get pointer to array of <type>db_val_t</type> structures.
+			</para>
+			<example>
+			    <title>ROW_VALUES Macro Example</title>
+			    <programlisting format="linespecific">
+...
+db_val_t* v = ROW_VALUES(row);
+if (VAL_TYPE(v) == DB_INT)
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">ROW_N(row)</function> Macro.
+			</para>
+			<para>
+			    Use this macro to get number of cells in a row.
+			</para>
+			<example>
+			    <title>ROW_N Macro Example</title>
+			    <programlisting format="linespecific">
+...
+db_val_t* val = ROW_VALUES(row);
+for(i = 0; i < ROW_N(row); i++) {
+    switch(VAL_TYPE(val + i)) {
+        case DB_INT: ...; break;
+        case DB_DOUBLE: ...; break;
+        ...
+    }
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+		</itemizedlist>
+	    </section> <!-- type-db-row -->
+
+	    <section id="type-db-res">
+		<title>Type <type>db_res_t</type></title>
+		<para>
+		    This type represents a result returned by <function moreinfo="none">db_query</function>
+		    function (see below). The  result can consist of zero or more rows 
+		    (see <type>db_row_t</type> description).
+		</para>
+		<note>
+		    <para>
+			A variable of type <type>db_res_t</type> returned by <function moreinfo="none">db_query</function>
+			function uses dynamically allocated memory, don't forget to call 
+			<function moreinfo="none">db_free_query</function> if you don't need  the variable anymore. 
+			You will encounter memory leaks if you fail to do this !
+		    </para>
+		</note>
+		<para>
+		    In addition to zero or more rows, each <type>db_res_t</type> object contains also an array 
+		    of <type>db_key_t</type> objects. The objects represent keys (names of columns).
+		</para>
+		<programlisting format="linespecific">
+typedef struct db_res {
+    struct {
+        db_key_t* keys;    /* Array of column names */
+	db_type_t* types;  /* Array of column types */
+	int n;             /* Number of columns */
+    } col;
+    struct db_row* rows;   /* Array of rows */
+    int n;                 /* Number of rows */
+} db_res_t;
+</programlisting>
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <function moreinfo="none">RES_NAMES(res)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you want to obtain pointer to an array of cell names.
+			</para>
+			<example>
+			    <title>RES_NAMES Macro Example</title>
+			    <programlisting format="linespecific">
+...
+db_key_t* column_names = ROW_NAMES(row);
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">RES_COL_N(res)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you want to get the number of columns in the result.
+			</para>
+			<example>
+			    <title>RES_COL_N Macro Example</title>
+			    <programlisting format="linespecific">
+...
+int ncol = RES_COL_N(res)
+for(i = 0; i < ncol; i++) {
+    /* do something with the column */
+}
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">RES_ROWS(res)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to obtain pointer to array of rows.
+			</para>
+			<example>
+			    <title>RES_ROWS Macro Example</title>
+			    <programlisting format="linespecific">
+...
+db_row_t* rows = RES_ROWS(res);
+...
+</programlisting>
+			</example>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <function moreinfo="none">RES_ROW_N(res)</function> Macro.
+			</para>
+			<para>
+			    Use this macro if you need to obtain the number of rows in the result.
+			</para>
+			<example>
+			    <title>RES_ROW_N Macro Example</title>
+			    <programlisting format="linespecific">
+...
+int n = RES_ROW_N(res);
+...
+</programlisting>
+			</example>
+		    </listitem>
+		</itemizedlist>
+	    </section> <!-- type-db-res -->
+	</section> <!-- data-types -->
+
+	<section id="db-functions">
+	    <title>Functions</title>
+	    <para>
+		There are several functions that implement the database <acronym>API</acronym> logic. All function
+		names start with db_ prefix, except <function moreinfo="none">bind_dbmod</function>. 
+		<function moreinfo="none">bind_dbmod</function>is implemented in <filename moreinfo="none">db.c</filename>
+		file, all other functions are implemented in a standalone module.
+		Detaileddescription of functions follows.
+	    </para>
+
+	    <section id="bind-dbmod">
+		<title><function moreinfo="none">bind_dbmod</function></title>
+		<para>
+		    This function is special, it's only purpose is to call <function moreinfo="none">find_export</function>
+		    function in the <acronym>SER</acronym> core and find addresses of all other functions (starting with db_
+		    prefix). This function <emphasis>MUST</emphasis> be called <emphasis>FIRST</emphasis> !
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">bind_dbmod</function></funcdef>
+			<void>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes no parameters.
+		</para>
+		<para>
+		    The function returns 0 if it was able to find addresses of all other 
+		    functions, otherwise value &lt; 0 is returned.
+		</para>
+	    </section> <!-- bin-dbmod -->
+
+	    <section id="db-init">
+		<title><function moreinfo="none">db_init</function></title>
+		<para>
+		    Use this function to initialize the database <acronym>API</acronym> and open a new database 
+		    connection. This function must be called after <function moreinfo="none">bind_dbmod</function>
+		    but before any other function is called.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>db_con_t* <function moreinfo="none">db_init</function></funcdef>
+			<paramdef>const char* <parameter moreinfo="none">_sql_url</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes one parameter, the parameter must contain database 
+		    connection <acronym>URL</acronym>. The <acronym>URL</acronym> is of the form 
+		    sql://username:password@host:port/database where:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>username</emphasis> - Username to use when logging into database (optional).
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>password</emphasis> - Password if it was set (optional).
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>host</emphasis> -  Hosname or IP address of the host 
+				where database server lives (mandatory).
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>port</emphasis> - Port number of the server if the port 
+				differs from default value (optional).
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>database</emphasis> - If the database server supports 
+				multiple databases, you must specify name of the database (optional).
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    The function returns pointer to <type>db_con_t</type>* representing the connection if it was
+		    successful, otherwise 0 is returned.
+		</para>
+	    </section> <!-- db-init -->
+
+	    <section id="db-close">
+		<title><function moreinfo="none">db_close</function></title>
+		<para>
+		    The function closes previously open connection and frees all previously 
+		    allocated memory. The function <function moreinfo="none">db_close</function> must be the very last 
+		    function called.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>void <function moreinfo="none">db_close</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes one parameter, this parameter is a pointer to <type>db_con_t</type>
+		    structure representing database connection that should be closed.
+		</para>
+		<para>
+		    Function doesn't return anything.
+		</para>
+	    </section> <!-- db-close -->
+
+	    <section id="db-query">
+		<title><function moreinfo="none">db_query</function></title>
+		<para>
+		    This function implements SELECT SQL directive.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">db_query</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
+			<paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_c</parameter></paramdef>
+			<paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
+			<paramdef>int <parameter moreinfo="none">_nc</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_o</parameter></paramdef>
+			<paramdef>db_res_t** <parameter moreinfo="none">_r</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes 8 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>_h</emphasis> - Database connection handle.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_k</emphasis> - Array of column names that will be compared and 
+				their values must match.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_v</emphasis> - Array of values, columns specified in _k parameter must match 
+				these values.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_c</emphasis> - Array of column names that you are interested in.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_n</emphasis> - Number of key-value pairs to match in _k and _v parameters.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_nc</emphasis> - Number of columns in _c parameter.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_o</emphasis> - Order by.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>_r</emphasis> - Address of variable where pointer to the result will be stored.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		    If _k and _v parameters are NULL and _n is zero, you will get the whole table.
+		    if _c is NULL and _nc is zero, you will get all table columns in the result
+		</para>
+		<para>
+		    _r will point to a dynamically allocated structure, it is neccessary to call
+		    db_free_query function once you are finished with the result.
+		</para>
+		<para>
+		    Strings in the result are not duplicated, they will be discarded if you call
+		    db_free_query, make a copy yourself if you need to keep it after db_free_query.
+		</para>
+		<para>
+		    You must call db_free_query <emphasis>BEFORE</emphasis> you can call db_query again !
+		</para>
+		<para>
+		    The function returns 0 if everything is OK, otherwise value &lt; 0 is returned.
+		</para>
+	    </section> <!-- db-query -->
+
+	    <section id="db-free-query">
+		<title><function moreinfo="none">db_free_query</function></title>
+		<para>
+		    This function frees all memory allocated previously in <function moreinfo="none">db_query</function>, 
+		    it is neccessary to call this function on a db_res_t structure if you don't need the
+		    structure anymore. You must call this function <emphasis>BEFORE</emphasis> you call 
+		    <function moreinfo="none">db_query</function> again !
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">db_free_query</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+			<paramdef>db_res_t* <parameter moreinfo="none">_r</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes 2 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_h</parameter> - Database connection handle.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_r</parameter> - Pointer to db_res_t structure to destroy.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    The function returns 0 if everything is OK, otherwise the function returns
+		    value &lt; 0.
+		</para>
+	    </section> <!-- db-free-query -->
+
+	    <section id="db-insert">
+		<title><function moreinfo="none">db_insert</function></title>
+		<para>
+		    This function implements INSERT SQL directive, you can insert one or more
+		    rows in a table using this function.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">db_insert</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
+			<paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
+			<paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes 4 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_h</parameter> - Database connection handle.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_k</parameter> - Array of keys (column names).
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_v</parameter> - Array of values for keys specified in _k parameter.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_n</parameter> - Number of keys-value pairs int _k and _v parameters.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    The function returns 0 if everything is OK, otherwise the function returns
+		    value &lt; 0.
+		</para>
+	    </section> <!-- db-insert -->
+
+	    <section id="db-delete">
+		<title><function moreinfo="none">db_delete</function></title>
+		<para>
+		    This function implements DELETE SQL directive, it is possible to delete one or
+		    more rows from a table.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">db_delete</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
+			<paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
+			<paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes 4 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_h</parameter> - Database connection handle.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_k</parameter> - Array of keys (column names) that will be matched.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_v</parameter> - Array of values that the row must match 
+				to be deleted.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_n</parameter> - Number of keys-value parameters in _k and _v 
+				parameters.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		    If _k is NULL and _v is NULL and _n is zero, all rows are deleted (table will
+		    be empty).
+		</para>
+		<para>
+		    The function returns 0 if everything is OK, otherwise the function returns
+		    value &lt; 0.
+		</para>
+	    </section> <!-- db-delete -->
+
+	    <section id="db-update">
+		<title><function moreinfo="none">db_update</function></title>
+		<para>
+		    The function implements UPDATE SQL directive. It is possible to modify one
+		    or more rows in a table using this function.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">db_update</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
+			<paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
+			<paramdef>db_key_t* <parameter moreinfo="none">_uk</parameter></paramdef>
+			<paramdef>db_val_t* <parameter moreinfo="none">_uv</parameter></paramdef>
+			<paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
+			<paramdef>int <parameter moreinfo="none">_un</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes 7 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_h</parameter> - Database connection handle.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_k</parameter> - Array of keys (column names) that will be matched.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_v</parameter> - Array of values that the row must match 
+				to be modified.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_uk</parameter> - Array of keys (column names) that will be modified.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_uv</parameter> - New values for keys specified in _k parameter.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_n</parameter> - Number of key-value pairs in _k and _v parameters.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_un</parameter> - Number of key-value pairs 
+				in _uk and _uv parameters.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    The function returns 0 if everything is OK, otherwise the function returns
+		    value &lt; 0.
+		</para>
+	    </section> <!-- db-update -->
+
+	    <section id="db-use-table">
+		<title><function moreinfo="none">db_use_table</function></title>
+		<para>
+		    The function db_use_table takes a table name and stores it db_con_t structure.
+		    All subsequent operations (insert, delete, update, query) are performed on
+		    that table.
+		</para>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>int <function moreinfo="none">db_use-table</function></funcdef>
+			<paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
+			<paramdef>cons char* <parameter moreinfo="none">_t</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<para>
+		    The function takes 2 parameters:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_h</parameter> - Database connection handle.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<parameter moreinfo="none">_t</parameter> - Table name.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    The function returns 0 if everything is OK, otherwise the function returns
+		    value &lt; 0.
+		</para>
+	    </section> <!-- db-use-table -->
+	</section> <!-- db-functions -->
+    </chapter> <!-- db-interface -->
+
+    <chapter id="fifo-server">
+	<title>FIFO Server</title>
+	<para>
+	    TBD by Jiri.
+	</para>
+    </chapter> <!-- fifo-server -->
+    
+    <chapter id="basic-modules">
+	<title>Basic Modules</title>
+	<section id="auth">
+	    <title>Digest Authentication</title>
+	    <para></para>
+	</section> <!-- auth -->
+	<section id="max-fwd">
+	    <title>Max Forwards</title>
+	    <para></para>
+	</section> <!-- max-fwd -->
+	<section id="mysql">
+	    <title>MySQL</title>
+	    <para></para>
+	</section> <!-- mysql -->
+	<section id="registrar">
+	    <title>Registrar</title>
+	    <para></para>
+	</section> <!-- registrar -->
+	<section id="rr">
+	    <title>Record-Routing</title>
+	    <para></para>
+	</section> <!-- rr -->
+	<section id="sl">
+	    <title>Stateless Replies</title>
+	    <para></para>
+	</section> <!-- sl -->
+	<section id="tm">
+	    <title>Transaction Module</title>
+	    <para>
+		TBD by Jiri.
+	    </para>
+	</section> <!-- tm -->
+	<section id="usrloc">
+	    <title>User Location Module</title>
+	    <para></para>
+	</section> <!-- usrloc -->
+	<section id="sms">
+	    <title>SMS Module</title>
+	    <para>
+		TBD by Bogdan.
+	    </para>
+	</section> <!-- sms -->
+	<section id="jabber">
+	    <title>Jabber Module</title>
+	    <para>
+		TBD by Daniel.
+	    </para>
+	</section> <!-- jabber -->
+	<section id="im">
+	    <title>Instant Messaging Module</title>
+	    <para>
+		TBD by Bogdan.
+	    </para>
+	</section> <!-- im -->
+	<section id="ext">
+	    <title>External Module</title>
+	    <para>
+		    TBD by Bogdan or Jiri.
+	    </para>
+	</section> <!-- ext -->
+    </chapter> <!-- basic-modules -->
+
+    <chapter id="message-modif">
+	<title><acronym>SIP</acronym> Message Modifications</title>
+	<para>TBD by Andrei or Jan.</para>
+    </chapter> <!-- message-modif -->
+
+    <chapter id="tips">
+	<title>Tips And Tricks</title>
+	<para>
+	    jak se prochazi vsechny hlavicky daneho typu
+	    Jak vlozit header na konec hlavicky
+	    jak vlozit prvni header
+	    jak neco vymazat
+	    jak vlozit header do odpovedi
+	    jak postupne prochazet headery stejneho typu dokud
+	    nenaleznu ten pravy
+	    jak spravne parsovat !!!
+	    jak se vola destroy, z jakeho procesu, kolikrat
+	    proc se init modules vola tam, kde se vola
+	    fix_rls se vola az po ini_modules - proc
+	    mod_init je vzdycky prvni zavolana funkce modulu !
+	    nelze destroy data z potomku
+	    builtin core commands -description
+	    popsat system proxy
+	    vsechno spravne prolinkovat
+	    Opravit dokumentaci k append_branch - pravdepodobne
+	    je tam spatne popis
+	    Popsat flagy
+	    Dopsat nekam poznamku ze vetsina field pri parsovani nejsou ukoncena
+	    0 a ze jsou to pouze pointery a delky do buf bufferu zpravy
+	    Adding a new header field body parser
+	    How to parse a header field body
+	    Jak udelat funkce, ktere nepujdou volat ze skriptu, ale jenom z ostatnich
+	    modulu.
+	    FAQ
+	</para>
+    </chapter> <!-- tips -->
+</book>