Przeglądaj źródła

- Improved documentation system
- documentation makefiles
- XML-based dialect of docbook used

Jan Janak 20 lat temu
rodzic
commit
9b81fab060
46 zmienionych plików z 6794 dodań i 7636 usunięć
  1. 29 0
      doc/serdev/Makefile
  2. 15 0
      doc/serdev/contact_body.xml
  3. 204 0
      doc/serdev/contact_parser.xml
  4. 49 0
      doc/serdev/cseq_body.xml
  5. 58 0
      doc/serdev/cseq_parser.xml
  6. 44 0
      doc/serdev/data_structures.xml
  7. 34 0
      doc/serdev/db_con_t.xml
  8. 508 0
      doc/serdev/db_interface.xml
  9. 27 0
      doc/serdev/db_key_t.xml
  10. 123 0
      doc/serdev/db_res_t.xml
  11. 74 0
      doc/serdev/db_row_t.xml
  12. 37 0
      doc/serdev/db_type_t.xml
  13. 241 0
      doc/serdev/db_val_t.xml
  14. 536 0
      doc/serdev/digest_parser.xml
  15. 55 0
      doc/serdev/event_parser.xml
  16. 49 0
      doc/serdev/event_t.xml
  17. 43 0
      doc/serdev/exp_body_t.xml
  18. 39 0
      doc/serdev/expires_parser.xml
  19. 33 0
      doc/serdev/fline_parser.xml
  20. 47 0
      doc/serdev/from_parser.xml
  21. 92 0
      doc/serdev/hdr_field.xml
  22. 252 0
      doc/serdev/hfname_parser.xml
  23. 33 0
      doc/serdev/ip_addr.xml
  24. 0 262
      doc/serdev/locking.sgml
  25. 289 0
      doc/serdev/locking.xml
  26. 25 0
      doc/serdev/lump.xml
  27. 25 0
      doc/serdev/lump_rpl.xml
  28. 132 0
      doc/serdev/main_loop.xml
  29. 0 434
      doc/serdev/modiface.sgml
  30. 800 0
      doc/serdev/modiface.xml
  31. 316 0
      doc/serdev/module_exports.xml
  32. 94 0
      doc/serdev/msg_parser.xml
  33. 114 0
      doc/serdev/msg_start.xml
  34. 467 0
      doc/serdev/routing_engine.xml
  35. 0 6940
      doc/serdev/serdev.sgml
  36. 73 0
      doc/serdev/serdev.xml
  37. 100 0
      doc/serdev/shutdown.xml
  38. 397 0
      doc/serdev/sip_msg.xml
  39. 61 0
      doc/serdev/sip_uri.xml
  40. 66 0
      doc/serdev/sr_module.xml
  41. 810 0
      doc/serdev/startup.xml
  42. 69 0
      doc/serdev/str.xml
  43. 80 0
      doc/serdev/to_body.xml
  44. 58 0
      doc/serdev/to_parser.xml
  45. 141 0
      doc/serdev/via_body.xml
  46. 55 0
      doc/serdev/via_parser.xml

+ 29 - 0
doc/serdev/Makefile

@@ -0,0 +1,29 @@
+#
+# The list of documents to build (without extensions)
+#
+DOCUMENTS = serdev
+
+#
+# The root directory containing Makefile.doc
+#
+ROOT_DIR=../..
+
+#
+# Validate docbook documents before generating output
+# (may be slow)
+#
+#VALIDATE=1
+
+#
+# You can override the stylesheet used to generate
+# xhtml documents here
+#
+#XHTML_XSL=$(ROOT_DIR)/doc/stylesheets/xhtml.xsl
+
+#
+# You can override the stylesheet used to generate
+# plain text documents here
+#
+#TXT_XSL=$(XHTML_XSL)
+
+include $(ROOT_DIR)/Makefile.doc

+ 15 - 0
doc/serdev/contact_body.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="contact_body" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+</section>

+ 204 - 0
doc/serdev/contact_parser.xml

@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="contact_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Contact Header Field Parser</title>
+    <para>
+	The parser is located under <filename>parser/contact</filename>
+	subdirectory. The parser is not called automatically 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>parse_contact</function> in file
+	<filename>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>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>contact_parser</function> will then check if the
+	contact is star, if not it will call
+	<function>parse_contacts</function> function that will parse all
+	contacts of the header field.
+    </para>
+    <para>
+	Function <function>parse_contacts</function> can be found in file
+	<filename>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>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 careful when processing the strings with
+	    functions that require zero termination (printf for example) !
+	</para>
+    </note>
+    <programlisting>
+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>
+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>
+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>
+/*
+ * 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 "=").
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>body</structfield> - Body of the parameter
+		    (i.e. the part after "=").
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>next</structfield> - Next parameter in the linked list.
+		</para>
+	    </listitem>
+	</itemizedlist>
+    </para>
+</section>

+ 49 - 0
doc/serdev/cseq_body.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="cseq_body" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Structure <structname>cseq_body</structname></title>
+    <para>
+	The structure represents parsed CSeq body. The structure is declared in
+	<filename>parse_cseq.h</filename> file.
+    </para>
+    <para><emphasis>Structure Declaration:</emphasis></para>
+    <programlisting>
+struct cseq_body{
+    int error;  /* Error code */
+    str number; /* CSeq number */
+    str method; /* Associated method */
+};
+    </programlisting>
+    <para>
+	<emphasis>Field Description:</emphasis>
+	<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>
+    </para>
+</section>

+ 58 - 0
doc/serdev/cseq_parser.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="cseq_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>CSeq Header Field Parser</title>
+    <para>
+	Purpose of this parser is to parse body of CSeq header field. The
+	parser can be found in file <filename>parse_cseq.c</filename> under
+	<filename>parser</filename> subdirectory.
+    </para>
+    <para>
+	Main function is <function>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>get_cseq</function> in file <filename>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>get_hdr_field</function> in file
+	<filename>msg_parser.c</filename>. The function first creates and
+	initializes an instance of <structname>cseq_body</structname>
+	structure, then calls <function>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>clean_hdr_field</function> in file
+	<filename>hf.c</filename> for more details.
+    </para>
+    <para>
+	See <xref linkend="cseq_body"/> for description of the
+	<structname>cseq_body</structname> structure.
+    </para>
+</section>

+ 44 - 0
doc/serdev/data_structures.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="data_structures" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Data Structures</title>
+    <para>
+	There are some data structures that are important and widely used in
+	the server. We will describe them in detail 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
+	    if needed.
+	</para>
+    </note>
+
+    <xi:include href="str.xml"/>
+    <xi:include href="hdr_field.xml"/>
+    <xi:include href="sip_uri.xml"/>
+    <xi:include href="via_body.xml"/>
+    <xi:include href="ip_addr.xml"/>
+    <xi:include href="lump.xml"/>
+    <xi:include href="lump_rpl.xml"/>
+    <xi:include href="msg_start.xml"/>
+    <xi:include href="sip_msg.xml"/>
+    <xi:include href="to_body.xml"/>
+    <xi:include href="cseq_body.xml"/>
+    <xi:include href="event_t.xml"/>
+    <xi:include href="exp_body_t.xml"/>
+
+</section>

+ 34 - 0
doc/serdev/db_con_t.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_con_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <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 <type>db_con_t</type> type serves as a handle for a
+	particular database connection.
+    </para>
+    <programlisting>
+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>

+ 508 - 0
doc/serdev/db_interface.xml

@@ -0,0 +1,508 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_interface" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <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 data types. All of them are defined in header
+	    files under <filename>db</filename> subdirectory, a client must
+	    include <filename>db.h</filename> header file to be able to use
+	    them.
+	</para>
+
+	<xi:include href="db_con_t.xml"/>
+	<xi:include href="db_key_t.xml"/>
+	<xi:include href="db_type_t.xml"/>
+	<xi:include href="db_val_t.xml"/>
+	<xi:include href="db_row_t.xml"/>
+	<xi:include href="db_res_t.xml"/>
+    </section>
+	
+    <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>bind_dbmod</function>.
+	    <function>bind_dbmod</function> is implemented in
+	    <filename>db.c</filename> file, all other functions are implemented
+	    in a standalone module.  Detailed description of functions follows.
+	</para>
+	
+	<section id="bind_dbmod">
+	    <title><function>bind_dbmod</function></title>
+	    <para>
+		This function is special, it's only purpose is to call
+		<function>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>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> <!-- bind_dbmod -->
+	
+	<section id="db_init">
+	    <title><function>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>bind_dbmod</function>
+		but before any other function is called.
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>db_con_t* <function>db_init</function></funcdef>
+		    <paramdef>const char* <parameter>_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
+		mysql://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> - Hostname 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>db_close</function></title>
+	    <para>
+		The function closes previously open connection and frees all
+		previously allocated memory. The function
+		<function>db_close</function> must be the very last function
+		called.
+	    </para>
+		<funcsynopsis>
+		<funcprototype>
+		    <funcdef>void <function>db_close</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_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>db_query</function></title>
+	    <para>
+		This function implements SELECT <acronym>SQL</acronym> directive.
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>db_query</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_h</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_k</parameter></paramdef>
+		    <paramdef>db_val_t* <parameter>_v</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_c</parameter></paramdef>
+		    <paramdef>int <parameter>_n</parameter></paramdef>
+		    <paramdef>int <parameter>_nc</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_o</parameter></paramdef>
+		    <paramdef>db_res_t** <parameter>_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
+		necessary to call db_free_result 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_result, make a copy yourself if
+		you need to keep it after db_free_result.
+	    </para>
+	    <para>
+		You must call db_free_result <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_result">
+	    <title><function>db_free_result</function></title>
+	    <para>
+		This function frees all memory allocated previously in
+		<function>db_query</function>, it is necessary to call this
+		function for a <type>db_res_t</type> structure if you don't
+		need the structure anymore. You must call this function
+		<emphasis>BEFORE</emphasis> you call
+		<function>db_query</function> again !
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>db_free_result</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_h</parameter></paramdef>
+		    <paramdef>db_res_t* <parameter>_r</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <para>
+		The function takes 2 parameters:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <parameter>_h</parameter> - Database connection handle.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_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_result -->
+	
+	<section id="db_insert">
+	    <title><function>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>db_insert</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_h</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_k</parameter></paramdef>
+		    <paramdef>db_val_t* <parameter>_v</parameter></paramdef>
+		    <paramdef>int <parameter>_n</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <para>
+		The function takes 4 parameters:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <parameter>_h</parameter> - Database connection handle.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_k</parameter> - Array of keys (column names).
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_v</parameter> - Array of values for
+			    keys specified in _k parameter.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_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>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>db_delete</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_h</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_k</parameter></paramdef>
+		    <paramdef>db_val_t* <parameter>_v</parameter></paramdef>
+		    <paramdef>int <parameter>_n</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <para>
+		The function takes 4 parameters:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <parameter>_h</parameter> - Database connection handle.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_k</parameter> - Array of keys
+			    (column names) that will be matched.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_v</parameter> - Array of values
+			    that the row must match to be deleted.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_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>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>db_update</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_h</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_k</parameter></paramdef>
+		    <paramdef>db_val_t* <parameter>_v</parameter></paramdef>
+		    <paramdef>db_key_t* <parameter>_uk</parameter></paramdef>
+		    <paramdef>db_val_t* <parameter>_uv</parameter></paramdef>
+		    <paramdef>int <parameter>_n</parameter></paramdef>
+		    <paramdef>int <parameter>_un</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <para>
+		The function takes 7 parameters:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <parameter>_h</parameter> - Database connection handle.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_k</parameter> - Array of keys (column names) that will be matched.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_v</parameter> - Array of values that the row must match 
+			    to be modified.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_uk</parameter> - Array of keys (column names) that will be modified.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_uv</parameter> - New values for keys specified in _k parameter.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_n</parameter> - Number of key-value pairs in _k and _v parameters.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_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>db_use_table</function></title>
+	    <para>
+		The function db_use_table takes a table name and stores it
+		in db_con_t structure.  All subsequent operations (insert,
+		delete, update, query) are performed on that table.
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>db_use-table</function></funcdef>
+		    <paramdef>db_con_t* <parameter>_h</parameter></paramdef>
+		    <paramdef>cons char* <parameter>_t</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <para>
+		The function takes 2 parameters:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <parameter>_h</parameter> - Database connection handle.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <parameter>_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>
+    </section>
+</section>

+ 27 - 0
doc/serdev/db_key_t.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_key_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <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
+	<type>const char*</type>.
+    </para>
+    <programlisting>
+typedef const char* db_key_t;
+    </programlisting>
+    <para>
+	There are no macros defined (they are not needed).
+    </para>
+</section>

+ 123 - 0
doc/serdev/db_res_t.xml

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_res_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Type <type>db_res_t</type></title>
+    <para>
+	This type represents a result returned by <function>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>db_query</function> function uses dynamically allocated
+	    memory, don't forget to call <function>db_free_result</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>
+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>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</title>
+		<programlisting>
+...
+db_key_t* column_names = ROW_NAMES(row);
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>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</title>
+		<programlisting>
+<![CDATA[
+...
+int ncol = RES_COL_N(res);
+for(i = 0; i < ncol; i++) {
+    /* do something with the column */
+}
+...
+]]>
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>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</title>
+		<programlisting>
+...
+db_row_t* rows = RES_ROWS(res);
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>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</title>
+		<programlisting>
+...
+int n = RES_ROW_N(res);
+...
+		</programlisting>
+	    </example>
+	</listitem>
+    </itemizedlist>
+</section>
+

+ 74 - 0
doc/serdev/db_row_t.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_row_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>
+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>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</title>
+		<programlisting>
+...
+db_val_t* v = ROW_VALUES(row);
+if (VAL_TYPE(v) == DB_INT)
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>ROW_N(row)</function> Macro.
+	    </para>
+	    <para>
+		Use this macro to get number of cells in a row.
+	    </para>
+	    <example>
+		<title>ROW_N Macro</title>
+		<programlisting>
+<![CDATA[
+...
+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>

+ 37 - 0
doc/serdev/db_type_t.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_type_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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 data-type 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>
+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>

+ 241 - 0
doc/serdev/db_val_t.xml

@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="db_val_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Type <type>db_val_t</type></title>
+    <para>
+	This structure represents a value in the database. Several data-types
+	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 data-types are automatically recognized, converted from internal
+	database representation and stored in a variable of corresponding type.
+    </para>
+    <programlisting>
+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 pinter to <type>db_val_t</type> variable as a
+	    parameter.
+	</para>
+    </note>
+    <itemizedlist>
+	<listitem>
+	    <para>
+		<function>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</title>
+		<programlisting>
+...
+VAL_TYPE(val) = DB_INT;
+if (VAL_TYPE(val) == DB_FLOAT)
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>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</title>
+		<programlisting>
+...
+if (VAL_NULL(val) == 1) {
+    printf("The cell is NULL");
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>VAL_INT(value)</function> Macro.
+	    </para>
+	    <para>
+		Use this macro if you need to access <type>integer</type> value
+		in <type>db_val_t</type> structure.
+	    </para>
+	    <example>
+		<title>VAL_INT Macro</title>
+		<programlisting>
+...
+if (VAL_TYPE(val) == DB_INT) {
+    printf("%d", VAL_INT(val));
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>VAL_DOUBLE(value)</function> Macro.
+	    </para>
+	    <para>
+		Use this macro if you need to access <type>double</type> value
+		in the <type>db_val_t</type> structure.
+	    </para>
+	    <example>
+		<title>VAL_DOUBLE Macro</title>
+		<programlisting>
+...
+if (VAL_TYPE(val) == DB_DOUBLE) {
+    printf("%f", VAL_DOUBLE(val));
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>VAL_TIME(value)</function> Macro.
+	    </para>
+	    <para>
+		Use this macro if you need to access <type>time_t</type> value
+		in <type>db_val_t</type> structure.
+	    </para>
+	    <example>
+		<title>VAL_TIME Macro</title>
+		<programlisting>
+...
+time_t tim;
+if (VAL_TYPE(val) == DB_DATETIME) {
+    tim = VAL_TIME(val);
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>VAL_STRING(value)</function> Macro.
+	    </para>
+	    <para>
+		Use this macro if you need to access <type>string</type> value
+		in <type>db_val_t</type> structure.
+	    </para>
+	    <example>
+		<title>VAL_STRING Macro</title>
+		<programlisting>
+...
+if (VAL_TYPE(val) == DB_STRING) {
+    printf("%s", VAL_STRING(val));
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>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</title>
+		<programlisting>
+...
+if (VAL_TYPE(val) == DB_STR) {
+    printf("%.*s", VAL_STR(val).len, VAL_STR(val).s);
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+	
+	<listitem>
+	    <para>
+		<function>VAL_BLOB(value)</function> Macro.
+	    </para>
+	    <para>
+		Use this macro if you need to access <type>blob</type> value in <type>db_val_t</type> structure.
+	    </para>
+	    <example>
+		<title>VAL_STR Macro</title>
+		<programlisting>
+...
+if (VAL_TYPE(val) == DB_BLOB) {
+    printf("%.*s", VAL_BLOB(val).len, VAL_BLOB(val).s);
+}
+...
+		</programlisting>
+	    </example>
+	</listitem>
+    </itemizedlist>
+</section>

+ 536 - 0
doc/serdev/digest_parser.xml

@@ -0,0 +1,536 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="digest_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Digest Body Parser</title>
+    <para>
+	Purpose of this parser is to parse digest response. The parser can be
+	found under <filename>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 automatically 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>parse_credentials</function> defined in
+	<filename>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 structures follows:
+	<programlisting>
+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>
+    <para>
+	This is the "main" structure. 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
+		    successfully authorized credentials (currently there is
+		    only one such function in the server, it is function
+		    <function>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 containing
+		    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>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
+		    "stale=true" parameter. "stale=true" 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>
+/*
+ * 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>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>
+/* 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> - "algorithm=MD5" was found in
+		    digest response.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <emphasis>ALG_MD5SESS</emphasis> - "algorithm=MD5-Session"
+		    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>
+/* 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> - "qop=auth" was found in
+		    digest response.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <emphasis>QOP_AUTHINT</emphasis> - "qop=auth-int" was found
+		    in digest response.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <emphasis>QOP_OTHER</emphasis> - Unknown qop parameter
+		    value was found in digest response.
+		</para>
+	    </listitem>
+	</itemizedlist>
+    </para>
+
+    <programlisting>
+/* Algorithm structure */
+struct algorithm {
+     str alg_str;       /* The original string representation */
+     alg_t alg_parsed;  /* Parsed value */
+};
+    </programlisting>
+    <para>
+	The structure represents "algorithm" 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>
+/* QOP structure */
+struct qp {
+    str qop_str;           /* The original string representation */
+    qop_type_t qop_parsed; /* Parsed value */
+};
+    </programlisting>
+    <para>
+	This structure represents "qop" 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 "qop"
+		    parameter value.
+		</para>
+	    </listitem>
+	</itemizedlist>
+    </para>
+    
+    <programlisting>
+/*
+ * 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 "username"
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>realm</structfield> - Value of "realm"
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>nonce</structfield> - Value of "nonce"
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>uri</structfield> - Value of "uri" parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>response</structfield> - Value of "response"
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>algorithm</structfield> - Value of "algorithm"
+		    parameter as string.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>alg</structfield> - Parsed value of
+		    "algorithm" parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>cnonce</structfield> - Value of "cnonce"
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>opaque</structfield> - Value of "opaque"
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>qop</structfield> - Value of "qop" parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>nc</structfield> - Value of "nc" parameter.
+		</para>
+	    </listitem>
+	</itemizedlist>
+    </para>
+    
+    <section id="other_functions">
+	<title>Other Functions Of the Digest 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>digest.c</filename> file.
+	</para>
+	
+	<funcsynopsis>
+	    <funcprototype>
+		<funcdef>dig_err_t <function>check_dig_cred</function></funcdef>
+		<paramdef>dig_cred_t* <parameter>_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 successful:
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			There must be non-empty "username" parameter in the
+			credentials.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			There must be non-empty "realm" parameter in the
+			credentials.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			There must be non-empty "nonce" parameter in the
+			credentials.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			There must be non-empty "uri" parameter in the
+			credentials.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			There must be non-empty "response" 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 "cnonce" and "nc"
+			parameters in the digest.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</para>
+	<note>
+	    <para>
+		It is recommended to call <function>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>mark_authorized_cred</function></funcdef>
+		<paramdef>struct sip_msg* <parameter>_m</parameter></paramdef>
+		<paramdef>struct hdr_field* <parameter>_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>get_authorized_cred</function></funcdef>
+		<paramdef>struct sip_msg* <parameter>_m</parameter></paramdef>
+		<paramdef>struct hdr_field** <parameter>_h</parameter></paramdef>
+	    </funcprototype>
+	</funcsynopsis>
+	
+	<para>
+	    This is convenience function. The function will retrieve pointer to
+	    authorized credentials previously saved using
+	    <function>mark_authorized_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>
+</section>

+ 55 - 0
doc/serdev/event_parser.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="event_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Event 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>parse_event.c</filename> under
+	<filename>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 "OTHER".
+	</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>parse_event</function> in file
+	<filename>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>clean_hdr_field</function> in file <filename>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>parse_event</function> function).
+    </para>
+
+    <xi:include href="event_t.xml"/>
+</section>

+ 49 - 0
doc/serdev/event_t.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="event_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Structure <structname>event_t</structname></title>
+    <para>
+	The structure represents parsed Event body. The structure is declared
+	in <filename>parse_event.h</filename> file.
+    </para>
+    <para><emphasis>Structure Declaration:</emphasis>
+	<programlisting>
+#define EVENT_OTHER    0
+#define EVENT_PRESENCE 1
+
+typedef struct event {
+    str text;   /* Original string representation */
+    int parsed; /* Parsed variant */
+} event_t;
+	</programlisting>
+    </para>
+
+    <para>
+	<emphasis>Field Description:</emphasis>
+	<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>
+    </para>
+</section>

+ 43 - 0
doc/serdev/exp_body_t.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="exp_body_t" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Structure <structname>exp_body_t</structname></title>
+    <para>
+	The structure represents parsed Expires body. The structure is declared
+	in <filename>parse_expires.h</filename> file.
+    </para>
+    <para><emphasis>Structure Declaration:</emphasis>
+	<programlisting>
+typedef struct exp_body {
+    str text;   /* Original text representation */
+    int val;    /* Parsed value */
+} exp_body_t;
+	</programlisting>
+    </para>
+
+    <para><emphasis>Field Description:</emphasis>
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    <structfield>text</structfield> - Expires value as text.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>val</structfield> - Expires value as integer.
+		</para>
+	    </listitem>
+	</itemizedlist>
+    </para>
+</section>

+ 39 - 0
doc/serdev/expires_parser.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="expires_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>parse_expires.c</filename>
+	under <filename>parser</filename> subdirectory. Main function is
+	<function>parse_expires</function>. The function is not called
+	automatically 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>
+
+    <xi:include href="exp_body_t.xml"/>
+</section>

+ 33 - 0
doc/serdev/fline_parser.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="fline_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+
+    </sectioninfo>
+    
+    <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>parse_fline.h</filename> under <filename>parser</filename>
+	subdirectory.
+    </para>
+    <para>
+	The main function of the first line parser is
+	<function>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>

+ 47 - 0
doc/serdev/from_parser.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="from_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>From Header Field 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>parse_from.c</filename>
+	under <filename>parser</filename> subdirectory. There is only one
+	function called <function>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>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 automatically. It is up to you to call the
+	<function>parse_from_header</function> when you want to parse a From
+	header field body.
+    </para>
+</section>

+ 92 - 0
doc/serdev/hdr_field.xml

@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="hdr_field" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Structure <structname>hdr_field</structname></title>
+    
+    <para>
+	The structure represents a header field of a SIP message. A header
+	field consist of <emphasis>name</emphasis> and
+	<emphasis>body</emphasis> separated by a double colon.  For example:
+	"Server: SIP Express Router\r\n" is one header field. "Server" is
+	header field name and "SI Express Router\r\n" is header field body.
+    </para>
+    <para>
+	The structure is defined in file <filename>hf.h</filename> under
+	<filename>parser</filename> subdirectory.
+    </para>
+    <para>
+	<emphasis>Structure Declaration</emphasis>
+	<programlisting>
+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>
+    <para>
+	<emphasis>Field Description:</emphasis>
+	<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 self explanatory. HDR_OTHER marks header
+		    field not recognized by the parser.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>name</structfield> - Name of the header field
+		    (the part before colon)
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>body</structfield> - body of the header field
+		    (the part after colon)
+		</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 <type>void*</type> 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>
+    </para>
+</section>

+ 252 - 0
doc/serdev/hfname_parser.xml

@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="hfname_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>parse_hname2</function>. The function can be found in file
+	<filename>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 comparison 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 pre-calculate 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>init_hfname_parser</function>).
+    </para>
+    <para>
+	The header name parser consists of several files, all of them are under
+	<filename>parser</filename> subdirectory. Main file is
+	<filename>parse_hname2.c</filename> - this files contains the parser
+	itself and functions used to initialize and lookup the hash table. File
+	<filename>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 (":"), minus or space and these
+	characters are not allowed in macro name, they must be
+	substituted. Colon is substituted by "1", minus is substituted by
+	underscore ("_") and space is substituted by "2".
+    </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
+	"Max-Forwards", messages containing some other combination of upper and
+	lower case characters (for example: "max-forwards", "MAX-FORWARDS",
+	"mAX-fORWARDS") 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. "Max-Forwards"):
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    Get the first 4 bytes of the header field name ("Max-"),
+		    convert it to an integer and compare to "_Max__"
+		    macro. Comparison succeeded, continue with the next step.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    Get next 4 bytes of the header field name ("Forw"), convert
+		    it to an integer and compare to "_Forw_" macro. Comparison
+		    succeeded, continue with the next step.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    Get next 4 bytes of the header field name ("ards"), convert
+		    it to an integer and compare to "_ards_" 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 "MAX-forwards":
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    Get the first 4 bytes of the header field name ("MAX-"),
+		    convert it to an integer and compare to "_Max__" macro.
+		</para>
+		<para>
+		    Comparison failed, try to lookup "MAX-" converted to
+		    integer in the hash table. It was found, result is "Max-"
+		    converted to integer.
+		</para>
+		<para>
+		    Try to compare the result from the hash table to "_Max__"
+		    macro. Comparison succeeded, continue with the next step.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    Compare next 4 bytes of the header field name ("forw"),
+		    convert it to an integer and compare to "_Max__" macro.
+		</para>
+		<para>
+		    Comparison failed, try to lookup "forw" converted to
+		    integer in the hash table. It was found, result is "Forw"
+		    converted to integer.
+		</para>
+		<para>
+		    Try to compare the result from the hash table to "Forw"
+		    macro. Comparison succeeded, continue with the next step.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    Compare next 4 bytes of the header field name ("ards"),
+		    convert it to integer and compare to "ards"
+		    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>

+ 33 - 0
doc/serdev/ip_addr.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="ip_addr" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Structure <structname>ip_addr</structname></title>
+    <para>
+	The structure represents IPv4 or IPv6 address. It is defined in
+	<filename>ip_addr.h</filename>.
+	<programlisting>
+struct ip_addr{
+     unsigned int af;     /* address family: AF_INET6 or AF_INET */
+     unsigned int len;    /* address len, 16 or 4 */
+		
+     /* 64 bits aligned address */
+     union {
+         unsigned int   addr32[4];
+         unsigned short addr16[8];
+         unsigned char  addr[16];
+     }u;
+};
+	</programlisting>
+    </para>
+</section>

+ 0 - 262
doc/serdev/locking.sgml

@@ -1,262 +0,0 @@
-<!-- $Id$ -->
-<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
-<!ENTITY ser "SIP Express Router">
-<!ENTITY moddir "/usr/lib/ser/modules">
-]>
-
-<book>
-    <chapter>
-	<title>Locking Interface</title>
-	<section>
-	    <title>Why use it ?</title>
-	    <para>
-		The main reason in creating it was to have a single transparent interface to various
-		locking methods. For example right now &ser; uses the following locking methods,
-		depending on their availability on the target system.
-	    </para>
-	    <itemizedlist>
-		<listitem>
-		    <simpara><emphasis>FAST_LOCK</emphasis></simpara>
-		    <simpara>
-			Fast inline assembly locks, defined in <filename
-			moreinfo="none">fast_lock.h</filename>. They are currently available for
-			x86, sparc64, strong-arm (amv4l) and ppc (external untested contributed
-			code). In general if the assembly code exists for a given architecture and
-			the compiler knows inline assembly (for example sun cc does not) FAST_LOCK
-			is preferred. The main advantage of using FAST_LOCK is very low memory
-			overhead and extremely fast lock/unlock operations (like 20 times faster
-			then SYSV semaphores on linux & 40 times on solaris). The only thing that
-			comes close to them are pthread mutexes (which are about 3-4 times slower).
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><emphasis>PHTREAD_MUTEX</emphasis></simpara>
-		    <simpara>
-			Uses pthread_mutex_lock/unlock. They are quite fast but they work between
-			processes only on some systems (they do not work on linux).
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><emphasis>POSIX_SEM</emphasis></simpara>
-		    <simpara>
-			Uses posix semaphores (<function
-			moreinfo="none">sem_wait</function>/<function
-			moreinfo="none">sem_post</function>). They are slower then the previous
-			methods but still way faster then SYSV semaphores. Unfortunately they also
-			do not work on all the systems (e.g. linux).
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><emphasis>SYSV_SEM</emphasis></simpara>
-		    <simpara>
-			This is the most portable but also the slowest locking method. Another
-			problem is that the number of semaphores that can be allocated by a process
-			is limited. One also has to free them before exiting.
-		    </simpara>
-		</listitem>
-	    </itemizedlist>
-	</section>
-	<section>
-	    <title>How to use it ?</title>
-	    <simpara>
-		First of all you have to include <filename
-		moreinfo="none">locking.h</filename>. Then when compiling the code one or all of
-		FAST_LOCK, USE_PTHREAD_MUTEX, USE_PTHREAD_SEM or USE_SYSV_SEM must be defined (the
-		ser <filename moreinfo="none">Makefile.defs</filename> takes care of this, you
-		should need to change it only for new architectures or compilers). <filename
-		moreinfo="none">locking.h</filename> defines 2 new types:
-		<structname>gen_lock_t</structname> and <structname>lock_set_t</structname>.
-	    </simpara>
-	</section>
-	<section>
-	    <title>Simple Locks</title>
-	    <simpara>
-		The simple locks are simple mutexes. The type is
-		<structname>gen_lock_t</structname>.
-	    </simpara>
-	    <warning>
-		<simpara>
-		    Do not make any assumptions on <structname>gen_lock_t</structname> base type, it
-		    does not have to be always an int.
-		</simpara>
-	    </warning>
-	    <section>
-		<title>Allocation & Initialization</title>
-		<simpara>
-		    The locks are allocated with: <function moreinfo="none">gen_lock_t*
-		    lock_alloc()</function> and initialized with <function
-		    moreinfo="none">gen_lock_t* lock_init(gen_lock_t* lock)</function>. Both
-		    functions return 0 on failure. The locks must be initialized before use. A
-		    proper alloc/init sequence looks like:
-		</simpara>
-		<programlisting format="linespecific">
-gen_lock_t* lock;
-
-lock=lock_alloc();
-if (lock==0) goto error;
-if (lock_init(lock)==0){
-   lock_dealloc(lock);
-   goto error; /* could not init lock*/
-}
-...
-</programlisting>
-		<simpara>
-		    Lock allocation can be skipped in some cases: if the lock is already in shared
-		    memory you don't need to allocate it again, you can initialize it directly, but
-		    keep in mind that the lock <emphasis>MUST</emphasis> be in shared memory.
-		</simpara>
-		<simpara>
-		    Example:
-		</simpara>
-		<programlisting format="linespecific">
-struct s {
-    int foo;
-    gen_lock_t lock;
-} bar;
-
-bar=shm_malloc(sizeof struct s); /* we allocate it in the shared memory */
-if (lock_init(&amp;bar->lock)==0){
- /* error initializing the lock */
- ...
-}
-</programlisting>
-	    </section>
-	    <section>
-		<title>Destroying & Deallocating the Locks</title>
-		<funcsynopsis>
-		    <!-- one of (FUNCPROTOTYPE FUNCSYNOPSISINFO) -->
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_destroy</function></funcdef>
-			<paramdef><parameter moreinfo="none">gen_lock_t* lock</parameter></paramdef>
-		    </funcprototype>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_dealloc</function></funcdef>
-			<paramdef><parameter moreinfo="none">gen_lock_t* lock</parameter></paramdef>
-		    </funcprototype>
-		</funcsynopsis>
-		<simpara>
-		    The <function moreinfo="none">lock_destroy</function> function must be called
-		    first. It removes the resources associated with the lock, but it does not also
-		    free the lock shared memory part. Think of sysv <command
-		    moreinfo="none">rmid</command>.  Please don't forget to call this function, or
-		    you can leave allocated resources in some cases (e.g sysv semaphores). Be
-		    careful to call it in your module destroy function if you use any global module
-		    locks.
-		</simpara>
-		<simpara>
-		    Example:
-		</simpara>
-		<programlisting format="linespecific">
-lock_destroy(lock);
-lock_dealloc(lock);
-</programlisting>
-		<simpara>
-		    Of course you don't need to call <function
-		    moreinfo="none">lock_dealloc</function> if your lock was not allocated with
-		    <function moreinfo="none">lock_alloc</function>l.
-		</simpara>
-	    </section>
-	    <section>
-		<title>Locking & Unlocking</title>
-		<funcsynopsis>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_get</function></funcdef>
-			<paramdef><parameter moreinfo="none">gen_lock_t* lock</parameter></paramdef>
-		    </funcprototype>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_release</function></funcdef>
-			<paramdef><parameter moreinfo="none">gen_lock_t* lock</parameter></paramdef>
-		    </funcprototype>
-		</funcsynopsis>
-	    </section>
-	</section>
-	<section>
-	    <title>Lock Sets</title>
-	    <simpara>
-		The lock sets are kind of sysv semaphore sets equivalent. The type is
-		<structname>lock_set_t</structname>.  Use them when you need a lot of mutexes. In
-		some cases they waste less system resources than arrays of
-		<structname>gen_lock_t</structname> (e.g. sys v semaphores).
-	    </simpara>
-	    <section>
-		<title>Allocating & Initializing</title>
-		<funcsynopsis>
-		    <funcprototype>
-			<funcdef>lock_set_t* lock_set_alloc</funcdef>
-			<paramdef><parameter moreinfo="none">int no</parameter></paramdef>
-		    </funcprototype>
-		    <funcprototype>
-			<funcdef>lock_set_t* lock_set_init</funcdef>
-			<paramdef><parameter moreinfo="none">lock_set_t* set</parameter></paramdef>
-		    </funcprototype>
-		</funcsynopsis>
-		<simpara>
-		    Both functions return 0 on failure.
-		</simpara>
-		<warning>
-		    <simpara>
-			Expect the allocation function to fail for large numbers. It depends on the
-			locking method used & the system available resources (again the sysv
-			semaphores example).
-		    </simpara>
-		</warning>
-		<simpara>
-		    Example:
-		</simpara>
-		<programlisting format="linespecific">
-lock_set_t *lock_set;
-
-lock_set=lock_set_alloc(100);
-if (lock_set==0) goto error;
-if (lock_set_init(lock_set)==0){
-   lock_set_dealloc(lock_set);
-   goto error;
-}
-</programlisting>
-	    </section>
-	    <section>
-		<title>Destroying & Deallocating</title>
-		<funcsynopsis>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_set_destroy</function></funcdef>
-			<paramdef><parameter moreinfo="none">lock_set_t* s</parameter></paramdef>
-		    </funcprototype>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_set_dealloc</function></funcdef>
-			<paramdef><parameter moreinfo="none">lock_set_t* s</parameter></paramdef>
-		    </funcprototype>
-		</funcsynopsis>
-		<simpara>
-		    Again don't forget to "destroy" the locks.
-		</simpara>
-	    </section>
-	    <section>
-		<title>Locking & Unlocking</title>
-		<funcsynopsis>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_set_get</function></funcdef>
-			<paramdef>
-			    <parameter moreinfo="none">lock_set_t* s</parameter>
-			    <parameter moreinfo="none">int i</parameter>
-			</paramdef>
-		    </funcprototype>
-		    <funcprototype>
-			<funcdef>void <function moreinfo="none">lock_set_release</function></funcdef>
-			<paramdef>
-			    <parameter moreinfo="none">lock_set_t* s</parameter>
-			    <parameter moreinfo="none">int i</parameter>
-			</paramdef>
-		    </funcprototype>
-		</funcsynopsis>
-		<simpara>
-		    Example:
-		</simpara>
-		<programlisting format="linespecific">
-lock_set_get(lock_set, 2);
-/* do something */
-lock_set_release(lock_set, 2);
-</programlisting>
-	    </section>
-	</section>
-    </chapter>
-</book>

+ 289 - 0
doc/serdev/locking.xml

@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="locking" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Locking Interface</title>
+
+    <section id="why">
+	<title>Why use it ?</title>
+	<para>
+	    The main reason in creating it was to have a single transparent
+	    interface to various locking methods. For example right now SER
+	    uses the following locking methods, depending on their availability
+	    on the target system.
+	</para>
+	<itemizedlist>
+	    <listitem>
+		<simpara><emphasis>FAST_LOCK</emphasis></simpara>
+		<simpara>
+		    Fast inline assembly locks, defined in
+		    <filename>fast_lock.h</filename>. They are currently
+		    available for x86, sparc64, strong-arm (amv4l) and ppc
+		    (external untested contributed code). In general if the
+		    assembly code exists for a given architecture and the
+		    compiler knows inline assembly (for example sun cc does
+		    not) FAST_LOCK is preferred. The main advantage of using
+		    FAST_LOCK is very low memory overhead and extremely fast
+		    lock/unlock operations (like 20 times faster then SYSV
+		    semaphores on linux &amp; 40 times on solaris). The only thing
+		    that comes close to them are pthread mutexes (which are
+		    about 3-4 times slower).
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><emphasis>PHTREAD_MUTEX</emphasis></simpara>
+		<simpara>
+		    Uses pthread_mutex_lock/unlock. They are quite fast but
+		    they work between processes only on some systems (they do
+		    not work on linux).
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><emphasis>POSIX_SEM</emphasis></simpara>
+		<simpara>
+		    Uses posix semaphores
+		    (<function>sem_wait</function>/<function>sem_post</function>). They
+		    are slower then the previous methods but still way faster
+		    then SYSV semaphores. Unfortunately they also do not work
+		    on all the systems (e.g. linux).
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><emphasis>SYSV_SEM</emphasis></simpara>
+		<simpara>
+		    This is the most portable but also the slowest locking
+		    method. Another problem is that the number of semaphores
+		    that can be allocated by a process is limited. One also has
+		    to free them before exiting.
+		</simpara>
+	    </listitem>
+	</itemizedlist>
+    </section>
+
+    <section id="how">
+	<title>How to use it ?</title>
+	<simpara>
+	    First of all you have to include
+	    <filename>locking.h</filename>. Then when compiling the code one or
+	    all of FAST_LOCK, USE_PTHREAD_MUTEX, USE_PTHREAD_SEM or
+	    USE_SYSV_SEM must be defined (the ser
+	    <filename>Makefile.defs</filename> takes care of this, you should
+	    need to change it only for new architectures or
+	    compilers). <filename>locking.h</filename> defines 2 new types:
+	    <structname>gen_lock_t</structname> and
+	    <structname>lock_set_t</structname>.
+	</simpara>
+    </section>
+    
+    <section id="simple_locks">
+	<title>Simple Locks</title>
+	<simpara>
+	    The simple locks are simple mutexes. The type is
+	    <structname>gen_lock_t</structname>.
+	</simpara>
+	<warning>
+	    <simpara>
+		Do not make any assumptions on
+		<structname>gen_lock_t</structname> base type, it does not have
+		to be always an int.
+	    </simpara>
+	</warning>
+	
+	<section id="allocation_and_initialization">
+	    <title>Allocation And Initialization</title>
+	    <simpara>
+		The locks are allocated with: <function>gen_lock_t*
+		    lock_alloc()</function> and initialized with
+		    <function>gen_lock_t* lock_init(gen_lock_t*
+		    lock)</function>. Both functions return 0 on failure. The
+		    locks must be initialized before use. A proper alloc/init
+		    sequence looks like:
+	    </simpara>
+	    <programlisting>
+gen_lock_t* lock;
+
+lock=lock_alloc();
+if (lock==0) goto error;
+if (lock_init(lock)==0){
+   lock_dealloc(lock);
+   goto error; /* could not init lock*/
+}
+...
+	    </programlisting>
+	    <simpara>
+		Lock allocation can be skipped in some cases: if the lock is
+		already in shared memory you don't need to allocate it again,
+		you can initialize it directly, but keep in mind that the lock
+		<emphasis>MUST</emphasis> be in shared memory.
+	    </simpara>
+	    <simpara>
+		Example:
+	    </simpara>
+	    <programlisting>
+struct s {
+    int foo;
+    gen_lock_t lock;
+} bar;
+
+bar=shm_malloc(sizeof struct s); /* we allocate it in the shared memory */
+if (lock_init(&amp;bar->lock)==0){
+ /* error initializing the lock */
+ ...
+}
+	    </programlisting>
+	</section>
+	
+	<section id="destroying">
+	    <title>Destroying And Deallocating the Locks</title>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>void <function>lock_destroy</function></funcdef>
+		    <paramdef><parameter>gen_lock_t* lock</parameter></paramdef>
+		</funcprototype>
+		<funcprototype>
+		    <funcdef>void <function>lock_dealloc</function></funcdef>
+		    <paramdef><parameter>gen_lock_t* lock</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <simpara>
+		The <function>lock_destroy</function> function must be called
+		first. It removes the resources associated with the lock, but
+		it does not also free the lock shared memory part. Think of
+		sysv <command>rmid</command>.  Please don't forget to call this
+		function, or you can leave allocated resources in some cases
+		(e.g sysv semaphores). Be careful to call it in your module
+		destroy function if you use any global module locks.
+	    </simpara>
+	    <simpara>
+		Example:
+	    </simpara>
+	    <programlisting>
+lock_destroy(lock);
+lock_dealloc(lock);
+	    </programlisting>
+	    <simpara>
+		Of course you don't need to call
+		<function>lock_dealloc</function> if your lock was not
+		allocated with <function>lock_alloc</function>.
+	    </simpara>
+	</section>
+	
+	<section id="locking_unlocking">
+	    <title>Locking And Unlocking</title>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>void <function>lock_get</function></funcdef>
+		    <paramdef><parameter>gen_lock_t* lock</parameter></paramdef>
+		</funcprototype>
+		<funcprototype>
+		    <funcdef>void <function>lock_release</function></funcdef>
+		    <paramdef><parameter>gen_lock_t* lock</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	</section>
+	
+	<section id="lock_sets">
+	    <title>Lock Sets</title>
+	    <simpara>
+		The lock sets are kind of sysv semaphore sets equivalent. The
+		type is <structname>lock_set_t</structname>.  Use them when you
+		need a lot of mutexes. In some cases they waste less system
+		resources than arrays of <structname>gen_lock_t</structname>
+		(e.g. sys v semaphores).
+	    </simpara>
+
+	    <section id="sets.allocating">
+		<title>Allocating And Initializing</title>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>lock_set_t* lock_set_alloc</funcdef>
+			<paramdef><parameter>int no</parameter></paramdef>
+		    </funcprototype>
+		    <funcprototype>
+			<funcdef>lock_set_t* lock_set_init</funcdef>
+			<paramdef><parameter>lock_set_t* set</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<simpara>
+		    Both functions return 0 on failure.
+		</simpara>
+		<warning>
+		    <simpara>
+			Expect the allocation function to fail for large
+			numbers. It depends on the locking method used and the
+			system available resources (again the sysv semaphores
+			example).
+		    </simpara>
+		</warning>
+		<simpara>
+		    Example:
+		</simpara>
+		<programlisting>
+lock_set_t *lock_set;
+
+lock_set=lock_set_alloc(100);
+if (lock_set==0) goto error;
+if (lock_set_init(lock_set)==0){
+   lock_set_dealloc(lock_set);
+   goto error;
+}
+		</programlisting>
+	    </section>
+
+	    <section id="sets.destroying">
+		<title>Destroying And Deallocating</title>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>void <function>lock_set_destroy</function></funcdef>
+			<paramdef><parameter>lock_set_t* s</parameter></paramdef>
+		    </funcprototype>
+		    <funcprototype>
+			<funcdef>void <function>lock_set_dealloc</function></funcdef>
+			<paramdef><parameter>lock_set_t* s</parameter></paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<simpara>
+		    Again don't forget to "destroy" the locks.
+		</simpara>
+	    </section>
+	    
+	    <section id="sets.locking">
+		<title>Locking And Unlocking</title>
+		<funcsynopsis>
+		    <funcprototype>
+			<funcdef>void <function>lock_set_get</function></funcdef>
+			<paramdef>
+			    <parameter>lock_set_t* s</parameter>
+			    <parameter>int i</parameter>
+			</paramdef>
+		    </funcprototype>
+		    <funcprototype>
+			<funcdef>void <function>lock_set_release</function></funcdef>
+			<paramdef>
+			    <parameter>lock_set_t* s</parameter>
+			    <parameter>int i</parameter>
+			</paramdef>
+		    </funcprototype>
+		</funcsynopsis>
+		<simpara>
+		    Example:
+		</simpara>
+		<programlisting>
+lock_set_get(lock_set, 2);
+/* do something */
+lock_set_release(lock_set, 2);
+		</programlisting>
+	    </section>
+	</section>
+    </section>
+</section>

+ 25 - 0
doc/serdev/lump.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="lump" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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 in chapter SIP
+	Message Modifications.
+    </para>
+
+</section> <!-- lump -->

+ 25 - 0
doc/serdev/lump_rpl.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="lump_rpl" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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 in chapter SIP
+	Message Modifications.
+    </para>
+</section> <!-- lump-rpl -->

+ 132 - 0
doc/serdev/main_loop.xml

@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="main_loop" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Main Loop</title>
+    <para>
+	Upon startup, all children execute <function>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>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>udp_rcv_loop</function> in file
+	<filename>udp_server.c</filename>.
+    </para>
+    <para>
+	The message is received using <function>recvfrom</function>
+	function. The received data is stored in buffer and zero 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>receive_msg</function>
+	function and <function>recvfrom</function> is called again.
+    </para>
+    
+    <section id="receive_msg">
+	<title><function>receive_msg</function> Function</title>
+	<para>
+	    The function can be found in <filename>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 <structfield>buf</structfield> 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 <structfield>orig</structfield> field. The
+		    original copy will be not modified during the server
+		    operation. All changes will be made to the copy in
+		    <structfield>buf</structfield> field. The second copy of
+		    the message will be removed in the future.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    The message will be parsed (function
+		    <function>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 add its own Via - 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 immediately before
+		    the routing part of the config file will be executed.  If
+		    there are such callbacks registered, they will be executed
+		    now.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    As the next step we will determine type of the message. 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 successful) 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 chapter <link linkend="routing_engine">The
+			Routing Engine</link>.
+		</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 -->
+</section>

+ 0 - 434
doc/serdev/modiface.sgml

@@ -1,434 +0,0 @@
-<!-- $Id$ -->
-<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
-<!ENTITY ser "SIP Express Router">
-<!ENTITY moddir "/usr/lib/ser/modules">
-]>
-
-<book>
-    <chapter>
-	<title>Module Interface</title>
-	<abstract>
-	    <para>
-		&ser; features modular architecture which allows us to split &ser;'s functionality
-		across several modules. This approach gives us greater flexibility, only required
-		set of functions can be loaded upon startup which minimizes the server's memory
-		footprint. Modules can be also provided by 3rd party developers and distributed
-		separately from the main server. Most of the functionality that &ser; provides is
-		available through modules, the core itself contains only minimum set of functions
-		that is essential for proper server's behavior or that is needed by all modules.
-	    </para>
-	    <para>
-		This chapter provides detailed information on module interface of &ser;, which is
-		used to pass information on available functions and parameters from the modules to
-		the core.
-	    </para>
-	</abstract>
-	<section>
-	    <title>Shared Objects</title>
-	    <abstract>
-		<para>
-		    First it would be good to know how &ser; loads and uses modules before we
-		    describe the module interface in detail. This section gives a brief overview of
-		    &ser;'s module subsystem.
-		</para>
-	    </abstract>
-	    <para>
-		&ser; modules are compiled as <quote>shared objects</quote>. A file containing a
-		shared object has usually .so suffix. All modules (shared objects) will be stored in
-		one directory after installation. For example <abbrev>tm</abbrev> module, which
-		contains code essential for stateful processing, will be stored in file named
-		<filename moreinfo="none">tm.so</filename>. By default these files are stored in
-		<filename moreinfo="none">&moddir;</filename> directory.
-	    </para>
-	    <para>
-		You can later load the modules using <command moreinfo="none">loadmodule</command>
-		command in your configuration file. If you want to load previously mentioned
-		<filename moreinfo="none">tm.so</filename> module, you can do it using <command
-		moreinfo="none">loadmodule "&moddir;/tm.so"</command> in your configuration
-		file. This command invokes dynamic linker provided by the operating system which
-		opens <filename moreinfo="none">tm.so</filename> file, loads it into memory and
-		resolves all symbol dependencies (a module might require symbols from the core, for
-		example functions and variables).
-	    </para>
-	    <para>
-		As the last step of the module loading the core tries to find variable named
-		<varname>exports</varname>, which describes all functions and parameters provided by
-		the module. These functions and parameters are later available to the server and can
-		be used either in the configuration file or by other modules.
-	    </para>
-	</section>
-	<section>
-	    <title>Exporting Functions</title>
-	    <abstract>
-		<para>
-		    Each module can provide zero or more functions, which can be used in the
-		    configuration file or by other modules internally. This section gives a detailed
-		    description of structure describing exported functions and passing this
-		    information to the core through the module interface.
-		</para>
-	    </abstract>
-	    <para>
-		Each function exported by a module must be described by
-		<structname>cmd_export_t</structname> structure. Structures describing all exported
-		functions are arranged into an array and pointer to the array is then passed to the
-		core. The last element of the array must contain 0 in all it's fields, this element
-		serves as the mark telling the core that this is the very last element and it must
-		stop scanning the array.
-	    </para>
-	    <para>
-		Each exported function is described by the following structure:
-	    </para>
-	    <programlisting format="linespecific">
-struct cmd_export_ {
-	char* name;             /* null terminated command name */
-	cmd_function function;  /* pointer to the corresponding function */
-	int param_no;           /* number of parameters used by the function */
-	fixup_function fixup;   /* pointer to the function called to "fix" the parameters */
-	int flags;              /* Function flags */
-};	   
-
-typedef struct cmd_export_ cmd_export_t;
-</programlisting>
-	    <itemizedlist>
-		<title>Meaning of the fileds:</title>
-		<listitem>
-		    <simpara><varname>char* name</varname><simpara> 
-		    <simpara>
-			This is the name under which the function will be visible to the
-			core. Usually it is the same as the name of the corresponding function.
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>cmd_function function</varname></simpara> 
-		    <para>cmd_function type is defined as follows: </para>
-		    <programlisting format="linespecific">
-typedef int (*cmd_function)(struct sip_msg*, char*, char*); 
-</programlisting>
-		    <simpara>
-			The first parameter is a <acronym>SIP</acronym> message being processed, the
-			other 2 parameters are given from the configuration file.
-		    </simpara>
-		    <note>
-			<simpara>
-			    From time to time you might need to export a function that has different
-			    synopsis. This can happen if you export functions that are supposed to
-			    be called by other modules only and must not be called from the
-			    configuration script. In this case you will have to do type-casting
-			    otherwise the compiler will complain and will not compile your module.
-			</simpara>
-			<simpara>
-			    Simply put (cmd_function) just before the function name, for example
-			    <function moreinfo="none">(cmd_function)my_function</function>.  Don't
-			    use this unless you know what are you doing ! The server might crash if
-			    you pass wrong parameters to the function later !
-			</simpara>
-		    </note>
-		</listitem>
-		<listitem>
-		    <simpara><varname>int param_no</varname></simpara>
-		    <simpara>
-			Number of parameters of the function. It can be 0, 1 or 2. The function will
-			be not visible from the configuration script if you use another value.
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>fixup_function fixup</varname></simpara>
-		    <simpara>
-			This is the function that will be used to <quote>fixup</quote> function
-			parameters. Set this field to 0 if you don't need this.
-		    </simpara>
-		    <simpara>
-			If you provide pointer to a fixup function in this field, the fixup function
-			will be called for each occurrence of the exported function in the
-			configuration script.
-		    </simpara>
-		    <simpara>
-			The fixup function can be used to perform some operation on the function
-			parameters. For example, if one of the parameters is a regular expression,
-			you can use the fixup to compile the regular expression. The fixup functions
-			are called only once - upon the server startup and so the regular expression
-			will be compiled before the server starts processing messages. When the
-			server calls the exported function to process a <acronym>SIP</acronym>
-			message, the function will be given the already compiled regular expression
-			and doesn't have to compile it again. This is a significant performance
-			improvement.
-		    </simpara>
-		    <simpara>
-			Fixup functions can also be used to convert string to integer. As you have
-			might noticed, the exported functions accept up to 2 parameters of type
-			char*. Because of that it is not possible to pass integer parameters from
-			the script files directly. If you want to pass an integer as a parameter,
-			you must pass it as string (i.e. enclosed in quotes).
-		    </simpara>
-		    <simpara>
-			Fixup function can be used to convert the string back to integer. Such a
-			conversion should happend only once because the string parameter doesn't
-			change when the server is running. Fixup is therefore ideal place for the
-			conversion, it will be converted upon the server startup before the server
-			starts processing <acronym>SIP</acronym> messages. After the conversion the
-			function will get directly the converted value. See existing modules for
-			example of such a fixup function.
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>int flags</varname></simpara>
-		    <simpara>
-			Usage of each function can be restricted. You may want to write a function
-			that can be used by other modules but cannot be called from the script. If
-			you write a function that is supposed to process <acronym>SIP</acronym>
-			requests only, you may want to restrict it so it will be never called for
-			<acronym>SIP</acronym> replies and vice versa. That's what is flags field
-			for.
-		    </simpara>
-		    <simpara>
-			This field is OR value of different flags. Currently only REQUEST_ROUTE and
-			REPLY_ROUTE flags are defined and used by the core. If you use REQUEST_ROUTE
-			flag, then the function can be called from the main route block. If you use
-			REPLY_ROUTE flag, then the function can be called from reply route blocks
-			(More on this in the SER User's Guide). If this field is set to 0, then the
-			function can be called internally (i.e. from other modules) only. If you
-			want to make your function callable anywhere in the script, you can use
-			REQUEST_ROUTE | REPLY_ROUTE.
-		    </simpara>
-		</listitem>
-	    </itemizedlist>
-	</section>
-	<section>
-	    <title>Exporting Parameters</title>
-	    <abstract>
-		<simpara>
-		    Each module can provide zero or more parameters, which can affect the module's
-		    behavior. This section gives a detailed description of structures describing
-		    exported parameters and passing this information to the core through the module
-		    interface.
-		</simpara>
-	    </abstract>
-	    <simpara>
-		Each parameter exported by a module must be described by
-		<structname>param_export_t</structname> structure. Structures describing all
-		exported parameters are arranged into an array and pointer to the array is then
-		passed to the core. The last element of the array must contain 0 in all it's fields,
-		this element serves as the mark telling the core that this is the very last element
-		and it must stop scanning the array (This is same as in array of exported
-		functions).
-	    </simpara>
-	    <simpara>
-		Each exported parameter is described by the following structure:
-	    </simpara>
-	    <programlisting format="linespecific">
-		
-struct param_export_ {
-	char* name;             /* null terminated param. name */
-	modparam_t type;        /* param. type */
-	void* param_pointer;    /* pointer to the param. memory location */
-};
-
-typedef struct param_export_ param_export_t;
-</programlisting>
-	    <itemizedlist>
-		<title>Meaning of the fields:</title>
-		<listitem>
-		    <simpara><varname>char* name</varname></simpara>
-		    <simpara>
-			This is null-terminated name of the parameters as it will be used in the
-			scripts. Usually this is the same as the name of the variable holding the
-			value.
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>modparam_t type</varname></simpara>
-		    <simpara>
-			Type of the parameter. Currently only two types are defined. INT_PARAM for
-			integer parameters (corresponding variable must be of type int) and
-			STR_PARAM for string parameters (corresponding variable must be of type
-			char*).
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>void* param_pointer</varname></simpara>
-		    <simpara>
-			Pointer to the corresponding variable (stored as void* pointer, make sure
-			that the variable has appropriate type depending on the type of the
-			parameter !).
-		    </simpara>
-		</listitem>
-	    </itemizedlist>
-	</section>
-	<section>
-	    <title>Module Initialization</title>
-	    <simpara>
-		If you need to initialize your module before the server starts processing
-		<acronym>SIP</acronym> messages, you should provide initialization function. Each
-		module can provide two initialization functions, main initialization function and
-		child-specific initialization function.  Fields holding pointers to both
-		initialization functions are in main export structure (will be described
-		later). Simply pass 0 instead of function pointer if you don't need one or both
-		initialization functions.
-	    </simpara>
-	    <simpara>
-		The main initialization function will be called before any other function exported
-		by the module. The function will be called only once, before the main process
-		forks. This function is good for initialization that is common for all the children
-		(processes). The function should return 0 if everything went OK and a negative error
-		code otherwise. Server will abort if the function returns a negative value.
-	    </simpara>
-	    <simpara>
-		Per-child initialization function will be called <emphasis>after</emphasis> the main
-		process forks. The function will be called for each child separately. The function
-		should perform initialization that is specific for each child. For example each
-		child process might open it's own database connection to avoid locking of a single
-		connection shared by many processes. Such connections can be opened in the per-child
-		initialization function. The function accepts one parameter which is rank (integer)
-		of child for which the function is being executed. This allows developers to
-		distinguish different children and perform different initialization for each
-		child. The meaning of return value is same as in the main initialization function.
-	    </simpara>
-	</section>
-	<section>
-	    <title>Module Clean-up</title>
-	    <simpara>
-		A module can also export a clean-up function that will be called by the main process
-		when the server shuts down. The function accepts no parameters and return no value.
-	    </simpara>
-	</section>
-	<section>
-	    <title>Module Callbacks</title>
-	    <para>
-		TBD.
-	    </para>
-	</section>
-	<section>
-	    <title><structname>exports</structname> Structure - Assembling the Pieces Together</title>
-	    <simpara>
-		We have already described how a module can export functions and parameters, but we
-		haven't yet described how to pass this information to the core. Each module must
-		have variable named <varname>exports</varname> which is structure
-		module_exports. The variable will be looked up by the core immediately after it
-		loads the module. The structure contains pointers to both arrays (functions,
-		parameters), pointers to both initialization functions, destroy function and the
-		callbacks. So the structure contains everything the core will need.
-	    </simpara>
-	    <simpara>The structure looks like the follows:</simpara>
-	    <programlisting format="linespecific">
-struct module_exports{
-    char* name;                     /* null terminated module name */
-    cmd_export_t* cmds;             /* null terminated array of the exported commands */
-    param_export_t* params;         /* null terminated array of the exported module parameters */
-    init_function init_f;           /* Initialization 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>
-	    <itemizedlist>
-		<title>Field description:</title>
-		<listitem>
-		    <simpara><varname>char* name</varname></simpara>
-		    <simpara>Null terminated name of the module</simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>cmd_exports* cmds</varname></simpara>
-		    <simpara>
-			Pointer to the array of exported functions
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>param_export_t* params</varname></simpara>
-		    <simpara>
-			Pointer to the array of exported parameters
-		    </simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>init_function init_f</varname></simpara>
-		    <simpara>Pointer to the module initialization function</simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>response_function response_f</varname></simpara>
-		    <simpara>Pointer to function processing responses</simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>destroy_function destroy_f</varname></simpara>
-		    <simpara>Pointer to the module clean-up function</simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>onbreak_function onbreak_f</varname></simpara>
-		    <simpara>TBD</simpara>
-		</listitem>
-		<listitem>
-		    <simpara><varname>child_init_function init_child_f</varname></simpara>
-		    <simpara>Pointer to the per-child initialization function</simpara>
-		</listitem>
-	    </itemizedlist>
-	</section>
-	<section>
-	    <title>Example - Simple Module Interface</title>
-	    <para>
-		Let's suppose that we are going to write a simple module. The module will export two functions - 
-		<function moreinfo="none">foo_req</function> which will be processing <acronym>SIP</acronym> requests and 
-		<function moreinfo="none">foo_int</function> which is an internal function that can be called by other modules only.
-		Both functions will take 2 parameters.
-	    </para>
-	    <programlisting format="linespecific">
-/* Prototypes */
-int foo_req(struct sip_msg* msg, char* param1, char* param2);
-int foo_res(struct sip_msg* msg, char* param1, char* param2);
-
-static cmd_export cmds[] = {
-    {"foo_req", foo_req, 2, 0, ROUTE_REQUEST},
-    {"foo_int", foo_int, 2, 0, 0            },
-    {0, 0, 0, 0}
-};
-</programlisting>
-	    <para>
-		The module will also have two parameters, foo_bar of type integer and bar_foo of type string.
-	    </para>
-	    <programlisting format="linespecific">
-int foo_bar = 0;
-char* bar_foo = "default value";
-
-static param_export params[] = {
-    {"foo_bar", INT_PARAM, &amp;foo_bar},
-    {"bar_foo", STR_PARAM, bar_foo     },
-    {0, 0, 0}
-}; 
-</programlisting>
-	    <para>
-		We will also create both initialization functions and a clean-up function:
-	    </para>
-	    <programlisting format="linespecific">
-static int mod_init(void)
-{
-    printf("foo module initializing\n");
-}
-
-static int child_init(int rank)
-{
-    printf("child nr. %d initializing\n", rank);
-    return 0;
-}
-
-static void destroy(void)
-{
-    printf("foo module cleaning up\n");
-}
-</programlisting>
-	    <para>
-		And finally we put everything into the exports structure:
-	    </para>
-	    <programlisting format="linespecific">
-struct module_exports exports = {
-    "foobar",   /* Module name */
-    cmds,       /* Exported functions */
-    params,     /* Exported parameters */
-    mod_init,   /* Module initialization function */
-    0,          /* Response function */
-    destroy,    /* Clean-up function */
-    0,          /* On Cancel function */
-    child_init  /* Per-child init function */
-};
-</programlisting>
-	    <simpara>And that's it.</simpara>
-	</section>
-    </chapter>
-</book>

+ 800 - 0
doc/serdev/modiface.xml

@@ -0,0 +1,800 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="module_interface" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+	<abstract>
+	<para>
+	    SER features modular architecture which allows us to split SER's
+	    functionality across several modules. This approach gives us
+	    greater flexibility, only required set of functions can be loaded
+	    upon startup which minimizes the server's memory footprint. Modules
+	    can be also provided by 3rd party developers and distributed
+	    separately from the main server. Most of the functionality that SER
+	    provides is available through modules, the core itself contains
+	    only minimum set of functions that is essential for proper server's
+	    behavior or that is needed by all modules.
+	</para>
+	<para>
+	    This chapter provides detailed information on module interface of
+	    SER, which is used to pass information on available functions and
+	    parameters from the modules to the core.
+	</para>
+
+	</abstract>
+    </sectioninfo>
+
+    <title>Module Interface</title>
+
+    <section id="shared_objects">
+	<title>Shared Objects</title>
+	<abstract>
+	    <para>
+		First it would be good to know how SER loads and uses modules
+		before we describe the module interface in detail. This section
+		gives a brief overview of SER's module subsystem.
+	    </para>
+	</abstract>
+	<para>
+	    SER modules are compiled as "shared objects". A file containing a
+	    shared object has usually .so suffix. All modules (shared objects)
+	    will be stored in one directory after installation. For example tm
+	    module, which contains code essential for stateful processing, will
+	    be stored in file named <filename>tm.so</filename>. By default
+	    these files are stored in
+	    <filename>/usr/local/lib/ser/modules</filename> directory.
+	</para>
+	<para>
+	    You can later load the modules using <command>loadmodule</command>
+	    command in your configuration file. If you want to load previously
+	    mentioned <filename>tm.so</filename> module, you can do it using
+	    <command>loadmodule "/usr/local/lib/ser/modules/tm.so"</command> in
+	    your configuration file. This command invokes dynamic linker
+	    provided by the operating system which opens
+	    <filename>tm.so</filename> file, loads it into memory and resolves
+	    all symbol dependencies (a module might require symbols from the
+	    core, for example functions and variables).
+	</para>
+	<para>
+	    As the last step of the module loading the core tries to find
+	    variable named <varname>exports</varname>, which describes all
+	    functions and parameters provided by the module. These functions
+	    and parameters are later available to the server and can be used
+	    either in the configuration file or by other modules.
+	</para>
+    </section>
+    
+    <section id="exporting_functions">
+	<title>Exporting Functions</title>
+	<abstract>
+	    <para>
+		Each module can provide zero or more functions, which can be
+		used in the configuration file or by other modules
+		internally. This section gives a detailed description of
+		structure describing exported functions and passing this
+		information to the core through the module interface.
+	    </para>
+	</abstract>
+	<para>
+	    Each function exported by a module must be described by
+	    <structname>cmd_export_t</structname> structure. Structures
+	    describing all exported functions are arranged into an array and
+	    pointer to the array is then passed to the core. The last element
+	    of the array must contain 0 in all it's fields, this element serves
+	    as the mark telling the core that this is the very last element and
+	    it must stop scanning the array.
+	</para>
+	<para>
+	    Each exported function is described by the following structure:
+	</para>
+	<programlisting>
+struct cmd_export_ {
+	char* name;             /* null terminated command name */
+	cmd_function function;  /* pointer to the corresponding function */
+	int param_no;           /* number of parameters used by the function */
+	fixup_function fixup;   /* pointer to the function called to "fix" the parameters */
+	int flags;              /* Function flags */
+};	   
+
+typedef struct cmd_export_ cmd_export_t;
+	</programlisting>
+	
+	<itemizedlist>
+	    <title>Meaning of the fileds:</title>
+	    <listitem>
+		<simpara><varname>char* name</varname></simpara> 
+		<simpara>
+		    This is the name under which the function will be visible
+		    to the core. Usually it is the same as the name of the
+		    corresponding function.
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>cmd_function function</varname></simpara>
+		<para>cmd_function type is defined as follows: </para>
+		<programlisting>
+typedef int (*cmd_function)(struct sip_msg*, char*, char*); 
+		</programlisting>
+		<simpara>
+		    The first parameter is a SIP message
+		    being processed, the other 2 parameters are given from the
+		    configuration file.
+		</simpara>
+		<note>
+		    <simpara>
+			From time to time you might need to export a function
+			that has different synopsis. This can happen if you
+			export functions that are supposed to be called by
+			other modules only and must not be called from the
+			configuration script. In this case you will have to do
+			type-casting otherwise the compiler will complain and
+			will not compile your module.
+		    </simpara>
+		    <simpara>
+			Simply put (cmd_function) just before the function
+			name, for example
+			<function>(cmd_function)my_function</function>.  Don't
+			use this unless you know what are you doing ! The
+			server might crash if you pass wrong parameters to the
+			function later !
+		    </simpara>
+		</note>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>int param_no</varname></simpara>
+		<simpara>
+		    Number of parameters of the function. It can be 0, 1 or
+		    2. The function will be not visible from the configuration
+		    script if you use another value.
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>fixup_function fixup</varname></simpara>
+		<simpara>
+		    This is the function that will be used to "fixup" function
+		    parameters. Set this field to 0 if you don't need this.
+		</simpara>
+		<simpara>
+		    If you provide pointer to a fixup function in this field,
+		    the fixup function will be called for each occurrence of
+		    the exported function in the configuration script.
+		</simpara>
+		<simpara>
+		    The fixup function can be used to perform some operation on
+		    the function parameters. For example, if one of the
+		    parameters is a regular expression, you can use the fixup
+		    to compile the regular expression. The fixup functions are
+		    called only once - upon the server startup and so the
+		    regular expression will be compiled before the server
+		    starts processing messages. When the server calls the
+		    exported function to process a SIP message, the function
+		    will be given the already compiled regular expression and
+		    doesn't have to compile it again. This is a significant
+		    performance improvement.
+		</simpara>
+		<simpara>
+		    Fixup functions can also be used to convert string to
+		    integer. As you have might noticed, the exported functions
+		    accept up to 2 parameters of type char*. Because of that it
+		    is not possible to pass integer parameters from the script
+		    files directly. If you want to pass an integer as a
+		    parameter, you must pass it as string (i.e. enclosed in
+		    quotes).
+		</simpara>
+		<simpara>
+		    Fixup function can be used to convert the string back to
+		    integer. Such a conversion should happend only once because
+		    the string parameter doesn't change when the server is
+		    running. Fixup is therefore ideal place for the conversion,
+		    it will be converted upon the server startup before the
+		    server starts processing SIP messages. After the conversion
+		    the function will get directly the converted value. See
+		    existing modules for example of such a fixup function.
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>int flags</varname></simpara>
+		<simpara>
+		    Usage of each function can be restricted. You may want to
+		    write a function that can be used by other modules but
+		    cannot be called from the script. If you write a function
+		    that is supposed to process SIP requests only, you may want
+		    to restrict it so it will be never called for SIP replies
+		    and vice versa. That's what is flags field for.
+		</simpara>
+		<simpara>
+		    This field is OR value of different flags. Currently only
+		    REQUEST_ROUTE and REPLY_ROUTE flags are defined and used by
+		    the core. If you use REQUEST_ROUTE flag, then the function
+		    can be called from the main route block. If you use
+		    REPLY_ROUTE flag, then the function can be called from
+		    reply route blocks (More on this in the SER User's
+		    Guide). If this field is set to 0, then the function can be
+		    called internally (i.e. from other modules) only. If you
+		    want to make your function callable anywhere in the script,
+		    you can use REQUEST_ROUTE | REPLY_ROUTE.
+		</simpara>
+	    </listitem>
+	</itemizedlist>
+    </section>
+
+    <section id="exporting_parameters">
+	<title>Exporting Parameters</title>
+	<abstract>
+	    <simpara>
+		Each module can provide zero or more parameters, which can
+		affect the module's behavior. This section gives a detailed
+		description of structures describing exported parameters and
+		passing this information to the core through the module
+		interface.
+	    </simpara>
+	</abstract>
+	<simpara>
+	    Each parameter exported by a module must be described by
+	    <structname>param_export_t</structname> structure. Structures
+	    describing all exported parameters are arranged into an array and
+	    pointer to the array is then passed to the core. The last element
+	    of the array must contain 0 in all it's fields, this element serves
+	    as the mark telling the core that this is the very last element and
+	    it must stop scanning the array (This is same as in array of
+	    exported functions).
+	</simpara>
+	<simpara>
+	    Each exported parameter is described by the following structure:
+	</simpara>
+	<programlisting>
+struct param_export_ {
+	char* name;             /* null terminated param. name */
+	modparam_t type;        /* param. type */
+	void* param_pointer;    /* pointer to the param. memory location */
+};
+
+typedef struct param_export_ param_export_t;
+	</programlisting>
+	<itemizedlist>
+	    <title>Meaning of the fields:</title>
+	    <listitem>
+		<simpara><varname>char* name</varname></simpara>
+		<simpara>
+		    This is null-terminated name of the parameters as it will
+		    be used in the scripts. Usually this is the same as the
+		    name of the variable holding the value.
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>modparam_t type</varname></simpara>
+		<simpara>
+		    Type of the parameter. Currently only two types are
+		    defined. INT_PARAM for integer parameters (corresponding
+		    variable must be of type int) and STR_PARAM for string
+		    parameters (corresponding variable must be of type char*).
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>void* param_pointer</varname></simpara>
+		<simpara>
+		    Pointer to the corresponding variable (stored as void*
+		    pointer, make sure that the variable has appropriate type
+		    depending on the type of the parameter !).
+		</simpara>
+	    </listitem>
+	</itemizedlist>
+    </section>
+
+    <section id="module_initialization">
+	<title>Module Initialization</title>
+	<simpara>
+	    If you need to initialize your module before the server starts
+	    processing SIP messages, you should provide
+	    initialization function. Each module can provide two initialization
+	    functions, main initialization function and child-specific
+	    initialization function.  Fields holding pointers to both
+	    initialization functions are in main export structure (will be
+	    described later). Simply pass 0 instead of function pointer if you
+	    don't need one or both initialization functions.
+	</simpara>
+	<simpara>
+	    The main initialization function will be called before any other
+	    function exported by the module. The function will be called only
+	    once, before the main process forks. This function is good for
+	    initialization that is common for all the children (processes). The
+	    function should return 0 if everything went OK and a negative error
+	    code otherwise. Server will abort if the function returns a
+	    negative value.
+	</simpara>
+	<simpara>
+	    Per-child initialization function will be called
+	    <emphasis>after</emphasis> the main process forks. The function
+	    will be called for each child separately. The function should
+	    perform initialization that is specific for each child. For example
+	    each child process might open it's own database connection to avoid
+	    locking of a single connection shared by many processes. Such
+	    connections can be opened in the per-child initialization
+	    function. The function accepts one parameter which is rank
+	    (integer) of child for which the function is being executed. This
+	    allows developers to distinguish different children and perform
+	    different initialization for each child. The meaning of return
+	    value is same as in the main initialization function.
+	</simpara>
+    </section>
+
+    <section id="module_cleanup">
+	<title>Module Clean-up</title>
+	<simpara>
+	    A module can also export a clean-up function that will be called by
+	    the main process when the server shuts down. The function accepts
+	    no parameters and return no value.
+	</simpara>
+    </section>
+
+    <section id="module_callbacks">
+	<title>Module Callbacks</title>
+	<para>
+	    TBD.
+	</para>
+    </section>
+
+    <section id="exports_structure">
+	<title><structname>exports</structname> Structure - Assembling the Pieces Together</title>
+	<simpara>
+	    We have already described how a module can export functions and
+	    parameters, but we haven't yet described how to pass this
+	    information to the core. Each module must have variable named
+	    <varname>exports</varname> which is structure module_exports. The
+	    variable will be looked up by the core immediately after it loads
+	    the module. The structure contains pointers to both arrays
+	    (functions, parameters), pointers to both initialization functions,
+	    destroy function and the callbacks. So the structure contains
+	    everything the core will need.
+	</simpara>
+	<simpara>The structure looks like the follows:</simpara>
+	<programlisting>
+struct module_exports{
+    char* name;                     /* null terminated module name */
+    cmd_export_t* cmds;             /* null terminated array of the exported commands */
+    param_export_t* params;         /* null terminated array of the exported module parameters */
+    init_function init_f;           /* Initialization 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>
+	<itemizedlist>
+	    <title>Field description:</title>
+	    <listitem>
+		<simpara><varname>char* name</varname></simpara>
+		<simpara>Null terminated name of the module</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>cmd_exports* cmds</varname></simpara>
+		<simpara>
+		    Pointer to the array of exported functions
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>param_export_t* params</varname></simpara>
+		<simpara>
+		    Pointer to the array of exported parameters
+		</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>init_function init_f</varname></simpara>
+		<simpara>Pointer to the module initialization function</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>response_function response_f</varname></simpara>
+		<simpara>Pointer to function processing responses</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>destroy_function destroy_f</varname></simpara>
+		<simpara>Pointer to the module clean-up function</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>onbreak_function onbreak_f</varname></simpara>
+		<simpara>TBD</simpara>
+	    </listitem>
+	    <listitem>
+		<simpara><varname>child_init_function init_child_f</varname></simpara>
+		<simpara>Pointer to the per-child initialization function</simpara>
+	    </listitem>
+	</itemizedlist>
+    </section>
+
+    <section id="simple_interface">
+	    <title>Example - Simple Module Interface</title>
+	<para>
+	    Let's suppose that we are going to write a simple module. The
+	    module will export two functions - <function>foo_req</function>
+	    which will be processing <acronym>SIP</acronym> requests and
+	    <function>foo_int</function> which is an internal function that can
+	    be called by other modules only.  Both functions will take 2
+	    parameters.
+	</para>
+	<programlisting>
+/* Prototypes */
+int foo_req(struct sip_msg* msg, char* param1, char* param2);
+int foo_res(struct sip_msg* msg, char* param1, char* param2);
+
+static cmd_export cmds[] = {
+    {"foo_req", foo_req, 2, 0, ROUTE_REQUEST},
+    {"foo_int", foo_int, 2, 0, 0            },
+    {0, 0, 0, 0}
+};
+	</programlisting>
+	<para>
+	    The module will also have two parameters, foo_bar of type integer
+	    and bar_foo of type string.
+	</para>
+	<programlisting>
+int foo_bar = 0;
+char* bar_foo = "default value";
+
+static param_export params[] = {
+    {"foo_bar", INT_PARAM, &amp;foo_bar},
+    {"bar_foo", STR_PARAM, bar_foo     },
+    {0, 0, 0}
+}; 
+	</programlisting>
+	<para>
+	    We will also create both initialization functions and a clean-up function:
+	</para>
+	<programlisting>
+static int mod_init(void)
+{
+    printf("foo module initializing\n");
+}
+
+static int child_init(int rank)
+{
+    printf("child nr. %d initializing\n", rank);
+    return 0;
+}
+
+static void destroy(void)
+{
+    printf("foo module cleaning up\n");
+}
+	</programlisting>
+	<para>
+	    And finally we put everything into the exports structure:
+	</para>
+	<programlisting>
+struct module_exports exports = {
+    "foobar",   /* Module name */
+    cmds,       /* Exported functions */
+    params,     /* Exported parameters */
+    mod_init,   /* Module initialization function */
+    0,          /* Response function */
+    destroy,    /* Clean-up function */
+    0,          /* On Cancel function */
+    child_init  /* Per-child init function */
+};
+	</programlisting>
+	<simpara>And that's it.</simpara>
+    </section>
+
+    <section id="module_interface_internals">
+	<title>Module Interface Internals</title>
+	<para>
+	    All the data structures and functions mentioned in this section can
+	    be found in files <filename>sr_module.h</filename> and
+	    <function>sr_module.c</function>.
+	</para>
+
+	<xi:include href="sr_module.xml"/>
+	<xi:include href="module_exports.xml"/>
+
+	<section id="module-loading">
+	    <title>Module Loading</title>
+	    <para>
+		Modules are compiled and stored as shared objects. Shared
+		objects have usually appendix ".so".  Shared objects can be
+		loaded at runtime.
+	    </para>
+	    <para>
+		When you instruct the server to load a module using
+		<function>loadmodule</function> command in the config file, it
+		will call function <function>load_module</function>. The
+		function will do the following:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    It will try to open specified file using
+			    <function>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
+			    "/usr/lib/ser/modules/auth.so" using
+			    <function>dlopen</function> function.
+			</para>
+			<para>
+			    If <function>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 "exports"
+			    symbol using <function>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>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>register_module</function> registers a
+		module with the server core. By registration we mean the
+		following set of steps (see function
+		<function>register_module</function> in file
+		<filename>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 returned by
+			    <function>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>dlsym</function> in
+			    <function>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_configuration">
+	    <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">
+		<title>Function <function>modparam</function></title>
+		<para>
+		    <function>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>modparam</function>
+				function is enclosed in quotes, it is string
+				parameter 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 -->
+	    
+	    <section id="set_mod_param">
+		<title>Function <function>set_mod_param</function></title>
+		<para>
+		    When the server finds <function>modparam</function>
+		    function in the config file, it will call
+		    <function>set_mod_param</function> function. The function
+		    can be found in <filename>modparam.c</filename> file. The
+		    function will do the following:
+		</para>
+		
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    It tries to find corresponding variable using
+			    <function>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>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 -->
+
+	    <section id="find_param_export">
+		<title>Function <function>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 finds
+		    module with given name.  Then it will search through 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 -->
+	</section> <!-- module_config -->
+	
+	<section id="lookingup_exported_function">
+	    <title>Looking Up an Exported Function</title> 
+	    <para>
+		If you need to find exported function with given name and
+		number of parameters, <function>find_export</function> function
+		is what you need. The function is defined in
+		<filename>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 through list of all loaded modules and
+		in each module through array of all exported functions until it
+		finds function with given name and number of parameters. If
+		such exported function was found,
+		<function>find_exported</function> will return pointer to the
+		function, otherwise zero will be returned.
+	    </para>
+	</section> <!-- lookingup_exported_function -->
+	
+	<section id="additional_functions">
+	    <title>Additional Functions</title>
+	    <para>
+		There are several additional functions defined in file
+		<filename>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>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>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>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>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>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>
+    </section>
+</section>

+ 316 - 0
doc/serdev/module_exports.xml

@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="module_exports" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>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>
+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;         /* Initialization 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>
+	<emphasis>Fields and their description</emphasis>:
+    </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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>cmd_function</function></funcdef>
+		    <paramdef>struct sip_msg* <parameter>msg</parameter></paramdef>
+		    <paramdef>char* <parameter>param1</parameter></paramdef>
+		    <paramdef>char* <parameter>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>param2</parameter> will be set to zero,
+		if the function accepts no parameters,
+		<parameter>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 continue. 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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>fixup_function</function></funcdef>
+		    <paramdef>void** <parameter>param</parameter></paramdef>
+		    <paramdef>int <parameter>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 fulfill 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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>response_function</function></funcdef>
+		    <paramdef>struct sip_msg* <parameter>msg</parameter></paramdef>
+		</funcprototype>
+	    </funcsynopsis>
+	    <para>
+		The function accepts one parameter which is structure
+		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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>void <function>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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>void <function>onbreak_function</function></funcdef>
+		    <paramdef>struct sip_msg* <parameter>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 initialization
+		function. This is an additional 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>
+		<emphasis>Function Prototype</emphasis>:
+	    </para>
+	    <funcsynopsis>
+		<funcprototype>
+		    <funcdef>int <function>child_init_function</function></funcdef>
+		    <paramdef>int <parameter>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>

+ 94 - 0
doc/serdev/msg_parser.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="msg_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>The SIP 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>parser</filename> subdirectory that contains all
+	the parsers and related stuff.
+    </para>
+    <para>
+	The following parsers can be found under <filename>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
+	    servers 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 (":"). For example, "Server: SIP Express Router" - in this
+	    case "Server" is header field name and "SIP Express Router" is
+	    header field body.
+	</para>
+    </section> <!-- sip-msg-structure -->
+    <section id="parser_structure">
+	<title>Parser Structure</title>
+	<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>
+	
+	<xi:include href="fline_parser.xml"/>
+	<xi:include href="hfname_parser.xml"/>
+
+	<xi:include href="to_parser.xml"/>
+	<xi:include href="from_parser.xml"/>
+	<xi:include href="cseq_parser.xml"/>
+	<xi:include href="event_parser.xml"/>
+	<xi:include href="expires_parser.xml"/>
+	<xi:include href="via_parser.xml"/>
+	<xi:include href="contact_parser.xml"/>
+	<xi:include href="digest_parser.xml"/>
+    </section> <!-- parser-organization -->
+</section>

+ 114 - 0
doc/serdev/msg_start.xml

@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="msg_start" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <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>parse_fline.h</filename>
+	under <filename>parser</filename> subdirectory.
+    </para>
+    
+    <para>
+	<emphasis>Structure Declaration</emphasis>
+	<programlisting>
+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>
+    <para>
+	<emphasis>Description of Request Related Fields:</emphasis>
+	<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 <type>str</type> 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>
+
+    <para>
+	<emphasis>Description of Response Related Fields:</emphasis>
+	<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>
+    </para>
+</section>
+

+ 467 - 0
doc/serdev/routing_engine.xml

@@ -0,0 +1,467 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="routing_engine" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <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>action.c</filename>.
+    </para>
+    <para>
+	The main function is <function>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 processed.
+    </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
+	<varname>rlist[0]</varname>. (The linked list of main route part is
+	always at index 0).
+    </para>
+    <para>
+	The function will then sequentially call <function>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 and the message will be
+	dropped.
+    </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>do_action</function> Function</title>
+	<para>
+	    <function>do_action</function> function is core of the routing
+	    engine. There is a big <function>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>drop</function>,
+	    <function>forward</function>,
+	    <function>send</function>,
+	    <function>log</function>,
+	    <function>append_branch</function>,
+	    <function>len_gt</function>,
+	    <function>setflag</function>,
+	    <function>resetflag</function>,
+	    <function>isflagset</function>,
+	    <function>error</function>,
+	    <function>route</function>,
+	    <function>exec</function>,
+	    <function>revert_uri</function>,
+	    <function>set_host</function>,
+	    <function>set_hostport</function>,
+	    <function>set_user</function>,
+	    <function>set_userpass</function>,
+	    <function>set_port</function>,
+	    <function>set_uri</function>,
+	    <function>prefix</function>,
+	    <function>strip</function>,
+	    <function>if</function>,
+	    <function>module</function>.
+	</para>
+	<para>
+	    Each of the commands is represented by a <emphasis>case</emphasis>
+	    statement in the switch.  (For example, if you are interested in
+	    implementation of <function>drop</function> command, look at
+	    "case DROP_T:" statement in the function.
+	</para>
+	<para>
+	    The respective commands will be described now.
+	</para>
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    <function>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>drop</function> will be executed.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>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>mk_proxy</function> converts hostname to
+		    corresponding <acronym>IP</acronym> address.  The message
+		    is then sent out using <function>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>forward_request</function> here to forward the
+		    message further.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>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
+		    altering.
+		</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>udp_send</function> directly.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>log</function> - The message given as a parameter
+		    will be logged using system logger. It can be either
+		    <command>syslog</command> or <varname>stderr</varname>
+		    (depends on configuration). The message is logged using
+		    <function>LOG</function> which is a macro defined in
+		    <filename>dprint.h</filename> header file.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>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 destinations and fork
+		    the request.
+		</para>
+		<para>
+		    The server keeps an array of all destinations, that should
+		    be used when forking. The array and related functions can
+		    be found in file <filename>dset.c</filename>. There is
+		    function <function>append_branch</function> which adds a
+		    new destination to the set.
+		</para>
+		<para>
+		    This command simply calls
+		    <function>append_branch</function> function and adds a new
+		    destination to the destination set.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>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 then 1 will be returned otherwise the
+		    function returns -1.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>setflag</function> - Sets a flag in the
+		    message. The command simply calls
+		    <function>setflags</function> function that will set the
+		    flag. Fore more information see file
+		    <filename>flag.c</filename>.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>resetflag</function> - Same as command
+		    <function>setflag</function> - only resetflag will be
+		    called instead of setflag.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>isflagset</function> - Test if the flag
+		    is set or not.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>error</function> - Log a message with NOTICE log
+		    level.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>route</function> - Execute another
+		    route statement.
+		</para>
+		<para>
+		    As we have mentioned already, there can be more that one
+		    route statement in the config file. One of them is main
+		    (without number), the other are additional. This command
+		    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>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 processed.
+		</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 <varname>rlist</varname>
+		    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>run_actions(rlist[a->p1.number], msg)</function>
+		    and that will execute route statement with number given as
+		    parameter.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>exec</function> - Execute a shell command.
+		</para>
+		<para>
+		    The command accepts one parameter of type
+		    <type>char*</type>. The string given as parameter will be
+		    passed to <function>system</function> function which will
+		    in turn execute <function>/bin/sh -c
+			&lt;string&gt;</function>.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>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>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>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>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>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>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>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 too.
+		</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>prefix</function> - Set the parameter as username
+		    prefix.
+		</para>
+		<para>
+		    The string will be put immediately after "sip:" 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>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>if</function> - if Statement.
+		</para>
+		<para>
+		    There is an expression associated with the command and one
+		    or two linked lists of commands. 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>run_action</function> function. The linked list
+		    represents command enclosed in curly braces of
+		    <function>if</function> command.
+		</para>
+		<para>
+		    Otherwise, if there is the second list, it will be executed
+		    in the same way. The second list represents commands of
+		    <function>else</function> statement.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <function>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 number of parameters.
+		</para>
+		<para>
+		    If the function was found, <function>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>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 -->
+</section>

+ 0 - 6940
doc/serdev/serdev.sgml

@@ -1,6940 +0,0 @@
-<!-- $Id$ -->
-<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN">
-
-<book label="serdev" id="serdev" lang="EN">
-<?dbhtml filename="index.html">
-    <title>SIP Express Router v0.8.8 - Developer's Guide</title>
-    <bookinfo>
-	<authorgroup>
-	    <author>
-		<firstname>Jan</firstname>
-		<surname>Janak</surname>
-		<email>[email protected]</email>
-	    </author>
-	    <author>
-		<firstname>Jiri</firstname>
-		<surname>Kuthan</surname>
-		<email>[email protected]</email>
-	    </author>
-	    <author>
-		<firstname>Bogdan</firstname>
-		<surname>Iancu</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 upon server startup. It's purpose is to initialize the server and
-	    enter main loop. The server initialization will be described in the following sections.
-	</para>
-	
-	<para>
-	    Particular initialization steps are described in order in which they appear in <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 graceful shutdown, print server 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 the <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 a fast 32-bit parser. The parser uses pre-calculated 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 parser's internals will be described
-		later.
-	    </para>
-	</section> <!-- parser-init -->
-	
-<!--
-	<section id="hash-init">
-	    <title>Hash Table Initialization</title>
-	    <para>TBD.</para>
-	</section>
--->
-	
-	<section id="malloc-init">
-	    <title>Malloc Initialization</title>
-	    <para>
-		To make <acronym>SER</acronym> even faster we decided to re-implement 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 subsystem. 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 initialized 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 special file (a named pipe). 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 in another chapter.
-	    </para>
-	</section> <!-- fifo-init -->
-	
-	<section id="builtin-mod-reg">
-	    <title>Built-in 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>
-		immediately with the 
-		core. When the module is compiled in statically, the registration<footnoteref linkend="regfoot"> 
-		must be performed during the server startup. Function 
-		<function moreinfo="none">register_builtin_modules</function> does the job.
-	    </para>
-	</section> <!-- builtin-mod-reg -->
-
-	<section id="ser-config">
-	    <title>Server Configuration</title>
-	    <para>
-		The server is configured through 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 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. A 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>
-		    Flex 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 the 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 isn't conformable with it's
-		    grammar, it is syntactically invalid and cannot be further processed. In that case an error
-		    will be issued and the server will be aborted.
-		</para>
-		<para>
-		    There is a utility called yacc. 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 <acronym>IP</acronym> address every time it finds an <acronym>IP</acronym> 
-		    address in the configuration file and convert the address to its binary representation.
-		</para>
-		<para>For more information see yacc documentation.</para>
-		<para>
-		    yacc creates the parser when the server is being compiled from the sources.
-		    Input file for yacc 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.
-		    Yacc 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 <quote>route</quote> sections will be executed
-			    step by step. The config file must always contain one main <quote>route</quote> statement and 
-			    may contain several additional <quote>route</quote> statements. Request processing always starts 
-			    at the beginning
-			    of the main <quote>route</quote> statement. Additional <quote>route</quote> statements can be 
-			    called from the main
-			    one or another additional <quote>route</quote> statements (It it similar 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 functionality 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">modparam</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 in which 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 the 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 with 
-			<structfield>type</structfield> field set to 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 <function moreinfo="none">action</function> rule to 
-			<function moreinfo="none">actions</function> rule. <function moreinfo="none">Actions</function> rule 
-			will create linked list of all commands. The linked list will be then inserted into  
-			<structfield>rlist</structfield> table.
-			(Function <function moreinfo="none">push</function> in rule <function moreinfo="none">route_stm</function>).
-			Each element of the table represents one <quote>route</quote> 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 array.
-		    </para>
-		    <para>
-			When the core is about to execute route statement with number n, it will look in the array
-			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 step by step.
-		    </para>
-		    <para>
-			Reply-Route statement is compiled in the same way. Main differences are:
-			<itemizedlist>
-			    <listitem>
-				<para>
-				    Reply-Route statement is executed when a <acronym>SIP</acronym> <emphasis>REPLY</emphasis> 
-				    comes (not ,<acronym>SIP</acronym> <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 an error and abort the server.
-		    </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 a 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: 
-				<emphasis>module name</emphasis>, <emphasis>variable name</emphasis> 
-				and <emphasis>variable value</emphasis>.
-			    </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 statement 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 successful, the server will look for
-			<structname>exports</structname> structure describing the module's interface and register the 
-			module. For more details see <link linkend="module-interface">module section</link>.
-		    </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 <acronym>IP</acronym> address and will use interface with 
-		the <acronym>IP</acronym> 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, <acronym>SER</acronym> 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 necessary. That ensures that the server will have
-			access to a particular directory and its subdirectories only.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			Server's working directory is changed if the new working directory was
-			specified (usually it is /).
-		    </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 necessary.
-	    </para>
-	    <para>
-		Instead of that the length of the string parameter could be pre-calculated 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 if necessary.
-	    </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 incoming 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. 
-		<varname>dont_fork</varname> is a global variable defined in <filename moreinfo="none">main.c</filename>.
-		We will describe both variants separately.
-	    </para>
-
-	    <section id="dont-fork-set">
-		<title><varname>dont_fork</varname> variable 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 processing 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 coming 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 The <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 file descriptor), 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 <quote>dont fork</quote> 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 children 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 the <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 attendant. 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 until 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 sequentially call <function moreinfo="none">child_init</function> functions of all loaded modules.
-		</para>
-		<para>
-		    Because 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 necessary
-		    to avoid conflicts. On the other hand 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 zero 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 
-			<structfield>buf</structfield>
-			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 <structfield>orig</structfield> field. The original copy will be not
-			modified during the server operation. All changes will be made to the copy in <structfield>buf</structfield>
-			field. 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 add its own Via - 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 immediately before the routing part of the config file will be executed. 
-			If there are such callbacks registered, they will be executed now.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			As the next step we will determine type of the message. 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
-			successful) 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 chapter <link linkend="routing-engine">The Routing Engine</link>.
-		    </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>The Server Shutdown</title>
-	<para>
-	    The 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> variable 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 shortcoming 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 <function moreinfo="none">destroy</function> 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 function 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 let it restart.
-	</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 detail 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
-		if 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> because the function is relatively slow. It
-		must scan the whole string and find the first occurrence 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>
-	    <important>
-		<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>
-	    </important>
-
-	    
-	    <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 careful 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 self explanatory. HDR_OTHER marks header field not recognized by the parser.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<structfield>name</structfield> - Name of the header field (the part before colon)
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<structfield>body</structfield> - body of the header field (the part after colon)
-		    </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 <type>void*</type> 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 aligned 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 in chapter 
-		SIP Message Modifications.
-	    </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 in chapter
-		SIP Message Modifications.
-	    </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 <type>str</type> 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 occurrence of it; subsequent occurrences 
-     * 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 modified 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 locally 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
-		occurrence 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's <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>REQUEST</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 
-			locally 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 processed.
-	</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 <varname>rlist[0]</varname>. (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 and the message will be dropped.
-	</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 <emphasis>case</emphasis> 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
-			altering.
-		    </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
-			<command moreinfo="none">syslog</command> or <varname>stderr</varname> 
-			(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 destinations and fork the request. 
-		    </para>
-		    <para>
-			The server keeps an 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 <function moreinfo="none">append_branch</function> 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 then 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>.
-		    </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 have mentioned already, there can be more that one route
-			statement in the config file. One of them is main (without
-			number), the other are additional. This command 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 processed.
-		    </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 <varname>rlist</varname> 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 <type>char*</type>. 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 &lt;string&gt;</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 too.
-		    </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
-			commands. 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 the second list, it will be executed in the same way. The
-			second list represents commands 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 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.
-	</para>
-    </chapter>
--->
-
-    <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 servers 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 id="parser-organization">
-	    <title>The Parser Organization</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 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 comparison 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 pre-calculate 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
-			automatically. 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 automatically
-			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 automatically 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 careful
-			    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 automatically 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 structures 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> structure. 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 successfully authorized credentials
-				    (currently 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
-				    containing 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> - Unknown 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 successful:
-			    <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_authorized_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>The 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>
-		<emphasis>Fields and their description:</emphasis>
-		<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;         /* Initialization 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>
-		<emphasis>Fields and their description</emphasis>:
-	    </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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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
-			continue. 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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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 fulfill 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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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 structure 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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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 initialization
-			function. This is an additional 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>
-			<emphasis>Function Prototype</emphasis>:
-		    </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 returned 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 parameter 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 finds module with given name.
-		    Then it will search through 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 of 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 through list of all loaded modules and in each module through
-		array of all exported functions until it finds function with given name and number of
-		parameters. 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 data types. All of them are defined in header files under 
-		<filename moreinfo="none">db</filename> subdirectory,
-		a client must include <filename moreinfo="none">db.h</filename> 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 <type>db_con_t</type> 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 
-		    <type>const char*</type>.
-		</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 data-type 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 data-types 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 data-types are automatically recognized, converted from internal database
-		    representation and stored in a 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 pinter 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</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</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 <type>integer</type> value in <type>db_val_t</type> structure.
-			</para>
-			<example>
-			    <title>VAL_INT Macro</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 <type>double</type> value in the <type>db_val_t</type> structure.
-			</para>
-			<example>
-			    <title>VAL_DOUBLE Macro</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 in <type>db_val_t</type> structure.
-			</para>
-			<example>
-			    <title>VAL_TIME Macro</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 <type>string</type> value in <type>db_val_t</type> structure.
-			</para>
-			<example>
-			    <title>VAL_STRING Macro</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</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 <type>blob</type> value in <type>db_val_t</type> structure.
-			</para>
-			<example>
-			    <title>VAL_STR Macro</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</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</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_result</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</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</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</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</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.
-		Detailed description 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 
-		    mysql://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> -  Hostname 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 <acronym>SQL</acronym> 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 necessary to call
-		    db_free_result 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_result, make a copy yourself if you need to keep it after db_free_result.
-		</para>
-		<para>
-		    You must call db_free_result <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_result</function></title>
-		<para>
-		    This function frees all memory allocated previously in <function moreinfo="none">db_query</function>, 
-		    it is necessary to call this function for a <type>db_res_t</type> 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_result</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 in 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.
-	</para>
-    </chapter>
--->
-    
-    <chapter id="basic-modules">
-	<title>Basic Modules</title>
-	<section id="auth">
-	    <title>Digest Authentication</title>
-	    <para>The module exports functions needed for digest authentication.</para>
-	    <para>
-		The module depends on:
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    <emphasis>mysql</emphasis> - Used as interface to database.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>sl</emphasis> - Used for stateless replies.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </para>
-
-	    <section>
-		<title>Exported Parameters</title>
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    <varname>db_url</varname> - Database url string in form
-			    <quote>mysql://&lt;user&gt;:&lt;pass&gt;@host/database</quote>.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>mysql://serro:47serro11@localhost/ser</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>user_column</varname> - Name of column containing usernames in subscriber table.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>user</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>realm_column</varname> - Name of column containing realm in subscriber table.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>realm</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>password_column</varname> - Name of column containing 
-			    (plaintext passwords)/(ha1 strings) if calculate_ha1 parameter is set to true/false.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>ha1</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>password_column_2</varname> - The parameter can be used if and only if USER_DOMAIN_HACK 
-			    macro is set in defs.h header file. The column of this name contains
-			    alternate ha1 strings calculated from username containing also
-			    domain, for example username="[email protected]". This hack is 
-			    necessary for some broken user agents. The parameter has no
-			    meaning if "calculate_ha1" is set to true.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>ha1b</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>secret</varname> - Nonce secret phrase.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: Randomly generated string.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>group_table</varname> - Name of table containing group definitions.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>grp</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>group_user_column</varname> - Name of column containing usernames in group table.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>user</quote>
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<para>
-			    <varname>group_group_column</varname> - Name of column containing groups in group table.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>grp</quote>
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>calculate_ha1</varname> - If set to true, auth module assumes that 
-			    <quote>password_column</quote> contains plaintext passwords and ha1 string will be calculated
-			    at runtime. If set to false, "password_column" must contain pre-calculated ha1 strings.
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: false
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>nonce_expire</varname> - Every nonce is valid only for a limited amount of time. This
-			    parameter specifies nonce validity interval in seconds. 
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 300
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>retry_count</varname> - This parameter specifies how many times a user is allowed to
-			    retry authentication with incorrect credentials. After that 
-			    the user will receive 403 Forbidden and must retry with different 
-			    credentials. This should prevent DoS attacks from misconfigured
-			    user agents which try to authenticate with incorrect password 
-			    again and again and again.
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 5
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-
-	    <section>
-		<title>Exported Functions</title>
-		<itemizedlist>
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">www_authorize</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function checks credentials in Authorization header field.
-			</para>
-			<para>
-			    <varname>realm</varname> - Realm string
-			</para>
-			<para>
-			    <varname>table</varname> - Subscriber table name
-			</para>
-			<example>
-			    <title>www_authorize</title>
-			    <programlisting format="linespecific">
-if (!www_authorize( "iptel.org", "subscriber" )) {
-    www_challenge(  "iptel.org", "0"); 
-    break; 
-}
-</programlisting>
-			</example>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">proxy_authorize</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function checks credentials in Proxy-Authorization header field.
-			</para>
-			<para>
-			    <varname>realm</varname> - Realm string
-			</para>
-			<para>
-			    <varname>table</varname> - Subscriber table name
-			</para>
-			<example>
-			    <title>proxy_authorize</title>
-			    <programlisting format="linespecific">
-if (!proxy_authorize( "iptel.org", "subscriber" )) {
-    proxy_challenge(  "iptel.org", "0"); 
-    break; 
-}
-</programlisting>
-			</example>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">www_challenge</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">qop</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Challenges a user agent using WWW-Authenticate header
-			    field. The second parameter specifies if qop parameter
-			    (according to rfc2617) should be used or not.
-			    (Turning off is useful primarily to make UAC happy, which
-			    have a broken qop implementation, particularly M$ Messenger 4.6).
-			</para>
-			<para>
-			    <varname>realm</varname> - Realm string
-			</para>
-			<para>
-			    <varname>qop</varname> - Qop string, <quote>1</quote> means use qop parameter
-                            <quote>0</quote> means do not use qop parameter.
-			    
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">proxy_challenge</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">qop</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Challenges a user agent using Proxy-Authenticate header
-			    field. The second parameter specifies if qop parameter
-			    (according to rfc2617) should be used or not.
-			    (Turning off is useful primarily to make UAC happy, which
-			    have a broken qop implementation, particularly M$ Messenger 4.6).
-			</para>
-			<para>
-			    <varname>realm</varname> - Realm string
-			</para>
-			<para>
-			    <varname>qop</varname> - Qop string, <quote>1</quote> means use qop parameter
-                            <quote>0</quote> means do not use qop parameter.
-			    
-			</para>
-		    </listitem>
-		    
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">is_user</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">username</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Checks if the specified username and matches the username
-			    in credentials. 
-			    Call after *_authorize, otherwise an error will be issued.
-			</para>
-			<para>
-			    <varname>username</varname> - Username string.
-			</para>
-			<para>
-			    <varname>s</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">is_in_group</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">group</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Checks if the user specified in credentials is member of
-			    given group
-			    Call after *_authorize, otherwise an error will be issued.
-			</para>
-			<para>
-			    <varname>group</varname> - Group name.
-			</para>
-			<para>
-			    <varname>s</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">check_to</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Checks if the username given in credentials and username in
-			    To header field are equal
-			    Call after *_authorize, otherwise an error will be issued.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-			<example>
-			    <title>check_to</title>
-			    <programlisting format="linespecific">
-if (method=="REGISTER" & proxy_authorize("iptel.org", "subscriber" ) {
-    if (!check_to) { 
-        sl_send_reply("403", "cheating: user!=to");
-        break;
-    }
-}
-</programlisting>
-			</example>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">check_from</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Checks if the username given in credentials and username in
-			    From header field are equal.
-			    Call after *_authorize, otherwise an error will be issued.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">consume_credentials</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Removes previously authorized credentials from the message.
-			    The function must be called after {www,proxy}_authorize.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">is_user_in</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">hf</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">group</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Checks, if the user is in specified table.
-			</para>
-			<para>
-			    <varname>hf</varname> - Use username in this header field, the following values
-			    are recognized:
-			    <itemizedlist>
-				<listitem>
-				    <para>
-					<quote>From</quote> - Extract username from From URI.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					<quote>To</quote> - Extract username from To URI.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					<quote>Request-URI</quote> - Extract username from Request-URI.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					<quote>credentials</quote> - Use username digest parameter.
-				    </para>
-				</listitem>
-			    </itemizedlist>
-			</para>
-			<para>
-			    <varname>group</varname> - Group name.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-	</section> <!-- auth -->
-
-
-	<section id="max-fwd">
-	    <title>Max Forwards</title>
-	    <para>
-		Implements all the operations regarding MAX-Forward header, like adding it (if
-		not present) or decrementing and checking the value of the existent one.
-	    </para>
-	    <para>
-		Module dependencies: none.
-	    </para>
-	    <section>
-		<title>Exported Parameters</title>
-		<para>
-		    None.
-		</para>
-	    </section>
-	    <section>
-		<title>Exported Functions</title>
-		<funcsynopsis>
-		    <funcprototype>
-			<funcdef>int <function moreinfo="none">mf_process_maxfwd_header</function></funcdef>
-			<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-			<paramdef>char* <parameter moreinfo="none">max_value</parameter></paramdef>
-			<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-		    </funcprototype>
-		</funcsynopsis>
-		<para>
-		    If no Max-Forwards header is present in the received request, a header will be
-		    added having the original value equal with "max_value". An OK code is returned
-		    by the function.
-		</para>
-		<para>
-		    If a Max-Forwards header is already present, its value will be decremented. If
-		    after this operation its value will be positive non-zero, an OK code will be
-		    returned. Otherwise (for a zero value) an error code will be returned.
-		    Note that an error code will be also returned if the SIP message couldn't
-		    be parsed or if the Max-Forwards header's body invalid (non numerical string or
-		    negative numerical value)
-		</para>
-		<para>
-		    Parameter s is not used.
-		</para>
-	    </section>
-
-	</section> <!-- max-fwd -->
-
-
-
-
-
-	<section id="registrar">
-	    <title>Registrar</title>
-	    <para>The module contains REGISTER processing logic.</para>
-	    <para>
-		The module depends on:
-		<itemizedlist>
-		    <listitem>
-			<para><emphasis>usrloc</emphasis> - User location module.</para>
-		    </listitem>
-		    <listitem>
-			<para><emphasis>sl</emphasis> - Used for stateless replies.</para>
-		    </listitem>
-		</itemizedlist>
-	    </para>
-	    <section>
-		<title>Exported Parameters</title>
-
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    <varname>default_expires</varname> - If the processed message contains neither Expires HFs nor
-			    expires contact parameters, this value will be used
-			    for newly created usrloc records. The parameter contains
-			    number of second to expire (for example use 3600 for one hour).
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 3600
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<para>
-			    <varname>default_q</varname> - The parameter represents default q value for new contacts. Because
-			    ser doesn't support float parameter types, the value in the parameter
-			    is divided by 100 and stored as float. For example, if you want default_q
-			    to be 0.38, use value 38 here.
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 0
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <varname>append_branches</varname> - The parameter controls how lookup function processes 
-			    multiple contacts. If there are multiple contacts for the given username in usrloc and this
-			    parameter is set to 1, Request-URI will be overwritten with the highest-q
-			    rated contact and the rest will be appended to sip_msg structure and can 
-			    be later used by tm for forking. If the parameter is set to 0, only 
-			    Request-URI will be overwritten with the highest-q rated contact and the 
-			    rest will be left unprocessed.  
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 1
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-
-	    <section>
-		<title>Exported Functions</title>
-		<itemizedlist>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">save</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function processes a REGISTER message. It can add, remove or modify
-			    usrloc records depending on Contact and Expires HFs in the REGISTER message.
-			    On success, 200 OK will be returned listing all contacts that are currently
-			    in usrloc. On an error, error message will be send with a short description
-			    in reason phrase.
-			</para>
-			<para>
-			    <varname>table</varname> - Table name where contacts should be stored.
-			</para>
-			<para>
-			    <varname>s</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">lookup</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The functions extracts username from Request-URI and tries to find all contacts
-			    for the username in usrloc. If there are no such contacts, -1 will be returned.
-			    If there are such contacts, Request-URI will be overwritten with the contact that
-			    has the highest q value and optionally the rest will be appended to the message
-			    (depending on append_branches parameter value).
-			</para>
-			<para>
-			    <varname>table</varname> - Name of table that should be used for the lookup.
-			</para>
-			<para>
-			    <varname>s</varname> - Not used.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-	</section> <!-- registrar -->
-
-
-	<section id="rr">
-	    <title>Record-Routing</title>
-	    <para>Record Routing module.</para>
-	    <para>
-		The module depends on: None.
-	    </para>
-
-	    <section>
-		<title>Exported Parameters</title>
-		<para>
-		    None.
-		</para>
-	    </section>
-	    <section>
-		<title>Exported Functions</title>
-
-		<itemizedlist>
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">rewriteFromRoute</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    If there are any Route HFs in the message, the function
-			    takes the first one, rewrites Request-URI with it's value
-			    and removes the first URI from Route HFs.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">addRecordRoute</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function adds a new Record-Route header field. The
-			    header field will be inserted in the message before any
-			    other Record-Route header fields.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-	</section> <!-- rr -->
-
-
-	<section id="sl">
-	    <title>Stateless Replies</title>
-	    <para>
-		The SL module provide possibilities to send stateless replies for the current 
-		request. Additional, a filter function is available for checking the ACK
-		requests generated by sending a SL reply to a INVITE req. Also, offers the
-		possibility to send explanatory SL replies in case of an internal error.
-	    </para>
-
-	    <para>
-		For the SL module to be able to recognize the ACKs generated by INVITE's
-		replies sent by itself, all the sent replies will have attached to TO header
-		a "tag" param. having a unique value (that was random generated at ser 
-		startup).When an ACK is received, the TO tag param tag is checked if
-		corresponds - all UAS MUST copy the TO tag from replies into ACK requests!
-		TO speed up the filtering process, the module uses a timeout mechanism. When
-		a reply is sent, a timer us set. As time as the timer is valid, The incoming
-		ACK requests will be checked using TO tag value  Once the timer expires, all
-		the ACK are let through - a long time passed till it sent a reply, so it does
-		not expect any ACK that have to be blocked.
-	    </para>
-	    
-	    <section>
-		<title>Exported Parameters</title>
-		<para>None.</para>
-	    </section>
-
-
-	    <section>
-		<title>Exported Functions</title>
-		<itemizedlist>
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">sl_send_reply</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">code</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">text_reason</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    For the current request, a reply is sent back having the given code and text
-			    reason. The reply is sent stateless, totally independent of the Transaction
-			    module and with no retransmission for the INVITE's replies.
-			</para>
-			<para>
-			    <varname>code</varname> - Reply code to be used.
-			</para>
-			<para>
-			    <varname>text_reason</varname> - Reason phrase to be used.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">sl_filter_ACK</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Identifies and blocks the ACK requests generated by INVITE's replies sent
-			    using the sl_send_reply() or sl_send_error() functions.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">sl_reply_error</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Identifies and blocks the ACK requests generated by INVITE's replies sent
-			    using the sl_send_reply() or sl_send_error() functions.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-	</section> <!-- sl -->
-
-	<section id="tm">
-	    <title>Transaction Module</title>
-	    <para>
-		The module implements logic necessary to manage SIP transactions.
-	    </para>
-	    <para>
-		The module depends on: None.
-	    </para>
-	    <para>
-		TM Module enables stateful processing of SIP transactions.
-		The main use of stateful logic, which is costly in terms of
-		memory and CPU, is some services inherently need state.
-		For example, transaction-based accounting (module acc) needs
-		to process transaction state as opposed to individual messages,
-		and any kinds of forking must be implemented statefully.
-		Other use of stateful processing is it trading CPU caused by 
-		retransmission processing for memory. That makes however only
-		sense if CPU consumption per request is huge. For example,
-		if you want to avoid costly DNS resolution for every retransmission
-		of a request to an unresolvable destination, use stateful mode.
-		Then, only the initial message burdens server by DNS queries,
-		subsequent retransmissions will be dropped and will not result in
-		more processes blocked by DNS resolution. The price is more 
-		memory consumption and higher processing latency.
-	    </para>
-	    <para>
-		From user's perspective, there are two major functions :
-		t_relay and t_relay_to. Both setup transaction state,
-		absorb retransmissions from upstream, generate downstream
-		retransmissions and correlate replies to requests.
-		t_relay forwards to current uri (be it original request's
-		uri or a uri changed by some of uri-modifying functions,
-		such as sethost). t_relay_to forwards to a specific address.
-	    </para>
-	    <para>
-		In general, if TM is used, it copies clones of received SIP
-		messages in shared memory. That costs the memory and also CPU
-		time (memcpys, lookups, shmem locks, etc.) Note that non-TM
-		functions operate over the received message in private memory,
-		that means that any core operations will have no effect on
-		statefully processed messages after creating the transactional
-		state. For example, calling addRecordRoute *after* t_relay
-		is pretty useless, as the RR is added to privately held message
-		whereas its TM clone is being forwarded.
-	    </para>
-	    <para>
-		TM is quite big and uneasy to program -- lot of mutexes, shared
-		memory access, malloc & free, timers -- you really need to be careful
-		when you do anything. To simplify TM programming, there is the
-		instrument of callbacks. The callback mechanisms allow programmers
-		to register their functions to specific event. See t_hooks.h
-		for a list of possible events.
-	    </para>
-	    <para>
-		Other things programmers may want to know is UAC -- it is 
-		a very simplistic code which allows you to generate your own
-		transactions. Particularly useful for things like NOTIFYs or
-		IM gateways. The UAC takes care of all the transaction
-		machinery: retransmissions , FR timeouts, forking, etc.
-		See t_uac prototype in uac.h for more details. Who wants to
-		see the transaction result may register for a callback.
-	    </para>
-
-	    <section>
-		<title>External Usage of TM</title>
-		<para>
-		    There are applications which would like to generate SIP
-		    transactions without too big involvement in SIP stack, transaction
-		    management, etc. An example of such an application
-		    is sending instant messages from a website. To address needs
-		    of such apps, SER accepts requests for new transactions via
-		    fifo pipes too. If you want to enable this feature, start
-		    FIFO server by configuration option
-		    fifo=<quote>/tmp/filename</quote>
-		    Then, an application can easily launch a new transaction by
-		    writing a transaction request to this named pipe. The request
-		    must follow very simple format, which is
-		    <programlisting format="linespecific">
-:t_uac:[&lt;file_name&gt;]\n
-&lt;method&gt;\n
-&lt;dst uri&gt;\n
-&lt;CR_separated_headers&gt;\n
-&lt;body&gt;\n
-\n
-\n
-</programlisting>
-		    (Filename is to where a report will be dumped. ser assumes /tmp
-		    as file's directory.)
-		</para>
-
-		<para>
-		    A convenience library fifo_uac.c implements this simple functionality.
-		    Note the the request write must be atomic, otherwise the request
-		    might get intermixes with writes from other writers.
-		    You can easily use it via Unix command-line tools, see the following
-		    example:
-		    <example>
-			<title>UAC</title>
-			<screen format="linespecific">
-[jiri@bat jiri]$ cat &gt; /tmp/fifo
-:t_uac:xxx
-MESSAGE
-sip:[email protected]
-header:value
-foo:bar
-bznk:hjhjk
-p_header: p_value
-
-body body body
-yet body
-end of body
-</screen>
-		    </example>
-		    Or use an example file and call cat test/transaction.fifo &gt; /tmp/fifo
-		</para>
-	    </section>
-
-
-	    
-
-	    <section>
-		<title>Exported Parameters</title>
-		<itemizedlist>
-
-		    <listitem>
-			<para>
-			    <varname>fr_timer</varname> - Timer which hits if no final reply for a request or
-			    ACK for a negative INVITE reply arrives.
-			</para>
-			<para>
-			    Type: <type>integer</type> (seconds)
-			</para>
-			<para>
-			    Default: 30
-			</para>
-		    </listitem>		
-
-		    <listitem>
-			<para>
-			    <varname>fr_inv_timer</varname> - Timer which hits if no final reply for an INVITE
-			arrives after a provisional message was received.
-			</para>
-			<para>
-			    Type: <type>integer</type> (seconds)
-			</para>
-			<para>
-			    Default: 120
-			</para>
-		    </listitem>		
-
-		    <listitem>
-			<para>
-			    <varname>wt_timer</varname> - Time for which a transaction stays in memory to absorb
-			    delayed messages after it completed; also, when this
-			    timer hits, retransmission of local cancels is stopped
-			    (a puristic but complex behavior would be not to enter
-			    wait state until local branches are finished by a final
-			    reply or FR timer -- we simplified)
-			</para>
-			<para>
-			    Type: <type>integer</type> (seconds)
-			</para>
-			<para>
-			    Default: 5
-			</para>
-		    </listitem>		
-
-		    <listitem>
-			<para>
-			    <varname>delete_timer</varname> - Time after which a to-be-deleted transaction currently
-			    ref-ed by a process will be tried to be deleted again.
-			</para>
-			<para>
-			    Type: <type>integer</type> (seconds)
-			</para>
-			<para>
-			    Default: 2
-			</para>
-		    </listitem>		
-
-		    <listitem>
-			<para>
-			    <varname>retr_timer1p1, 2, 3</varname> - Retransmission period.
-			</para>
-			<para>
-			    Type: <type>integer</type> (seconds)
-			</para>
-			<para>
-			    Default: RETR_T1=1, 2*RETR_T1, 4*RETR_T1
-			</para>
-		    </listitem>		
-
-		    <listitem>
-			<para>
-			    <varname>retr_timer2</varname> - Maximum retransmission period.
-			</para>
-			<para>
-			    Type: <type>integer</type> (seconds)
-			</para>
-			<para>
-			    Default: RETR_T2=4
-			</para>
-		    </listitem>		
-
-		    <listitem>
-			<para>
-			    <varname>noisy_ctimer</varname> - If set, on FR timer INVITE transactions will be 
-			    explicitly canceled if possible, silently dropped
-			    otherwise; preferably, it is turned off to allow
-			    very long ringing; this behavior is overridden if
-			    a request is forked, or some functionality explicitly
-			    turned it off for a transaction (like acc does to avoid
-			    unaccounted transactions due to expired timer).
-			</para>
-			<para>
-			    Type: <type>integer</type> (boolean)
-			</para>
-			<para>
-			    Default: 0 (false)
-			</para>
-		    </listitem>		
-		</itemizedlist>
-	    </section>
-
-	    <section>
-		<title>Exported Functions</title>
-		
-		<itemizedlist>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_relay_to</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">ip_address</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">port_number</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Relay a message statefully to a fixed destination; this along with
-			    t_relay is the function most users want to use -- all other are
-			    mostly for programming; programmers interested in writing TM
-			    logic should review how t_relay is implemented in tm.c and how
-			    TM callbacks work.
-			</para>
-			<para>
-			    <varname>ip_address</varname> - IP address of the destination.
-			</para>
-			<para>
-			    <varname>port_number</varname> - Port of the destination.
-			</para>
-			<example>
-			    <title>t_relay_to</title>
-			    <programlisting format="linespecific">
-if (!t_relay_to("1.2.3.4", "5060")) { 
-    sl_reply_error(); 
-    break; 
-};
-</programlisting>
-			</example>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_relay</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Relay a message statefully to destination indicated in current URI;
-			    (if the original URI was rewritten by UsrLoc, RR, strip/prefix,
-			    etc., the new URI will be taken); returns a negative value on
-			    failure -- you may still want to send a negative reply upstream
-			    statelessly not to leave upstream UAC in lurch.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-			<example>
-			    <title>t_relay</title>
-			    <programlisting format="linespecific">
-if (!t_relay()) { 
-    sl_reply_error(); 
-    break; 
-};
-</programlisting>
-			</example>
-		    </listitem>
-
-
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_on_negative</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">reply_route</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Sets reply routing block, to which control is passed after
-			    a transaction completed with a negative result but before
-			    sending a final reply; In the referred block, you can
-			    either start a new branch (good for services such as
-			    forward_on_no_reply) or send a final reply on your own
-			    (good for example for message silo, which received 
-			    a negative reply from upstream and wants to tell
-			    upstream "202 I will take care of it"); Note that the
-			    set of command which are usable within reply_routes is
-			    strictly limited to rewriting URI, initiating new branches,
-			    logging, and sending 'unsafe' replies (t_reply_unsafe). Any 
-			    other commands may result in unpredictable behavior and 
-			    possible server failure.
-			    Note that whenever reply_route is entered, uri is reset to
-			    value which it had on relaying. If it temporarily changed
-			    during a reply_route processing, subsequent reply_route
-			    will ignore the changed value and use again the original
-			    one.
-			</para>
-			<para>
-			    <varname>reply_route</varname> - Reply routing block.
-			</para>
-			<para>
-			    <varname>s</varname> - Not used.
-			</para>
-			<example>
-			    <title>t_on_negative</title>
-			    <programlisting format="linespecific">
-route { 
-    t_on_negative("1"); 
-    t_relay(); 
-} reply_route[1] {
-    revert_uri(); 
-    setuser("voicemail"); 
-    append_branch(); 
-}
-</programlisting>
-			</example>
-		    </listitem>
-
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_newtran</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Creates a new transaction, returns a negative value on 
-			    error; this is the only way a script can add a new transaction 
-			    in an atomic way; typically, it is used to deploy a UAS
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-			<example>
-			    <title>t_newtran</title>
-			    <programlisting format="linespecific">
-if (t_newtran()) { 
-    log("UAS logic"); 
-    t_reply("999","hello"); 
-} else sl_reply_error();
-</programlisting>
-			</example>
-		    </listitem>
-
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_reply</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">code</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">reason_phrase</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Sends a stateful reply after a transaction has been
-			    established; see t_newtran for usage; note: never use
-			    t_reply from within reply_route ... always use t_reply_unsafe.
-			</para>
-			<para>
-			    <varname>code</varname> - Code of the response.
-			</para>
-			<para>
-			    <varname>reason_phrase</varname> - Reason phrase of the response.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_lookup_request</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Checks if a transaction exists; returns a positive value
-			    if so, negative otherwise; most likely you will not want
-			    to use it, as a typical application of a look-up is to
-			    introduce a new transaction if none was found; however
-			    this is safely (atomically) done using t_newtran.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-		    
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_retransmit_reply</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Retransmits a reply sent previously by UAS transaction.
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_release</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Remove transaction from memory (it will be first put on
-			    a wait timer to absorb delayed messages).
-			</para>
-			<para>
-			    <varname>s1</varname> - Not used.
-			</para>
-			<para>
-			    <varname>s2</varname> - Not used.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_forward_noack</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">ip</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">port</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Mainly for internal -- forward a non-ACK request statefully.
-			</para>
-			<para>
-			    <varname>ip</varname> - IP address.
-			</para>
-			<para>
-			    <varname>port</varname> - Port number.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">register_tmcb</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">cb_type</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">cb_func</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    For programmatic use only -- register a function to be called
-			    back on an event; see t_hooks.h for more details.
-			</para>
-			<para>
-			    <varname>cb_type</varname> - Callback type.
-			</para>
-			<para>
-			    <varname>cb_func</varname> - Callback function.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">load_tm</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">import_structure</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    For programmatic use only -- import exported TM functions;
-			    see the acc module for an example of use.
-			</para>
-			<para>
-			    <varname>import_structure</varname> - Structure where pointers to tm functions will be stored.
-			</para>
-			<para>
-			    <varname>s</varname> - Not used.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">t_reply_unsafe</function></funcdef>
-				<paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">code</parameter></paramdef>
-				<paramdef>char* <parameter moreinfo="none">reason_phrase</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Sends a stateful reply after a transaction has been
-			    established; it can only be used from reply processing;
-			    using it from regular processing will introduce erroneous
-			    conditions; using t_reply from reply_processing will
-			    introduce a deadlock.
-			</para>
-			<para>
-			    <varname>code</varname> - Code of the reply.
-			</para>
-			<para>
-			    <varname>reason_phrase</varname> - Reason phrase of the reply.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-
-	    <section>
-		<title>Known Issues</title>
-		<itemizedlist>
-		    <listitem>
-			<para>Need to revisit profiling again.</para>
-		    </listitem>
-		    <listitem>
-			<para>Review whether there is not potential for to-tag rewriting and ACK matching.</para>
-		    </listitem>
-		    <listitem>
-			<para>We don't have authentication merging on forking.</para>
-		    </listitem>
-		    <listitem>
-			<para>Branch tid is not used yet.</para>
-		    </listitem>
-		    <listitem>
-			<para>local ACK/CANCELs copy'n'pastes Route and ignores deleted Routes</para>
-		    </listitem>
-		    <listitem>
-			<para>6xx should be delayed.</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    Possibly, performance could be improved by not parsing non-INVITEs,
-			    as they do not be replied with 100, and do not result in ACK/CANCELs,
-			    and other things which take parsing. However, we need to rethink
-			    whether we don't need parsed headers later for something else.
-			    Remember, when we now conserver a request in sh_mem, we can't apply
-			    any pkg_mem operations to it any more. (that might be redesigned too).
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    t_replicate should be done more cleanly -- Vias, Routes, etc. should
-			    be removed from a message prior to replicating it.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>SNMP support.</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    Lookup fails to recognize subsequent requests which have additional 
-			    leading spaces in header field values.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    Make UAC session-aware (as opposed to just transaction aware) -- needed
-			    for keeping SUB-NOT dialog state, etc. Currently, there are only
-			    place-holders for in in TM.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>Places labeled with "HACK" strongly deserve beautification.</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-	</section> <!-- tm -->
-
-	<section id="usrloc">
-	    <title>User Location Module</title>
-	    <para>Support for location of users.</para>
-	    <para>Module depends on: Optionally mysql (if configured for persistence)</para>
-
-	    <important>
-		<para>
-		    Usrloc is convenient module only. It's functions cannot be called from scripts
-		    directly, but are used by registrar module internally.  This module will be
-		    utilized by more modules in the future and therefore it is standalone. Use
-		    registrar module functions if you need usrloc support in your scripts.
-		</para>
-	    </important>
-
-	    <section>
-		<title>Exported Parameters</title>
-		<itemizedlist>
-
-		    <listitem>
-			<para>
-			    <varname>user_col</varname> - Name of column containing usernames.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>user</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>contact_col</varname> - Name of column containing contacts.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>contact</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>expires_col</varname> - Name of column containing expires.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>expires</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>q_col</varname> - Name of column containing q values.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>q</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>callid_col</varname> - Name of column containing callids.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>callid</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>cseq_col</varname> - Name of column containing cseq numbers.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>cseq</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>method_col</varname> - Name of column containing supported methods.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>method</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>db_url</varname> - URL of the database that should be used.
-			</para>
-			<para>
-			    Type: <type>string</type>
-			</para>
-			<para>
-			    Default: <quote>mysql://ser:heslo@localhost/ser</quote>
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>timer_interval</varname> - Number of seconds between two timer runs. The
-			    module uses timer to delete expired contacts,
-			    synchronize with database and other tasks, that
-			    need to be run periodically.
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 60 seconds
-			</para>
-		    </listitem>				
-
-		    <listitem>
-			<para>
-			    <varname>db_mode</varname> - The usrloc module can utilize database for persistent
-			    contact storage. If you use database, your contacts
-			    will survive machine restarts or SW crashes. The
-			    disadvantage is that accessing database can be very
-			    time consuming. Therefore, usrloc module implements
-			    three database accessing modes:
-			    <itemizedlist>
-				<listitem>
-				    <para>
-					0 - This disables database completely. Only memory
-					will be used. Contacts will not survive restart.
-					Use this value if you need a really fast usrloc
-					and contact persistence is not necessary or is
-					provided by other means.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					1 - <emphasis>Write-Through</emphasis> scheme. All changes to usrloc are
-					immediately reflected in database too. This is
-					very slow, but very reliable. Use this scheme
-					if speed is not your priority but need to make
-					sure that no registered contacts will be lost
-					during crash or reboot.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					2 - <emphasis>Write-Back</emphasis> scheme. This is a combination of
-					previous two schemes. All changes are made to
-					memory and database synchronization is done
-					in the timer. The timer deletes all expired contacts
-					and flushes all modified or new contacts to database.
-					Use this scheme if you encounter high-load peaks and
-					want them to process as fast as possible. The mode
-					will not help at all if the load is high all the time.
-					Also, latency of this mode is much lower than latency
-					of mode 1, but slightly higher than latency of mode 0.
-				    </para>
-				</listitem>
-			    </itemizedlist>
-			</para>
-			<para>
-			    Type: <type>integer</type>
-			</para>
-			<para>
-			    Default: 0
-			</para>
-			<warning>
-			    <para>
-				In case of crash or restart contacts that
-				are in memory only and haven't been flushed
-				yet will get lost. If you want minimize the
-				risk, use shorter timer interval.
-			    </para>
-			</warning>
-		    </listitem>				
-		</itemizedlist>
-	    </section>
-
-	    <section>
-		<title>Exported Functions</title>
-		<itemizedlist>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_register_domain</function></funcdef>
-				<paramdef>const char* <parameter moreinfo="none">name</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function registers a new domain. Domain is just another name
-			    for table used in registrar. The function is called from fixups
-			    in registrar. It gets name of the domain as a parameter and returns
-			    pointer to a new domain structure. The fixup than 'fixes' the
-			    parameter in registrar so that it will pass the pointer instead of
-			    the name every time save() or lookup() is called. Some usrloc functions
-			    get the pointer as parameter when called. For more details see 
-			    implementation of save function in registrar.
-			</para>
-			<para>
-			    <varname>name</varname> - Name of the domain (also called table) to be
-                            registered.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_insert_urecord</function></funcdef>
-				<paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">aor</parameter></paramdef>
-				<paramdef>urecord_t** <parameter moreinfo="none">rec</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function creates a new record structure and inserts it in the specified
-			    domain. The record is structure that contains all the contacts for belonging
-			    to the specified username.			
-			</para>
-			<para>
-			    <varname>domain</varname> - Pointer to domain returned by ul_register_udomain.
-			</para>
-			<para>
-			    <varname>aor</varname> - Address of Record (aka username) of the new record
-                            (at this time the record will contain no contacts yet).
-			</para>
-			<para>
-			    <varname>rec</varname> - The newly created record structure.
-			</para>
-		    </listitem>
-
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_delete_urecord</function></funcdef>
-				<paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">aor</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function deletes all the contacts bound with the given Address Of Record.
-			</para>
-			<para>
-			    <varname>domain</varname> - Pointer to domain returned by ul_register_udomain.
-			</para>
-			<para>
-			    <varname>aor</varname> - Address of record (aka username) of the record, that should
-                            be deleted.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_get_urecord</function></funcdef>
-				<paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">aor</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function returns pointer to record with given Address of Record.
-			</para>
-			<para>
-			    <varname>domain</varname> - Pointer to domain returned by ul_register_udomain.
-			</para>
-			<para>
-			    <varname>aor</varname> - Address of Record of request record.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_lock_udomain</function></funcdef>
-				<paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function lock the specified domain, it means, that no other processes
-			    will be able to access during the time. This prevents race conditions. Scope
-			    of the lock is the specified domain, that means, that multiple domain can be
-			    accessed simultaneously, they don't block each other.
-			</para>
-			<para>
-			    <varname>domain</varname> - Domain to be locked.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_unlock_udomain</function></funcdef>
-				<paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Unlock the specified domain previously locked by ul_lock_udomain.
-			</para>
-			<para>
-			    <varname>domain</varname> - Domain to be unlocked.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_release_urecord</function></funcdef>
-				<paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    Do some sanity checks - if all contacts have been removed, delete the entire
-			    record structure.
-			</para>
-			<para>
-			    <varname>record</varname> - Record to be released.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_insert_ucontact</function></funcdef>
-				<paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">contact</parameter></paramdef>
-				<paramdef>time_t <parameter moreinfo="none">expires</parameter></paramdef>
-				<paramdef>float <parameter moreinfo="none">q</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">callid</parameter></paramdef>
-				<paramdef>int <parameter moreinfo="none">cseq</parameter></paramdef>
-				<paramdef>ucontact_t* <parameter moreinfo="none">cont</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function inserts a new contact in the given record with specified parameters.
-			</para>
-			<para>
-			    <varname>record</varname> - Record in which the contact should be inserted.
-			</para>
-			<para>
-			    <varname>contact</varname> - Contact URL.
-			</para>
-			<para>
-			    <varname>expires</varname> - Expires of the contact in absolute value.
-			</para>
-			<para>
-			    <varname>q</varname> - q value of the contact.
-			</para>
-			<para>
-			    <varname>callid</varname> - Call-ID of the REGISTER message that contained the contact.
-			</para>
-			<para>
-			    <varname>cseq</varname> - CSeq of the REGISTER message that contained the contact.
-			</para>
-			<para>
-			    <varname>cont</varname> - Pointer to newly created structure.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_delete_ucontact</function></funcdef>
-				<paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
-				<paramdef>ucontact_t* <parameter moreinfo="none">contact</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function deletes given contact from record.
-			</para>
-			<para>
-			    <varname>record</varname> - Record from which the contact should be removed.
-			</para>
-			<para>
-			    <varname>contact</varname> - Contact to be deleted.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_get_ucontact</function></funcdef>
-				<paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">contact</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function tries to find contact with given Contact URI and returns
-			    pointer to structure representing the contact.
-			</para>
-			<para>
-			    <varname>record</varname> - Record to be searched for the contact.
-			</para>
-			<para>
-			    <varname>contact</varname> - URI of the request contact.
-			</para>
-		    </listitem>
-
-
-		    <listitem>
-			<funcsynopsis>
-			    <funcprototype>
-				<funcdef>int <function moreinfo="none">ul_update_ucontact</function></funcdef>
-				<paramdef>ucontact_t* <parameter moreinfo="none">contact</parameter></paramdef>
-				<paramdef>time_t <parameter moreinfo="none">expires</parameter></paramdef>
-				<paramdef>float <parameter moreinfo="none">q</parameter></paramdef>
-				<paramdef>str* <parameter moreinfo="none">callid</parameter></paramdef>
-				<paramdef>int <parameter moreinfo="none">cseq</parameter></paramdef>
-			    </funcprototype>
-			</funcsynopsis>
-			<para>
-			    The function updates contact with new values.
-			</para>
-			<para>
-			    <varname>contact</varname> - Contact to be updated.
-			</para>
-			<para>
-			    <varname>expires</varname> - New expires value.
-			</para>
-			<para>
-			    <varname>q</varname> - New q value.
-			</para>
-			<para>
-			    <varname>callid</varname> - New Call-ID.
-			</para>
-			<para>
-			    <varname>cseq</varname> - New CSeq.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </section>
-	</section> <!-- usrloc -->
-    </chapter> <!-- basic-modules -->
-
-<!--    
-
-	    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
-	    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
-	    Dopsat interface configuration sekci.
-	    Use command tag
-	    Use error code tag
-	    qandaset - FAQ    
--->
-</book>

+ 73 - 0
doc/serdev/serdev.xml

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="serdev" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<authorgroup>
+	    <author>
+		<firstname>Jan</firstname>
+		<surname>Janak</surname>
+		<email>[email protected]</email>
+	    </author>
+	    <author>
+		<firstname>Jiri</firstname>
+		<surname>Kuthan</surname>
+		<email>[email protected]</email>
+	    </author>
+	    <author>
+		<firstname>Bogdan</firstname>
+		<surname>Iancu</surname>
+		<email>[email protected]</email>
+	    </author>
+	</authorgroup>
+	<copyright>
+	    <year>2001</year>
+	    <year>2002</year>
+	    <holder>FhG FOKUS</holder>
+	</copyright>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+	<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>
+    </sectioninfo>
+    
+    <title>SER Developer's Guide</title>
+    
+    <xi:include href="startup.xml"/>
+    <xi:include href="main_loop.xml"/>
+    <xi:include href="shutdown.xml"/>
+    <xi:include href="data_structures.xml"/>
+    <xi:include href="routing_engine.xml"/>
+
+    <xi:include href="msg_parser.xml"/>
+    <xi:include href="modiface.xml"/>
+    <xi:include href="db_interface.xml"/>
+    <xi:include href="locking.xml"/>
+
+    <!--    
+    TODO:
+    * How to traverse all headers of given type
+    * How to append a header at the end of the message
+    * How to insert a header at the beginning of the message
+    * How to delete a chunk of text from the header
+    * How to add header into a reply
+    * How mod_destroy gets called, from which process and how many times
+    -->
+</section>

+ 100 - 0
doc/serdev/shutdown.xml

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="shutdown" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>The Server Showdown</title>
+    <para>
+	The 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>sig_usr</function> in file <filename>main.c</filename>.
+    </para>
+    
+    <para>
+	In normal mode of operation (<varname>dont_fork</varname> variable is
+	not set), the main server is not processing any requests, it calls
+	<function>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>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 shortcoming doesn't
+	harm in that case.
+    </para>
+    <para>
+	Upon receipt of SIGINT, SIGPIPE or SIGTERM
+	<function>destroy_modules</function> will be called.  Each module may
+	register so-called <function>destroy</function> function if it needs to
+	do some cleanup when the server is terminating (flush of cache to disk
+	for example). <function>destroy_modules</function> will call destroy
+	function 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 let it restart.
+    </para>
+
+</section> <!-- server-shutdown -->

+ 397 - 0
doc/serdev/sip_msg.xml

@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="sip_msg" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>
+	<programlisting>
+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 occurrence of it; subsequent occurrences 
+     * 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 modified 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 locally 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>
+    <para>
+	<emphasis>Field Description:</emphasis>
+	<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>
+
+	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 occurrence if there
+	is more than one header field of the same type).
+
+	<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>
+	
+	The following fields are mostly used internally by the server and
+	should be modified through dedicated functions only.
+	
+	<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's <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>REQUEST</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 locally 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>
+    </para>
+</section> <!-- sip_msg -->

+ 61 - 0
doc/serdev/sip_uri.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="sip_uri" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>Structure <structname>sip_uri</structname></title>
+    <para>
+	This structure represents parsed SIP URI.
+    </para>
+    <programlisting>
+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>
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    <structfield>user</structfield> - Username if found in the URI.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>passwd</structfield> - Password if found in
+		    the URI.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>host</structfield> - Hostname of the URI.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>params</structfield> - Parameters of the URI
+		    if any.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>headers</structfield> - See the SIP RFC.
+		</para>
+	    </listitem>
+	</itemizedlist>
+    </para>
+</section>

+ 66 - 0
doc/serdev/sr_module.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="sr_module" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>sr_module.c</filename> which is head of linked-list
+	of all loaded modules.
+    </para>
+    <para>
+	Detailed description of the structure follows:
+    </para>
+    <programlisting>
+struct sr_module{
+    char* path;
+    void* handle;
+    struct module_exports* exports;
+    struct sr_module* next;
+};
+    </programlisting>
+    <para>
+	<emphasis>Fields and their description:</emphasis>
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    <structfield>path</structfield> - Path to the module. This
+		    is the path you pass as parameter to
+		    <function>loadmodule</function> function in the config
+		    file.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>handle</structfield> - Handle returned by
+		    <function>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>

+ 810 - 0
doc/serdev/startup.xml

@@ -0,0 +1,810 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="ser_startup" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>The Server Startup</title>
+    <para>
+	The <function>main</function> function in file
+	<filename>main.c</filename> is the first function called upon server
+	startup. It's purpose is to initialize the server and enter main
+	loop. The server initialization will be described in the following
+	sections.
+    </para>
+    
+    <para>
+	Particular initialization steps are described in order in which they
+	appear in <function>main</function> function.
+    </para>
+    
+    <section id="signal_handlers">
+	<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 graceful shutdown, print server statistics and so on. There is
+	    only one signal handler function which is function
+	    <function>sig_usr</function> in file <filename>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="cmdline_parameters">
+	<title>Processing Command Line Parameters</title>
+	<para>
+	    SER utilizes the <function>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>
+	    SER contains a fast 32-bit parser. The parser uses pre-calculated
+	    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>init_hfname_parser</function> initializes
+	    hash table in header field name parser and function
+	    <function>init_digest_parser</function> initializes hash table in
+	    digest authentication parser. The parser's internals will be
+	    described later.
+	</para>
+    </section> <!-- parser-init -->
+    
+    <section id="malloc_init">
+	<title>Malloc Initialization</title>
+	<para>
+	    To make SER even faster we decided to re-implement memory
+	    allocation routines. The new <function>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>init_timer</function> initializes the timer
+	    subsystem. The function is called from <filename>main.c</filename>
+	    and can be found in <filename>timer.c</filename> The timer
+	    subsystem will be described later.
+	</para>
+	<warning>
+	    <para>
+		Timer subsystem must be initialized before config file is parsed !
+	    </para>
+	</warning>
+    </section> <!-- timer-init -->
+
+    <section id="fifo_init">
+	<title>FIFO Initialization</title>
+	<para>
+	    SER has built-in support for FIFO control. It means that the
+	    running server can accept commands over a FIFO special file (a
+	    named pipe). Function <function>register_core_fifo</function>
+	    initializes FIFO subsystem and registers basic commands, that are
+	    processed by the core itself. The function can be found in file
+	    <filename>fifo_server.c</filename>.
+	</para>
+	<para>
+	    The FIFO server will be described in another chapter.
+	</para>
+    </section> <!-- fifo-init -->
+    
+    <section id="builtin_modules">
+	<title>Built-in 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>
+	    immediately with the core. When the module is compiled in
+	    statically, the registration<footnoteref linkend="regfoot"/> must be
+	    performed during the server startup. Function
+	    <function>register_builtin_modules</function> does the job.
+	</para>
+    </section> <!-- builtin-mod-reg -->
+    
+    <section id="ser_configuration">
+	<title>Server Configuration</title>
+	<para>
+	    The server is configured through 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="lexical_analysis">
+	    <title>Lexical Analysis</title>
+	    <para>
+		Lexical analysis is 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. A 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>
+		Flex input file for the SER config file is in file
+		<filename>cfg.lex</filename>. The file is processed by flex
+		when the server is being compiled and the result is written in
+		file <filename>lex.yy.c</filename>. The output file contains
+		the scanner implemented in the 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 isn't conformable with
+		it's grammar, it is syntactically invalid and cannot be further
+		processed. In that case an error will be issued and the server
+		will be aborted.
+	    </para>
+	    <para>
+		There is a utility called yacc. 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 an IP address in the configuration file and
+		convert the address to its binary representation.
+	    </para>
+	    <para>For more information see yacc documentation.</para>
+	    <para>
+		yacc creates the parser when the server is being compiled from
+		the sources.  Input file for yacc is
+		<filename>cfg.y</filename>. The file contains grammar of the
+		config file along with actions that create the binary
+		representation of the file.  Yacc will write its result into
+		file <filename>cfg.tab.c</filename>. The file contains function
+		<function>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_structure">
+	    <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 step by step. The
+			config file must always contain one main "route"
+			statement and may contain several additional "route"
+			statements. 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 similar 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
+			functionality 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>loadmodule</function> and
+			<function>modparam</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_statement">
+		<title>Route Statement</title>
+		<para>The following grammar snippet describes how the route statement is constructed</para>
+		<programlisting>
+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 in which 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>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 the 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>forward</function> command,
+		    <function>mk_action</function> function (as specified in
+		    the grammar snippet above) will be called. The function
+		    creates a new structure with
+		    <structfield>type</structfield> field set to 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 <function>action</function>
+		    rule to <function>actions</function>
+		    rule. <function>Actions</function> rule will create linked
+		    list of all commands. The linked list will be then inserted
+		    into <structfield>rlist</structfield> table.  (Function
+		    <function>push</function> in rule
+		    <function>route_stm</function>).  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 array.
+		</para>
+		<para>
+		    When the core is about to execute route statement with
+		    number n, it will look in the array 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 step by
+		    step.
+		</para>
+		<para>
+		    Reply-Route statement is compiled in the same way. Main differences are:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				Reply-Route statement is executed when a SIP
+				<emphasis>REPLY</emphasis> comes (not ,SIP
+				<emphasis>REQUEST</emphasis>).
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				Only subset of commands is allowed in the
+				reply-route statement.  (See file
+				<filename>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_statement">
+		<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>
+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 an error and abort
+		    the server.
+		</para>
+	    </section> <!-- assign-stm -->
+	    
+	    <section id="module_statement">
+		<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 a shared object.  The
+			    shared object will be loaded using
+			    <function>dlopen</function>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>modparam</emphasis> - It is possible to
+			    configure a module using this command. The command
+			    accepts 3 parameters: <emphasis>module
+			    name</emphasis>, <emphasis>variable name</emphasis>
+			    and <emphasis>variable value</emphasis>.
+			</para>
+		    </listitem>
+		</itemizedlist>
+		<para>The following grammar snippet describes the module statement:</para>
+		<programlisting>
+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>loadmodule</function>
+		    command, it will execute statement in curly braces.  The
+		    statement will call <function>load_module</function>
+		    function.  The function will load the specified filename
+		    using <function>dlopen</function>.  If
+		    <function>dlopen</function> was successful, the server will
+		    look for <structname>exports</structname> structure
+		    describing the module's interface and register the
+		    module. For more details see <link
+		    linkend="module_interface">module section</link>.
+		</para>
+		<para>
+		    If the parser finds <function>modparam</function> command,
+		    it will try to configure the specified variable in the
+		    specified module. The module must be loaded using
+		    <function>loadmodule</function> before
+		    <function>modparam</function> for the module can be used !
+		    Function <function>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>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>daemonize</function> in file
+	    <filename>main.c</filename> for more details.  The function does
+	    the following:
+	</para>
+	<itemizedlist>
+	    <listitem>
+		<para>
+		    <emphasis>chroot</emphasis> is performed if necessary. That
+		    ensures that the server will have access to a particular
+		    directory and its subdirectories only.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    Server's working directory is changed if the new working
+		    directory was specified (usually it is /).
+		</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>mod_init</function>
+	    function. <function>mod_init</function> function of all loaded
+	    modules will be called now.
+	</para>
+    </section> <!-- module-init -->
+    
+    <section id="routing_list_fixing">
+	<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>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>strlen</function> every time it is called, but that
+	    is not a very good idea because <function>strlen</function> would
+	    be called every time a message is processed and that is not
+	    necessary.
+	</para>
+	<para>
+	    Instead of that the length of the string parameter could be
+	    pre-calculated upon server startup, saved and reused later. The
+	    processing of the request will be faster because
+	    <function>append_hf</function> doesn't need to call
+	    <function>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 if necessary.
+	</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>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 incoming 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>udp_init</function> in file
+	    <filename>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.
+	    <varname>dont_fork</varname> is a global variable defined in
+	    <filename>main.c</filename>.  We will describe both variants
+	    separately.
+	</para>
+
+	<section id="dont_fork">
+	    <title><varname>dont_fork</varname> variable 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 processing 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>
+			FIFO server will spawn another child if enabled. The
+			child will be processing all commands coming through
+			the fifo interface.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>If SNMP 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>main_loop</function> in
+		file <filename>main.c</filename>.
+	    </para>
+
+	    <itemizedlist>
+		<listitem>
+		    <para>Another child will be forked for the timer subsystem.</para>
+		</listitem>
+		<listitem>
+		    <para>
+			Initialize the FIFO server if enabled, this will fork
+			another child.  For more info about the FIFO server,
+			see section The FIFO server.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			Call <function>init_child(0).</function> The function
+			performs per-child specific initialization of all
+			loaded modules.  A module can be initialized though
+			<function>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 file descriptor), it cannot be done in
+			<function>mod_init</function>.  To make such
+			initialization possible, a module can export another
+			initialization function called
+			<function>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>init_child</function> wouldn't be called.
+		    </para>
+		    <para>
+			That would be bad, because
+			<function>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>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>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 children 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 the FIFO server. The FIFO
+		server needs another child to handle communication over FIFO
+		and thus another child will be created. The FIFO server will be
+		described in more detail later.
+	    </para>
+
+	    <para>
+		Then the main process will perform another fork for the timer
+		attendant. 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>pause</function> function until a signal comes and
+		call <function>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>init_child</function>
+		function. The function will sequentially call
+		<function>child_init</function> functions of all loaded
+		modules.
+	    </para>
+	    <para>
+		Because 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>mod_init</function> function, all the children would
+		share the same connection and locking would be necessary to
+		avoid conflicts. On the other hand if the connection was opened
+		in <function>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>udp_rcv_loop</function> function which contains the
+		main loop logic.
+	    </para>
+	    
+	</section> <!-- dont-fork-not-set -->
+    </section> <!-- forking -->
+</section>

+ 69 - 0
doc/serdev/str.xml

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="str" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title></title>
+
+    <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>strlen</function> because the function is
+	relatively slow. It must scan the whole string and find the first
+	occurrence 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>
+    <important>
+	<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>
+    </important>
+    
+    <para><emphasis><type>str</type> Type Declaration</emphasis></para>
+    <programlisting>
+struct _str{
+    char* s;
+    int len;
+};
+
+typedef struct _str str;		    
+    </programlisting>
+    
+    <para>
+	The declaration can be found in header file <filename>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 careful when using functions like
+	    <function>snprintf</function> that rely on the ending zero. You can
+	    print variable of type <type>str</type> this way:
+
+	    <programlisting>
+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>

+ 80 - 0
doc/serdev/to_body.xml

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="to_body" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+
+    <title>Structure <structname>to_body</structname></title>
+    <para>
+	The structure represents parsed To body. The structure is declared in
+	<filename>parse_to.h</filename> file.
+    </para>
+    <para><emphasis>Structure Declaration:</emphasis></para>
+    <programlisting>
+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>

+ 58 - 0
doc/serdev/to_parser.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="lump" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>To Header Field Parser</title>
+    <para>
+	Purpose of this parser is to parse body of To header field. The parser
+	can be found in file <filename>parse_to.c</filename> under
+	<filename>parser</filename> subdirectory.
+    </para>
+    <para>
+	Main function is <function>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>get_to</function> in file <filename>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>get_hdr_field</function> in file
+	<filename>msg_parser.c</filename>. The function first creates and
+	initializes an instance of <structname>to_body</structname> structure,
+	then calls <function>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>clean_hdr_field</function> in file
+	<filename>hf.c</filename> for more details.
+    </para>
+    <para>
+	See <xref linkend="to_body"/> for detailed description of the data
+	structure produced by this parser.
+    </para>
+</section>

+ 141 - 0
doc/serdev/via_body.xml

@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="via_body" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <title>The Server Startup</title>
+
+    <title>Structure <structname>via_body</structname></title>
+    <para>
+	The structure represents parsed Via header field. See file
+	<filename>parse_via.h</filename> under <filename>parser</filename>
+	subdirectory for more details.
+    </para>
+    <programlisting>
+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>
+	<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 "Via" or "v" in this case.
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>name</structfield> - Protocol name ("SIP" in
+		    this case).
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>version</structfield> - Protocol version (for
+		    example "2.0").
+		</para>
+	    </listitem>
+	    <listitem>
+		<para>
+		    <structfield>transport</structfield> - Transport protocol
+		    name ("TCP", "UDP" 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>
+    </para>
+</section>

+ 55 - 0
doc/serdev/via_parser.xml

@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4//EN"
+                      "file:///usr/share/sgml/docbook/dtd/xml/4/docbookx.dtd">
+
+<section id="via_parser" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <sectioninfo>
+	<revhistory>
+	    <revision>
+		<revnumber>$Revision$</revnumber>
+		<date>$Date$</date>
+	    </revision>
+	</revhistory>
+    </sectioninfo>
+    
+    <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>parse_via.c</filename> under
+	<filename>parser</filename> subdirectory.
+    </para>
+    <para>
+	Main function is <function>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>get_hdr_field</function> in file
+	<filename>msg_parser.c</filename>. The function first creates and
+	initializes an instance of <structname>via_body</structname> structure,
+	then calls <function>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>clean_hdr_field</function> in file
+	<filename>hf.c</filename> for more details.
+    </para>
+    <para>
+	Structure <structname>via_body</structname> is described in
+	<xref linkend="via_body"/>.
+    </para>
+</section>