浏览代码

minor documentation changes

Jiri Kuthan 22 年之前
父节点
当前提交
16e00a7dc0
共有 10 个文件被更改,包括 5774 次插入5715 次删除
  1. 32 21
      README-MODULES
  2. 801 0
      doc/seruser/apps.sgml
  3. 425 0
      doc/seruser/general.sgml
  4. 1478 0
      doc/seruser/intro.sgml
  5. 1480 0
      doc/seruser/operation.sgml
  6. 133 0
      doc/seruser/otherapps.sgml
  7. 1406 0
      doc/seruser/reference.sgml
  8. 16 5691
      doc/seruser/seruser.sgml
  9. 1 1
      doc/seruser/voicemail.sgml
  10. 2 2
      etc/ser.cfg

+ 32 - 21
README-MODULES

@@ -73,19 +73,6 @@ Maturity:   alpha
 Depends on: -
 Purpose:    Database emulation in plaintext files
 
-Name:       domain
-Owner:      jih
-Use:        experimental
-Maturity:   beta
-Depends on: mysql
-Purpose:    Local domain lists and related functions
-
-Name:       enum
-Owner:      jih
-Use:        experimental
-Maturity:   beta
-Depends on: -
-Purpose:    Enum support
 
 Name:       exec
 Owner:      jiri
@@ -102,7 +89,7 @@ Depends on: -
 Purpose:    Execution of external URI processing logic
 
 Name:       extcmd
-Owner:      jiri
+Owner:      bogdan
 Use:        experimental
 Maturity:   alpha
 Depends on: -
@@ -171,13 +158,6 @@ Maturity:   stable
 Depends on: -
 Purpose:    Printing messages to stdout
 
-Name:       radius_acc
-Owner:      ssi
-Use:        experimental
-Maturity:   beta
-Depends on: tm
-Purpose:    radius accounting
-
 Name:       registrar
 Owner:      janakj
 Use:        regular
@@ -254,3 +234,34 @@ Use:        experimental
 Maturity:   alpha
 Depends on: tm
 Purpose:    Voicemail interface
+
+Contributions
+-------------
+Name:       domain
+Owner:      jih
+Use:        experimental
+Maturity:   beta
+Depends on: mysql
+Purpose:    Local domain lists and related functions
+
+Name:       enum
+Owner:      jih
+Use:        experimental
+Maturity:   beta
+Depends on: -
+Purpose:    Enum support
+
+Name:       domain
+Owner:      jih
+Use:        experimental
+Maturity:   beta
+Depends on: -
+Purpose:    support for maintenance of multiple domains
+
+Name:		permissions
+Owner:		tirpi
+Use:		experimental
+Maturity:	beta
+Depends on:	-
+Purpose:	hosts.allow-like ACLs
+

+ 801 - 0
doc/seruser/apps.sgml

@@ -0,0 +1,801 @@
+    <chapter>
+	<title>Application Writing</title>
+	<para>
+	    <application moreinfo="none">ser</application> offers several
+	    ways to couple its functionality with applications. The coupling
+	    is bidirectional: <application moreinfo="none">ser</application>
+	    can utilize external applications and external applications can
+	    utilize <application moreinfo="none">ser</application>. 
+	    An example of the former direction would be an external program
+	    determining a least-cost route for a called destination  using 
+	    a pricing table. An example of the latter case
+	    is a web application for server provisioning.
+	    Such an application may want to send instant 
+	    messages, query all current user's locations and monitor server
+	    health. An existing web interface to <application moreinfo="none">ser</application>,
+	    <application moreinfo="none">serweb</application>, actually
+	    does all of it. 
+	</para>
+	<para>
+	    The easiest, language-independent way of using external logic 
+	    from <application moreinfo="none">ser</application> is provided
+	    by exec module. exec module allows <application moreinfo="none">ser</application>
+	    to start external programs on receipt of a request. The
+	    programs can execute arbitrary logic and/or affect routing of SIP
+	    requests. A great benefit of this programming method is it
+	    is language-independent. Programmers may use programming languages
+	    that are effective or with which they are best familiar.
+	    <xref linkend="usingexec"> gives additional examples illustrating 
+	    use of the exec module.
+	</para>
+	<para>
+	    Another method for extending <application moreinfo="none">ser</application>
+	    capabilities is to write new modules in C. This method takes
+	    deeper understanding of <application moreinfo="none">ser</application>
+	    internals but gains the highest flexibility. Modules can implement
+	    arbitrary brand-new commands upon which <application moreinfo="none">ser</application>
+	    scripts can rely on. Guidelines on module programming can be
+	    found in <application moreinfo="none">ser</application>
+	    programmer's handbook available from iptel.org website.
+	</para>
+	<para>
+	    To address needs of applications wishing to leverage
+	    <application moreinfo="none">ser</application>,
+	    <application moreinfo="none">ser</application> exports
+	    parts of its functionality via its built-in
+	    "Application FIFO server". This is a simple textual
+	    interface that allows any external applications
+	    to communicate with the server. It can be used to
+	    send instant messages, manipulate user contacts,
+	    watch server health, etc. Programs written in any
+	    language (PHP, shell scripts, Perl, C, etc.) can
+	    utilize this feature. How to use it is shown in
+	    <xref linkend="fifoserver">.
+	</para>
+
+
+	<section id="usingexec">
+	    <title>Using exec Module</title>
+	    <para>
+		
+		The easiest way is to couple <application moreinfo="none">ser</application>
+		with external applications via the <emphasis>exec</emphasis>
+		module. This module allows execution of logic and URI manipulation 
+		by external applications on request receipt. While very
+		simple, many useful services can be
+		implemented this way. External applications can be written in
+		any programming language and do not be aware of SIP at all.
+		<application moreinfo="none">ser</application> interacts with
+		the application via standard input/output and environment 
+		variables.
+		
+
+	    </para>
+	
+
+	    <para>
+		For example, an external shell script
+		may send an email whenever a request for a user arrives.
+	    </para>
+
+	    <example>
+		<title>Using exec: Step 1</title>
+		<programlisting format="linespecific">
+# send email if a request for user "jiri" arrives
+if (uri=~"^sip:jiri@") {
+     exec_msg("echo 'body: call arrived'|mail -s 'call for you' jiri");
+}
+		</programlisting>
+	    </example> <!-- step 1 -->
+	    <para>
+		In this example, the <command moreinfo="none">exec_msg</command> 
+		action starts an external shell. It passes a received SIP request
+		to shell's input. In the shell, <command>mail</command> command
+		is called to send a notification by e-mail.
+		The script however features several simplifications:
+		<orderedlist inheritnum="ignore" continuation="restarts">
+		    <listitem>
+			<para>
+			    The email notification does not tell who was calling.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    The logic is not general: it only supports one well-known user (jiri).
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    The logic is stateless. It will be executed on
+			    every retransmission.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    It is a script fragment not explaining the 
+			    context. This particular example may be for
+			    example used to report on missed calls.
+			</para>
+		    </listitem>
+		</orderedlist>
+		All of these simplifications are addressed step-by-step
+		in the following examples.
+	    </para>
+	    <example> <!-- step 2: who called me -->
+		<title>Using exec: Step 2, Who Called Me</title>
+		<para>
+		    This example shows how to display caller's address
+		    in email notification. The trick is easy: process
+		    request received on shell programm's input
+		    and grep From header field.
+		</para>
+		<programlisting format="linespecific">
+&execstep2;
+		</programlisting>
+		<para>
+			The following two figures show an example SIP request and
+			email notification generated on its receipt.
+			
+		    <screen format="linespecific">
+
+<![CDATA[
+INVITE sip:[email protected] SIP/2.0
+Via: SIP/2.0/UDP 195.37.77.100:5040
+Max-Forwards: 10
+From: "alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:[email protected]>
+Call-ID: [email protected]
+CSeq: 2 INVITE
+Contact: <sip:123.20.128.35:9315>
+Content-Type: application/sdp
+Content-Length: 451
+
+--- SDP payload snipped ---
+]]>
+
+		    </screen>
+		
+		    email received:
+		
+			<screen format="linespecific">
+<![CDATA[
+Date: Thu, 12 Dec 2002 14:25:02 +0100
+From: root <[email protected]>
+To: [email protected]
+Subject: request for you
+
+From: "alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+request received
+]]>
+		    </screen>
+		</para>
+		<para>
+		    There is another way to learn values of request
+		    header fields, simpler than use of <command moreinfo="none">grep</command>. 
+		    <application moreinfo="none">ser</application>
+		    parses header fields and passes their values in 
+		    environment variables. Their names correspond
+		    to header field names prefixed with "SIP_HF_".
+		<programlisting format="linespecific">
+# send email if a request for "jiri" arrives
+if (uri=~"^sip:jiri@") {
+     exec_msg("echo request received from $SIP_HF_FROM | mail -s 'request for you' jiri");
+};
+		</programlisting>
+		    Moreover, several other values are passed in environment
+		    variables. <varname>SIP_TID</varname> is a token uniquely identifying 
+		    transaction, to which the request belongs. <varname>SIP_DID</varname>
+		    includes to-tag, and is empty in requests creating a dialog.
+		    <varname>SIP_SRCIP</varname> includes IP address, from which the
+		    request was sent. <varname>SIP_RURI</varname> and <varname>SIP_ORURI</varname>
+		    include current request-uri and original request-uri respectively,
+		    <varname>SIP_USER</varname> and <varname>SIP_OUSER</varname> username
+		    parts of these. The following listing shows environment variables
+		    passed to a shell script on receipt of the previous message:
+		    <programlisting format="linespecific">
+<![CDATA[
+SIP_HF_MAX_FORWARDS=10
+SIP_HF_VIA=SIP/2.0/UDP 195.37.77.100:5040
+SIP_HF_CSEQ=2 INVITE
+SIP_HF_FROM="alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+SIP_ORUI=sip:[email protected]
+SIP_HF_CONTENT_LENGTH=451
+SIP_TID=3b6b8295db0835815847b1f35f3b29b8
+SIP_DID=
+SIP_RURI=iptel.org
+SIP_HF_TO=<sip:[email protected]>
+SIP_OUSER=jiri
+SIP_HF_CALLID=d10815e0-bf17-4afa-8412-d9130a793d96@213.20.128.35
+SIP_SRCIP=195.37.77.100
+SIP_HF_CONTENT_TYPE=application/sdp
+SIP_HF_CONTACT=<sip:123.20.128.35:9315>
+]]>
+		    </programlisting>
+				    
+		</para>
+	    </example> <!-- step 2, who called me -->
+
+
+	    <example>  <!-- step 3,  make the script work for anyone -->
+		<title>Using exec: step 3, Make The Script Work For Anyone</title>
+		<para>
+		    A drawback of the previous example is it works only
+		    for one well-known user: request URI is matched against
+		    his SIP address and notification is sent to his hard-wired email
+		    address. In real scenarios, one would like
+		    to enable such a service for all users without enumerating
+		    their addresses in the script. The missing piece
+		    is translation of user's SIP name to his email address.
+		    This information is maintained in subscriber profiles,
+		    stored in MySQL by <application moreinfo="none">ser</application>.
+		    To translate the username to email address, the executed script
+		    needs to query the MySQL database. That is what this example
+		    shows. First, an SQL query is constructed which looks up
+		    email address of user, for whom a request arrived. If the
+		    query does not return a valid email address, the script
+		    returns with an error status and <application moreinfo="none">ser</application>
+		    script replies with "user does not exist". Otherwise
+		    an email notification is sent.
+		
+		    <programlisting format="linespecific">
+&execstep3;
+		    </programlisting>
+		</para>
+	    </example> <!-- step 3 make the script work for anyone -->
+	    <example> <!-- step 4, stateful processing -->
+		<title>Adding Stateful Processing</title>
+		<para>
+		    The previously improved example still features a shortcoming.
+		    When a message retransmission arrives due to a nework
+		    mistake such as lost reply, the email notification is
+		    executed again and again. That happens because the script
+		    is stateless, i.e., no track of current transactions is
+		    kept. The script does not know whether a request is
+		    a new or a retransmitted one. Transaction management may
+		    be introduced by use of tm module as described in
+		    <xref linkend="statefulua">. In the script,
+		    <command moreinfo="none">t_newtran</command> is first
+		    called to absorb requests retransmission -- if they
+		    occur, script does not continue. Then, as in the previous
+		    example, an exec module action is called. Eventually,
+		    a reply is sent statefully.
+		    <note>
+			<para>
+			    Note carefuly: it is important that the stateful
+			    reply processing (<command moreinfo="none">t_reply</command>)
+			    is used as opposed to using stateless replies
+			    (<command moreinfo="none">sl_send_reply</command>).
+			    Otherwise, the outgoing reply would not affect
+			    transactional context and would not be resent on
+			    receipt of a request retransmission.
+			</para>
+		    </note>
+		    <programlisting format="linespecific">
+&execstep4;
+		    </programlisting>
+		    
+		</para>
+	    </example> <!-- step 4,  stateful processing -->
+	    <example> <!-- step 5, full exec use -->
+		<title>Full Example of exec Use</title>
+		<para>
+		    The last example iteration shows how to integrate the
+		    email notification on missed calls with the default
+		    <application moreinfo="none">ser</application> script
+		    (see <xref linkend="defaultscript">). It generates an
+		    email for every call invitation to an off-line user.
+		    <programlisting format="linespecific">
+&execstep5;
+		    </programlisting>
+		</para>
+		    
+		<para>
+		    Production "missed calls" services may want to 
+		    report on calls missed for other reasons than
+		    being off-line too. Particularly, users may wish to be
+		    reported calls missed due to call cancellation,
+		    busy status or a downstream failure. Such missed
+		    calls can be easily reported to syslog or mysql
+		    using the acc module (see <xref linkend="missedcalls">).
+		    The other, more general way, is to return to request
+		    processing on receipt of a negative reply.
+		    (see <xref linkend="replyprocessingsection">). Before
+		    a request is forwarded, it is labeled to be
+		    re-processed in a <command moreinfo="none">reply_route</command>
+		    on receipt of a negative reply -- this is what
+		    <command moreinfo="none">t_on_negative</command> action
+		    is used for. It does not matter what caused the transaction
+		    to fail -- it may be unresponsive downstream server,
+		    server responding with 6xx, or server sending a 487
+		    reply, because an INVITE was cancelled. When any such
+		    circumstances occur (i.e., transaction does not complete
+		    with a 2xx status code), <command moreinfo="none">reply_route</command>
+		    is entered.
+		</para>
+		<para>
+		    The following <application moreinfo="none">ser</application>
+		    script reports missed calls in all possible cases.
+		    It reports them when a user is off-line as well as when
+		    a user is on-line, but INVITE transaction does not complete
+		    successfully.
+		    <programlisting format="linespecific">
+&execstep5b;
+		    </programlisting>
+		</para>
+		
+	    </example> <!-- step 5, full exec use -->
+
+	</section> <!-- using exec -->
+
+	<section id="fifoserver">
+	    <title>Application FIFO Server</title>
+
+	    <para>
+	    Application FIFO server is a very powerful method to program
+	    SIP services. The most valuable benefit
+	    is it works with SIP-unaware applications
+	    written in any programming language. Textual nature of the
+	    FIFO interface allows for easy integration with a lot of
+	    existing programs. Today, <application moreinfo="none">ser</application>'s
+	    complementary web-interface, <application moreinfo="none">serweb</application>,
+	    written in PHP, leverages the FIFO interface when displaying
+	    and changing user location records stored in server's memory.
+	    It uses this interface to send instant messages too, without
+	    any knowledge of underlying <acronym>SIP</acronym> stack.
+	    Another application relying on the FIFO interface is 
+	    <application moreinfo="none">serctl</application>, <application moreinfo="none">ser</application>
+	    management utility. The command-line utility can browse
+	    server's in-memory user-location database, display 
+	    running processes and operational statistics.
+	    </para>
+	    <para>
+		The way the FIFO server works is similar to how 
+		<filename moreinfo="none">/proc</filename> filesystem works
+		on some operating systems. It provides a human-readable way
+		to access <application moreinfo="none">ser</application>'s
+		internals. Applications dump their requests into the FIFO
+		server and receive a status report when request processing
+		completes. <application moreinfo="none">ser</application>
+		exports a lot of its functionality located in both the
+		core and external modules through the FIFO server. 
+		</para>
+	    <para>
+		FIFO requests are formed easily. They begin with a command
+		enclosed in colons and followed by name of file or pipe (relative
+		to <filename moreinfo="none">/tmp/</filename> path), to which
+		a reply should be printed. The first request line may be
+		followed by additional lines with command-specific 
+		parameters. For example, the <command moreinfo="none">t_uac_dlg</command>
+		FIFO command for initiating a transaction allows 
+		to pass additional header fields and message body to
+		a newly created transaction. Each request is terminated by
+		an empty line. Whole requests must be sent by applications
+		atomically in a single batch to avoid mixing with
+		requests from other applications. Requests are sent to
+		pipe at which <application moreinfo="none">ser</application>
+		listens (filename configured by the <varname>fifo</varname> config
+		file option).
+	    </para>
+	    <para>
+		An easy way to use the FIFO interface is via the
+		<application moreinfo="none">serctl</application>
+		command-line tool. When called along with "fifo",
+		FIFO command name, and optional parameters, the tool
+		generates a FIFO request and prints request result.
+		The following example shows use of this tool with
+		the <command moreinfo="none">uptime</command> and
+		<command moreinfo="none">which</command> commands.
+		<command moreinfo="none">uptime</command> returns
+		server's running time, <command moreinfo="none">which</command>
+		returns list of available FIFO commands. Note that only
+		the built-in FIFO command set is displayed as no modules
+		were loaded in this example.
+		<example>
+		    <title>Use of <application moreinfo="none">serctl</application> 
+		    to Access FIFO Server</title>
+		    <programlisting format="linespecific">
+[jiri@cat test]$ serctl fifo uptime
+Now: Fri Dec  6 17:56:10 2002
+Up Since: Fri Dec  6 17:56:07 2002
+Up time: 3 [sec]
+
+[jiri@cat test]$ serctl fifo which
+ps
+which
+version
+uptime
+print
+		    </programlisting>
+		</example>
+		The request which the <application moreinfo="none">serctl</application>
+		command-line tool sent to FIFO server looked like this:
+		<example>
+		    <title><command moreinfo="none">uptime</command> FIFO Request</title>
+		    <programlisting format="linespecific">
+:uptime:ser_receiver_1114
+		    </programlisting>
+		</example>
+		This request contains no parameters and consists only of
+		command name enclosed in colons and name of file, to which
+		a reply should be printed. FIFO replies consist of a status
+		line followed by optional parameters. The status line consists,
+		similarly to <acronym>SIP</acronym> reply status, of 
+		a three-digit status code and a reason phrase. Status codes
+		with leading digit 2 (200..299) are considered positive,
+		any other values indicate an error. For example, FIFO server
+		returns "500" if execution of a non-existing FIFO command is 
+		requested.
+		<example>
+		    <title>FIFO Errors</title>
+		    <programlisting format="linespecific">
+[jiri@cat sip_router]$ serctl fifo foobar
+500 command 'foobar' not available
+		    </programlisting>
+		</example>
+
+		<example>
+		    <title>Showing User Contacts Using serctl</title>
+		    <para>
+			Another example of use of FIFO is accessing server's
+			in-memory user location database. That's a very powerful
+			feature: web applications and other tools can use it
+			to gain users access to the database. They can add new
+			contacts (like permanent gateway destinations), remove
+			and review their whereabouts. The example here utilizes
+			FIFO command <command>ul_show_contact</command> to
+			retrieve current whereabouts of user "jiri".
+			<programlisting>
+<![CDATA[
+[jiri@fox ser]$ serctl fifo ul_show_contact location jiri
+<sip:195.37.78.160:14519>;q=0.00;expires=1012
+]]>
+			</programlisting>
+		    </para>
+		</example>
+	    </para>
+	    <para>
+		The user location example demonstrates an essential feature
+		of the FIFO server: extensibility. It is able to export new 
+		commands implemented in new modules.
+		Currently, usrloc module exports FIFO
+		commands for maintaining in-memory user location
+		database and tm module exports FIFO commands for
+		management of SIP transactions. See the 
+		example in 
+		<filename moreinfo="none">examples/web_im/send_im.php</filename>
+		for how to initiate a SIP transaction
+		(instant message)
+		from a PHP script via the FIFO server. This example
+		uses FIFO command 
+		<command moreinfo="none">t_uac_dlg</command>. The command
+		is followed by parameters: header fields and 
+		message body. The same FIFO command can be used from
+		other environments to send instant messages too. The
+		following example shows how to send instant messages
+		from a shell script.
+		<example>
+		    <title>Sending IM From Shell Script</title>
+		    <programlisting format="linespecific">
+#!/bin/sh
+#
+# call this script to send an instant message; script parameters
+# will be displayed in message body
+#
+# paremeters mean: message type, request-URI, outbound server is
+# left blank ("."), required header fields From and To follow,
+# then optional header fields terminated by dot and optional
+# dot-terminated body
+
+cat &gt; /tmp/ser_fifo &lt;&lt;EOF
+:t_uac_dlg:hh
+NOTIFY
+sip:[email protected]
+.
+From: sip:[email protected]
+To: sip:[email protected]
+foo: bar_special_header
+x: y
+p_header: p_value
+Contact: &lt;sip:[email protected]:9&gt;
+Content-Type: text/plain; charset=UTF-8
+.
+Hello world!!!! $@
+.
+EOF
+		    </programlisting>
+		</example>
+		</para>
+	    <example>
+		<title>Manipulation of User Contacts</title>
+		<para>
+		    The following example shows use of FIFO server to change 
+		    user's contacts. This may be very practical, if for example
+		    a user wishes to set up his cell phone number as his temporary
+		    contact. The cell phone, which is behind a PSTN gateway, cannot
+		    register automatically using SIP. The user needs to set 
+		    forwarding manually through some convenient web interface.
+		    The web interface needs to have the ability to upload new user's
+		    contacts to <application moreinfo="none">ser</application>.
+		    This is what the <command moreinfo="none">ul_add</command> FIFO
+		    command is good far. Paremeterized by user's name, table name,
+		    expiration time and wight, it allows external applications to
+		    introduce new contacts to server's in-memory user location table.
+		</para>
+		<para>
+		    The example is borrowed from <application moreinfo="none">serweb</application>,
+		    <application moreinfo="none">ser</application>'s web 
+		    PHP-written interface.
+		    It consists of a short "stub" function which carries out
+		    all mechanics of FIFO communication and of forming the FIFO
+		    request.
+		</para>
+		<programlisting format="linespecific">
+<![CDATA[
+
+/* construct and send a FIFO command; the command parameters $sip_address, 
+   $expires are PHP variables originating from an HTML form
+ */
+	$fifo_cmd=":ul_add:".$config->reply_fifo_filename."\n".
+		$config->ul_table."\n".			//table
+		$user_id."\n".		//username
+		$sip_address."\n".				//contact
+		$expires."\n".					//expires
+		$config->ul_priority."\n\n";		//priority
+		$message=write2fifo($fifo_cmd, $errors, $status);
+
+/* .......... snip .................. */
+
+/* this is the stub function for communicating with FIFO server.
+   it dumps a request to FIFO server, opens a reply FIFO and
+   reads server's reply from it
+*/
+function write2fifo($fifo_cmd, &$errors, &$status){
+	global $config;
+
+	/* open fifo now */
+	$fifo_handle=fopen( $config->fifo_server, "w" );
+	if (!$fifo_handle) {
+		$errors[]="sorry -- cannot open fifo"; return;
+	}
+	
+	/* create fifo for replies */
+	@system("mkfifo -m 666 ".$config->reply_fifo_path );
+
+	/* add command separator */
+	$fifo_cmd=$fifo_cmd."\n";
+	
+	/* write fifo command */
+	if (fwrite( $fifo_handle, $fifo_cmd)==-1) {
+	    @unlink($config->reply_fifo_path);
+	    @fclose($fifo_handle);
+		$errors[]="sorry -- fifo writing error"; return;
+	}
+	@fclose($fifo_handle);
+	
+	/* read output now */
+	@$fp = fopen( $config->reply_fifo_path, "r");
+	if (!$fp) {
+	    @unlink($config->reply_fifo_path);
+		$errors[]="sorry -- fifo reading error"; return;
+	}
+
+	$status=fgetS($fp,256);
+	if (!$status) {
+	    @unlink($config->reply_fifo_path);
+		$errors[]="sorry -- fifo reading error"; return;
+	}
+	
+	$rd=fread($fp,8192);
+	@unlink($config->reply_fifo_path);
+	
+	return $rd;
+}
+]]>		   
+		</programlisting>
+	    </example>
+	    <para>
+		See
+		<xref linkend="fiforeference"> for a complete listing
+		of FIFO commands available with current 
+		<application moreinfo="none">ser</application>
+		distribution.
+	    </para>
+	    <section>
+		<title>Advanced Example: Click-To-Dial</title>
+		<para>
+		    A very useful SIP application is phonebook with
+		    "click-to-dial" feature. It allows users to keep their 
+		    phonebooks on the web and dial by clicking on an entry. 
+		    The great advantage is that you can use the phonebook 
+		    alone with any phone you have. If you temporarily use 
+		    another phone, upgrade it permanently with another make, 
+		    or use multiple phones in parallel, your phonebook will 
+		    stay with you on the web. You just need to click an entry 
+		    to initiate a call. Other scenario using "click-to-dial"
+		    feature includes "click to be connected with our
+		    sales representative".
+		</para>
+		<para>
+		    There are basically two ways how to build such a feature:
+		    distributed and centralized. We prefer the distributed
+		    approach since it is very robust and leight-weighted.
+		    The "click-to-dial" application just needs to instruct
+		    the calling user to call a destination and that's it.
+		    (That's done using "REFER" method.)
+		    Then, the calling user takes over whereas the initating
+		    application disappears from signaling and
+		    is no longer involved in subsequent communication. Which
+		    is good because such a simple design scales well. 
+		</para>
+		<para>
+		    The other design alternative is use of a B2BUA 
+		    <footnote>
+			<para>
+			    See <filename moreinfo="none">
+				draft-ietf-sipping-3pcc-02.txt 
+			    </filename>  for more details.
+			</para>
+		    </footnote>
+		    which acts as a "middleman" involved in signaling during the
+		    whole session. It is complex: ringing needs to be achieved
+		    using a media server, it introduces session state,
+		    mangling of SIP payloads, complexity when QoS reservation
+		    is used and possibly other threats which result from 
+		    e2e-unfriendly design. The only benefit
+		    is it works even for poor phones which do not support
+		    REFER -- which should not matter because you do not wish
+		    to buy such.
+		</para>
+		<para>
+		    So how does "distributed click-to-dial" application
+		    work? It is simple. The core piece is sending a REFER
+		    request to the calling party. REFER method is typically
+		    used for call transfer and it means "set up a call 
+		    to someone else". 
+		    </para>
+		<para>
+		    There is an issue -- most phones
+		    don't accept unsolicited REFER. If a malicious
+		    user made your phone to call thirty destinations without
+		    your agreement, you would certainly not appreciate it.
+		    The workaround is that first of all the click-to-dial
+		    application gives you a "wrapper call". If you accept it, 
+		    the application will send a REFER which will be considered
+		    by the phone as a part of approved communication and
+		    granted. Be aware that without cryptography, 
+		    security is still weak. Anyone who saw an INVITE can 
+		    generate an acceptable REFER.
+		    <example>
+			<title>Call-Flow for Click-To-Dial Using REFER</title>
+
+			<programlisting format="linespecific">
+
+        CTD                  Caller               Callee
+            #1 INVITE
+            ----------------->
+                             ...
+                             caller answers
+            #2 200
+            <-----------------
+            #3 ACK
+            ----------------->
+            #4 REFER
+            ----------------->
+            #5 202
+            <-----------------
+            #6 BYE
+            ----------------->
+            #7 200
+            <-----------------
+                                  #8 INVITE
+                                  ------------------>
+                                  #9 180 ringing
+                                  <------------------
+
+
+#1 click-to-dial (CTD) is started and the "wrapper call" is initiated
+INVITE caller
+From: controller
+To: caller
+SDP: on hold
+
+#2 calling user answes
+200 OK
+From: controller
+To: caller
+
+#3 CTD acknowledges
+ACK caller
+From controller
+To: caller
+
+#4 CTD initiates a transfer
+REFER caller
+From: controller
+To: caller
+Refer-To: callee
+Refered-By: controller
+
+#5 caller confirms delivery of REFER
+202 Accepted
+From: controller
+To: caller
+
+#6 CTD terminates the wrapper call -- it is no longer needed
+BYE caller
+From: controller
+To: caller
+
+#7 BYE is confirmed
+200 Ok
+From: controller
+To: caller
+
+#8 caller initates transaction solicited through REFER
+INVITE callee
+From: caller
+To: callee
+Referred-By: controller
+
+#9 that's it -- it is now up to callee to answer the INVITE
+180 ringing
+From: caller
+To: callee
+			</programlisting>
+
+		    </example>
+		</para>
+		<para>
+		    Implementation of this scenario is quite
+		    straight-forward: you initiate INVITE, BYE and
+		    REFER transaction.
+
+
+
+		    The largest amount of code
+		    is spent with getting dialog processing right.
+		    The subsequent BYE and REFER transactions need to
+		    be build using information learned from the reply
+		    to INVITE: Contact header field, To-tag and Route
+		    set. That's what the function 
+		    <function moreinfo="none">filter_fl</function>
+		    is used for. The "main" part just initiates
+		    each of the transactions, waits for its completion
+		    and proceeds to the next one until BYE is over.
+		    Source code of the example written in Bourne shell
+		    is available in source distrubtion, in 
+		    <filename moreinfo="none">examples/ctd.sh</filename>.
+		    A PHP implementation exists as well.
+		</para>
+		<example>
+		    <title>Running the CTD Example</title>
+		    <programlisting format="linespecific">
+[jiri@cat examples]$ ./ctd.sh 
+destination unspecified -- taking default value sip:[email protected]
+caller unspecified -- taking default value sip:[email protected]
+invitation succeeded
+refer succeeded
+bye succeeded
+		    </programlisting>
+		</example>
+	    </section> <!-- click-to-dial -->
+<!-- for some reason, this does not work :-(
+
+		<example>
+		    <title>Initiating a SIP Transaction from PHP via FIFO</title>
+
+
+		    <programlisting format="linespecific">
+			<textobject>
+			    <textdata fileref="../../examples/web_im/send_im.php" format="linespecific">
+			</textobject>
+			    
+		    </programlisting>
+
+		    
+		</example>
+-->
+
+	</section> <!-- FIFO server -->
+    </chapter>
+

+ 425 - 0
doc/seruser/general.sgml

@@ -0,0 +1,425 @@
+    <chapter id="general">
+	<title>General Information</title>
+	<section id="aboutser">
+	    <title>About <acronym>SIP</acronym> Express Router (<acronym>SER</acronym>)</title>
+	    <para>
+		SIP Express Router (<acronym>SER</acronym>) is an industrial-strength, free VoIP 
+		server based on the Session Initiation Protocol (<acronym>SIP</acronym>, RFC3261). 
+		It is engineered to power <acronym>IP</acronym> telephony infrastructures up to large 
+		scale. The server keeps track of users, sets up VoIP sessions, 
+		relays instant messages and creates space for new plug-in applications. 
+		Its proven interoperability guarantees seamless integration with 
+		components from other vendors, eliminating the risk of a single-vendor 
+		trap. It has successfully participated in various interoperability 
+		tests in which it worked with the products of other leading <acronym>SIP</acronym> vendors.
+	    </para>
+	    <para>
+		The <acronym>SIP</acronym> Express Router enables a flexible plug-in model for new 
+		applications: Third parties can easily link their plug-ins with 
+		the server code and provide thereby advanced and customized services. 
+		In this way, plug-ins such as <acronym>SNMP</acronym> support, RADIUS accounting,
+		or SMS gateway have already been developed and are provided as 
+		advanced features. Other modules are underway: Presence server,
+		firewall control, and more.
+	    </para>
+	    <para>
+		Its performance and robustness allows it to serve millions of users 
+		and accommodate needs of very large operators. With a $3000 dual-CPU PC, the 
+		<acronym>SIP</acronym> Express Router is able to power <acronym>IP</acronym> telephony services in an area 
+		as large as the Bay Area during peak hours. Even on an IPAQ <acronym>PDA</acronym>, the server 
+		withstands 150 calls per second (<acronym>CPS</acronym>)! The server has been powering our 
+		iptel.org free <acronym>SIP</acronym> site withstanding heavy daily load that is further 
+		increasing with the popularity of Microsoft's Windows Messenger.  
+	    </para>
+	    <para>
+		The <acronym>SIP</acronym> Express Router is extremely configurable to allow the creation of 
+		various routing and admission policies as well as setting up new and 
+		customized services. Its configurability allows it to serve many roles: 
+		network security barrier, application server, or <acronym>PSTN</acronym> gateway guard for 
+		example.
+	    </para>
+	    <para>
+		<application moreinfo="none">ser</application> can be also
+		used with contributed applications. Currently, 
+		<application moreinfo="none">serweb</application>, a
+		<application moreinfo="none">ser</application> web interface,
+		and <application moreinfo="none">SIPSak</application>
+		diagnostic tool are available. Visit our site, 
+		<ulink url="http://www.iptel.org/">http://www.iptel.org/</ulink>, 
+                for more information on contributed packages.
+	    </para>
+	</section> 
+
+	<section id="aboutiptel">
+	    <title>About iptel.org</title>
+	    <para>
+		iptel.org is a know-how company spun off from Germany's national 
+		research company FhG Fokus. One of the first <acronym>SIP</acronym> implementations ever, 
+		low-QoS enhancements, interoperability tests and VoIP-capable firewall 
+		control concepts are examples of well-known FhG's work.
+	    </para>
+	    <para>
+		iptel.org continues to keep this know-how leadership in <acronym>SIP</acronym>. 
+		The access rate of the company's site, a well-known source of 
+		technological information, is a best proof of interest. Thousands 
+		of hits come every day from the whole Internet.
+	    </para>
+	    <para>
+		The iptel.org site, powered by SER, offers SIP services on the public 
+		Internet. Feel free to apply for a free SIP account at
+		<ulink url="http://www.iptel.org/user/">http://www.iptel.org/user/
+		</ulink>
+	    </para>
+
+	    
+	</section> <!-- iptel -->
+	<section id="serfeatures">
+	    <title>Feature List</title>
+	    <para>
+		Based on the latest standards, the <acronym>SIP</acronym> Express Router (<acronym>SER</acronym>) includes 
+		support for registrar, proxy and redirect mode. Further it acts as 
+		an application server with support for instant messaging and 
+		presence including a <acronym>2G/SMS</acronym> and Jabber gateway, a call control policy 
+		language, call number translation, private dial plans and accounting, 
+		authorization and authentication (<acronym>AAA</acronym>) services. <application>SER</application> runs on Sun/Solaris, 
+		PC/Linux, PC/BSD, IPAQ/Linux platforms and supports  both <acronym>IPv4</acronym> and <acronym>IPv6</acronym>. 
+		Hosting multiple domains and database redundancy is supported.
+	    </para>
+	    <para>
+		Other extensions are underway: presence server, firewall control and more.
+	    </para>
+	    <para>
+		<application>ser</application> has been carefully engineered with the following 
+		design objectives in mind:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>Speed</emphasis> - With <application>ser</application>, 
+			    thousands of calls per seconds are achievable 
+			    even on low-cost platforms. This competitive capacity allows 
+			    setting up networks which are inexpensive and easy to manage 
+			    due to low number of devices required. The processing capacity 
+			    makes dealing with many stress factors easier. The stress
+			    factors may include but are not limited to broken configurations and implementations,
+			    boot avalanches on power-up, high-traffic applications such as presence, 
+			    redundancy replications and denial-of-service attacks.
+			</para>
+			<para> The speed has been achieved by extensive code optimization, use of customized code, 
+			    <acronym>ANSI C</acronym> combined with assembly instructions and leveraging latest 
+			    <acronym>SIP</acronym> improvements. When powered by a dual-CPU Linux PC, 
+			    <application>ser</application> is able to process thousands of calls per second,
+			    capacity needed to serve call signaling demands of Bay Area population.
+			   
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>Flexibility</emphasis> - <application>SER</application> allows its users 
+			    to define its behavior. 
+			    Administrators may write textual scripts which determine <acronym>SIP</acronym> routing 
+			    decisions, the main job of a proxy server. They may use the script to 
+			    configure numerous parameters and introduce additional logic. For example, 
+			    the scripts can determine for which destinations record routing should be 
+			    performed, who will be authenticated, which transactions should be processed 
+			    statefully, which requests will be proxied or redirected, etc.
+			</para>
+
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>Extensibility</emphasis> - <application>SER</application>'s extensibility allows linking of 
+			    new C code to ser to 
+			    redefine or extend its logic. The new code can be developed independently 
+			    on <application>SER</application> core and linked to it in run-time. The concept is similar to 
+			    the module concept known for example in Apache Web server. Even such essential parts such 
+			    as transaction management have been developed as modules to keep the <application>SER</application> core 
+			    compact and fast.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				Portability.
+			    </emphasis>
+			    <application>ser</application> has been written in ANSI C. It has been extensively tested 
+			    on PC/Linux and Sun/Solaris. Ports to BSD and IPAQ/Linux exist.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>			   
+				Interoperability. 
+			</emphasis>
+			<application>ser</application> is based on the open <acronym>SIP</acronym> standard. 
+			    It has undergone extensive tests with products of other vendors both in iptel.org
+			    labs and in the SIP Interoperability Tests (SIPIT). <application>ser</application> 
+			    powers the public iptel.org site 24 hours a day, 356 days a year 
+			    serving numerous SIP implementations using this site.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>Small size.</emphasis>
+			    Footprint of the core is 300k, add-on modules take up to 630k.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	</section> <!-- serfeatures -->
+
+	<section id="usecases">
+	    <title>Use Cases</title>
+	    <para>
+		This section illustrates the most frequent uses of SIP. In all these scenarios, 
+		the SIP Express Router (SER) can be easily deployed as the glue connecting all 
+		SIP components together, be it soft-phones, hard-phones, PSTN gateways or any other 
+		SIP-compliant devices.
+	    </para>
+	    <section>
+		<title>Added-Value ISP Services</title>
+		<para>
+		    To attract customers, ISPs frequently offer applications bundled with IP access. 
+		    With SIP, the providers can conveniently offer a variety of services running on top 
+		    of a single infrastructure. Particularly, deploying VoIP and instant messaging and 
+		    presence services is as easy as setting up a SIP server and guiding customers to use 
+		    Windows Messenger. Additionally, the ISPs may offer advanced services such as PSTN 
+		    termination, user-driven call handling or unified messaging all using the same infrastructure.
+		</para>
+		<para>
+		    SIP Express Router has been engineered to power large scale networks: its capacity can deal 
+		    with large number of customers under high load caused by modern applications. Premium 
+		    performance allows deploying a low number of boxes while keeping investments and operational 
+		    expenses extremely low. ISPs can offer SIP-based instant messaging services and interface
+		    them to other instant messaging systems (Jabber, SMS). VoIP can be easily integrated along
+		    with added-value services, such as voicemail.
+		</para>
+	    </section> <!-- Added-value ISP -->
+	    <section>
+		<title>PC2Phone</title>
+		<para>
+		    Internet Telephony Service Providers (ITSPs) offer the service of interconnecting 
+		    Internet telephony users using PC softphone or appliances to PSTN. Particularly with 
+		    long-distance and international calls, competitive pricing can be achieved by 
+		    routing the calls over the Internet.
+		</para>
+		<para>
+		    SIP Express Router can be easily configured to serve pc2phone users, distribute
+		    calls to geographically appropriate PSTN gateway, act as a security barrier and keep 
+		    track of charging. 
+		</para>
+	    </section>
+	    <section>
+		<title>PBX Replacement</title>
+		<para>
+		    Replacing a traditional PBX in an enterprise can achieve reasonable 
+		    savings. Enterprises can deploy a single infrastructure for both voice 
+		    and data and bridge distant locations over the Internet. Additionally, they can 
+		    benefit of integration of voice and data.
+		</para>
+		<para>
+		    The SIP Express Router scales from SOHOs to large, international enterprises. 
+		    Even a single installation on a common PC is able to serve VoIP signaling of any 
+		    world's enterprise. Its policy-based routing language makes implementation of numbering 
+		    plans of companies spread across the world very easy. ACL features allow for protection of 
+		    PSTN gateway from unauthorized callers.
+		</para>
+		<para>
+		    SIP Express Router's support for programmable routing and accounting efficiently allows for 
+		    implementation of such a scenario.
+		</para>
+	    </section>
+	</section> <!-- Use Cases -->
+	<section id="aboutsip">
+	    <title>About SIP Technology</title>
+	    <para>
+		The SIP protocol family is the technology which integrates services. 
+		With SIP, Internet users can easily contact each other; figure out 
+		willingness to have a conversation and couple different applications such as VoIP, video 
+		and instant messaging. Integration with added-value services is seamless and easy. Examples 
+		include integration with web (click-to-dial), E-mail (voice2email, UMS), and PSTN-like 
+		services (conditional forwarding).
+	    </para>
+	    <para>
+		The core piece of the technology is the Session Initiation Protocol (SIP, RFC3261) standardized by IETF. 
+		Its main function is to establish communication sessions between users connected to the public 
+		Internet and identified by e-mail-like addresses. One of SIP's greatest features is its transparent 
+		support for multiple applications: the same infrastructure may be used for voice, video, gaming 
+		or instant messaging as well as any other communication application.
+	    </para>
+	    <para>
+		There are numerous scenarios in which SIP is already deployed: PBX replacement allows for 
+		deployment of single inexpensive infrastructure in enterprises; PC-2-phone long-distance 
+		services (e.g., Deltathree) cut callers long-distance expenses; instant messaging offered 
+		by public severs (e.g., iptel.org) combines voice and text services with presence information. 
+		New deployment scenarios are underway: SIP is a part of UMTS networks and research publications 
+		suggest the use of SIP for virtual home environments or distributed network games.
+	    </para>
+	</section> <!-- about sip -->
+	<section id="serlimitations">
+	    <title>Known SER Limitations</title>
+	    <para>
+		The following items are not part of current distribution and are planned for next releases:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    Script processing of multiple branches on forking
+			</para>
+
+			<warning>
+			    <para>
+				<application>ser</application>'s request processing language allows 
+				to make request decisions based on current URI. 
+				When a request if forked to multiple destinations, only the first branch's URI is used as 
+				input for script processing. This might lead to unexpected results. Whenever a URI resolves 
+				to multiple different next-hop URIs, only the first is processed which may result in handling 
+				not appropriate for the other branch. For example, a URI might resolve to an IP phone SIP 
+				address and PSTN gateway SIP address. If the IP phone address is the first, then script 
+				execution ignores the second branch. If a script includes checking gateway address in
+				request URI, the checks never match. That might result in ignoring of 
+				gateway admission control rules or applying them unnecessarily to non-gateway 
+				destinations.
+			    </para>
+			</warning>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	    <para>
+		List of known bugs is publicly available at the 
+		<application>ser</application> webpage at
+		<ulink url="http://www.iptel.org/ser/">
+		    http://www.iptel.org/ser/
+		</ulink>. See the "ISSUES" link.
+	    </para>
+	</section> <!-- limitations -->
+	<section id="licensing">
+	    <title>Licensing</title>
+	    <para>
+		<application>ser</application> is freely available under terms and
+		conditions of the GNU General Public License.
+	    </para>	
+	    <!-- COPYING -->
+	    <screen>
+	    	    &gpllicense;
+	    </screen>
+	    
+	</section>
+	<section id="support">
+	    <title>Obtaining Technical Assistance</title>
+	    <para>
+		We offer best-effort free support for <application>ser</application>.
+		"best-effort" means that we try to solve your problems via email
+		as soon as we can, subject to available manpower. If you need
+		commercial support, contact [email protected].
+	    </para>
+	    <para>
+		To receive feedback to your inquiries, we recommend you to subscribe
+		to the <emphasis>serusers</emphasis> mailing list and post your
+		queries there. This mailing list is set up for mutual help by
+		the community of <application>ser</application> users and developers.
+	    </para>
+	    <itemizedlist>
+		<title>Mailing List Instructions</title>
+		<listitem>
+		    <para>
+			Public archives and subscription form:
+			<ulink url="http://mail.iptel.org/mailman/listinfo/serusers">
+			    http://mail.iptel.org/mailman/listinfo/serusers
+			</ulink>			
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			To post, send an email to [email protected]
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			If you think you encountered an error, please submit the
+			following information to avoid unnecessary round-trip times:			
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    Name and version of your operating system --
+				    you can obtain it by calling
+				    <command>uname -a</command>
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <application>ser</application> distribution: 
+				    release number and package				    
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <application>ser</application> build -- 
+				    you can obtain it by calling 
+				    <command moreinfo="none">ser -V</command>
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    Your <application>ser</application> configuration file
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <application>ser</application> logs -- with default settings
+				    few logs are printed to <command>syslog</command> facility which
+				    typically dumps them to 
+				    <filename moreinfo="none">/var/log/messages</filename>. To 
+				    enable detailed logs dumped to <filename>stderr</filename>,
+				    apply the following configuration options: <command moreinfo="none">
+				    debug=8, log_stderror=yes, fork=no</command>.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    Captured SIP messages -- you can obtain them 
+				    using tools such as <application>ngrep</application>
+				    or <application moreinfo="none">ethereal</application>.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		    
+		</listitem>
+	    </itemizedlist>	    
+	
+	    <para>
+		If you are concerned about your privacy and do not wish your
+		queries to be posted and archived publicly, you may post to
+		[email protected]. E-mails to this address are only forwarded
+		to iptel.org's <application>ser</application> development team.
+		However, as the team is quite busy you should not be surprised
+		to get replies with considerable delay.
+
+	    </para>
+	</section>
+        
+	<section id="moreinfo">
+	    <title>More Information</title>
+	    <para>
+		Most up-to-date information including latest and most complete version
+		of this documentation is always available at our website,
+		<ulink url="http://www.iptel.org/ser/">http://www.iptel.org/ser/</ulink>.
+		The site includes links to other important information about
+		<application moreinfo="none">ser</application>, such
+		as installation guidelines (INSTALL), download links,
+		development pages, programmer's manual, etc.
+	    </para>
+	    <para>
+		A SIP tutorial (slide set) is available at 
+		<ulink url="http://www.iptel.org/sip/">http://www.iptel.org/sip/</ulink> .
+	    </para>
+	</section> <!-- info -->
+
+	<section>
+	    <title>Release Notes</title>
+	    <literallayout format="linespecific" class="normal">
+&releasenotes;
+	    </literallayout>
+	</section> <!-- release notes -->
+
+
+    </chapter> <!-- general -->

+ 1478 - 0
doc/seruser/intro.sgml

@@ -0,0 +1,1478 @@
+    <chapter>
+	<title>Introduction to SER</title>
+
+	<section id="requestrouting">
+	    <title>Request Routing and SER Scripts</title>
+	    <para>
+		The most important concept of every SIP server is that of
+		request routing. The request routing logic determines the next
+		hop of a request. It can be for example used to implement user 
+		location service or enforce static routing to a gateway. Real-world
+		deployments actually ask for quite complex routing logic, which
+		needs to reflect static routes to PSTN gateways, dynamic routes
+		to registered users, authentication policy, capabilities of
+		SIP devices, etc.
+	    </para>
+	    <para>
+		SER's answer to this need for routing flexibility is a routing
+		language, which allows administrators to define the SIP request
+		processing logic in a detailed manner. They can for example easily
+		split SIP traffic by method or destination, perform user location, 
+		trigger authentication, verify access permissions, and so on.
+	    </para>
+	    <para>
+		The primary building block of the routing language are <emphasis>actions</emphasis>. 
+		There are built-in actions (like <command>forward</command> for stateless forwarding
+		or <command>strip</command> for stripping URIs) as 
+		well as external actions imported from shared library modules. All actions can 
+		be combined in compound actions by enclosing them in braces, 
+		e.g. <command>{a1(); a2();}</command>. 
+		Actions are aggregated in one or more <emphasis>route blocks</emphasis>.
+		Initially, only the default routing block denoted by <command>route[0]</command>
+		is called. Other routing blocks can be called by the action
+		<command>route(blocknumber)</command>, recursion is permitted.
+		The language includes <emphasis>conditional statements</emphasis>. 
+	    </para>
+
+	    <para>
+		The routing script is executed for every received request in sequential order. 
+		Actions may return positive/negative/zero value. 
+
+		Positive values are considered success and evaluated as
+		TRUE in conditional expressions. Negative values are considered FALSE. 
+
+		Zero value means error and leaves execution of currently processed
+		route block. The route block is left too, if <command>break</command> is explicitly
+		called from it.
+
+	    </para>
+	    <para>
+		The easiest and still very useful way for <application>ser</application>
+		users to affect request routing logic is
+		to determine next hop statically. An example is
+		routing to a PSTN gateway whose static IP address is well known.
+		To configure static routing, simply use the action
+		<command>forward( IP_address, port_number)</command>.
+		This action forwards an incoming request "as is" to the
+		destination described in action's parameters.
+	    </para>
+
+	    <example>
+		<title>Static Forwarding</title>
+		<programlisting format="linespecific">
+# if requests URI is numerical and starts with
+# zero, forward statelessly to a static destination
+
+if (uri=~"^sip:0[0-9]*@iptel.org) {
+    forward( 192.168.99.3, 5080 );
+} 
+		</programlisting>
+	    </example>
+
+	    <para>
+		However, static forwarding is not sufficient in many cases.
+		Users desire mobility and change their location frequently.
+		Lowering costs for termination of calls in PSTN requires
+		locating a least-cost gateway. Which next-hop is taken may
+		depend on user's preferences. These and many other scenarios
+		need the routing logic to be more dynamic. We describe in
+		<xref linkend="conditions"> how to make request processing
+		subject to various conditions and in 
+		<xref linkend="urirewriting"> how to determine next SIP hop.
+	    </para>
+	</section>
+
+	<section id="conditions">
+	    <title>Conditional Statements</title>
+	    <para>
+		A very useful feature is the ability to make routing
+		logic depend on a condition. A script condition may for
+		example distinguish between request processing for
+		served and foreign domains, IP and PSTN routes,
+		it may split traffic by method or username, it
+		may determine whether a request should be authenticated
+		or not, etc. <application moreinfo="none">ser</application>
+		allows administrators to form conditions based on
+		properties of processed request, such as method or uri,
+		as well as on virtually any piece of data on the
+		Internet.
+	    </para>
+	    <example>
+		<title>Conditional Statement</title>
+		<para>
+		    This example shows how a conditional statement is
+		    used to split incoming requests between a PSTN
+		    gateway and a user location server based on
+		    request URI.
+		</para>
+		<programlisting format="linespecific">
+# if request URI is numerical, forward the request to PSTN gateway...
+if (uri=~"^sip:[0-9][email protected]") { # match using a regular expression
+    forward( gateway.foo.bar, 5060 );
+} else { # ... forward the request to user location server otherwise
+    forward( userloc.foo.bar, 5060 );
+};
+		</programlisting>
+	    </example>
+
+	    <para>
+		Conditional statements in <application>ser</application> scripts may depend
+		on a variety of  expressions. The simplest expressions are 
+		action calls. They return true if they completed successfully or false otherwise. 
+		An example of an action frequently used in conditional statements is
+		<command moreinfo="none">search</command> imported from textops module.
+		<command moreinfo="none">search</command> action leverages textual
+		nature of SIP and compares SIP requests against a regular expression.
+		The action returns true if the expression matched, false otherwise.
+		<example>
+		    <title>Use of <command>search</command> Action in Conditional Expression</title>
+		    <programlisting format="linespecific">
+# prevent strangers from claiming to belong to our domain;
+# if sender claims to be in our domain in From header field,
+# better authenticate him 
+if (search("(f|From): .*@mydomain.com)) {
+    if (!(proxy_authorize("mydomain.com" /* realm */,"subscriber" /* table name */ ))) {
+           proxy_challenge("mydomain.com /* ream */, "1" /* use qop */ );
+           break;
+    }
+}
+ 		    </programlisting>
+		</example>
+	    </para>
+	    <para>
+		As modules may be created, which export new functions, there is virtually
+		no limitation on what functionality <application moreinfo="none">ser</application>
+		conditions are based on. Implementers may introduce new actions whose
+		return status depends on request content or any external data as well. Such actions
+		can query SQL, web, local file systems or any other place which can provide
+		information wanted for request processing.
+	    </para>
+	    <para>
+		Furthermore, many request properties may be examined using existing built-in operands
+		and operators. Available left-hand-side operands and legal combination with
+		operators and right-hand-side operands are described in <xref linkend="logicalexpr">.
+		Expressions may be grouped together using logical operators:
+		negation (<command>!</command>), AND (<command>&&</command>), OR (<command moreinfo="none">
+		||</command> and precedence parentheses (<command>()</command>).
+	    </para>
+
+	    <section id="operators">
+		<title>Operators and Operands</title>
+		<para>
+		    There is a set of predefined operators and operands
+		    in ser, which in addition to actions may be evaluated
+		    in conditional expressions. 
+		</para>
+		<para>
+		    Left hand-side operands, which <application>ser</application>
+		    understands are the following:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				<emphasis>method</emphasis>, which refers to 
+				request method
+				such as REGISTER or INVITE
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>uri</emphasis>, which refers to current request URI,
+				such as 
+				"sip:[email protected]"
+				<note>
+				    <para>
+					Note that "uri" always refers to current
+					value of URI, which is subject to change
+					be uri-rewriting actions.
+				    </para>
+				</note>
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>src_ip</emphasis>, which refers to IP address from 
+				which a request came.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>dst_ip</emphasis> refers to server's IP address 
+				at which a request was received
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				<emphasis>src_port</emphasis> port number from which a SIP
+				request came
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<para>
+		    ser understands the following operators:
+		    <itemizedlist>
+			<listitem>
+			    <para>
+				== stands for equity
+			    </para>
+			    
+			</listitem>
+			<listitem>
+			    <para>
+				=~ stands for regular expression matching
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				logical operators: and, or, negation, parentheses
+				(C-notation for the operators may be used too)
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+
+	    <table id="logicalexpr">
+		<title>Valid Combinations of Operands and Operators in Expressions</title>
+		<tgroup cols="4">
+		    <thead>
+			<row>
+			    <entry>
+				left-hand-side operand
+			    </entry>			    
+			    <entry>
+				valid operators
+			    </entry>
+			    <entry>
+				valid right-hand side operators
+			    </entry>
+			    <entry>
+				examples/comments
+			    </entry>
+			</row>
+
+		    </thead>
+		    <tbody>
+
+			<row>
+			    <entry>
+				method
+			    </entry>			    
+			    <entry>
+				== (exact match), =~ (regular expression matching)
+			    </entry>
+			    <entry>
+				string
+			    </entry>
+			    <entry>
+				method=="INVITE" || method=="ACK" || method=="CANCEL"
+			    </entry>
+			</row>			
+
+			<row>
+			    <entry>
+				uri
+			    </entry>			    
+			    <entry>
+				== (exact match), =~ (regular expression matching)
+			    </entry>
+			    <entry>
+				string
+			    </entry>
+			    <entry>
+				uri=="sip:[email protected]" matches only if exactly this uri
+				is in request URI
+
+			    </entry>
+			</row>				
+
+			<row>
+			    <entry>
+				
+			    </entry>			    
+			    <entry>
+				== (exact match)
+			    </entry>
+			    <entry>
+				myself
+			    </entry>
+			    <entry>
+				
+				the expression uri==myself is true if the host part in 
+				request URI equals a server name or a server alias (set using
+				the alias option in configuration file)
+				
+			    </entry>
+			</row>				
+
+			<row>
+			    <entry>
+				src_ip
+			    </entry>			    
+			    <entry>
+				== (match)
+			    </entry>
+			    <entry>
+				IP, IP/mask_length, IP/mask, hostname, myself
+			    </entry>
+			    <entry>
+				src_ip==192.168.0.0/16 matches requests coming from
+				a private network
+			    </entry>
+			</row>
+
+			<row>
+			    <entry>
+				dst_ip				
+			    </entry>			    
+			    <entry>
+				== (match)
+			    </entry>
+			    <entry>
+				IP, IP/mask_length, IP/mask, hostname, myself
+			    </entry>
+			    <entry>
+				dst_ip==127.0.0.1 matches if a request was received
+				via loopback interface
+			    </entry>
+			</row>
+
+			<row>
+			    <entry>
+				    src_port
+			    </entry>			    
+			    <entry>
+				== (match)
+			    </entry>
+			    <entry>
+				port number
+			    </entry>
+			    <entry>
+				port number from which a request was sent, e.g. src_port==5060
+			    </entry>
+			</row>			    
+
+
+		    </tbody>
+		</tgroup>
+	    </table>
+	    
+
+		<example>
+		    <title>
+			More examples of use of <application>ser</application> operators and operands in conditional
+			statements
+		    </title>
+		    <programlisting format="linespecific">
+# using an action as condition input; in this
+# case, an actions 'search' looks for Contacts
+# with private IP address in requests; the condition
+# is processed if such a contact header field is
+# found
+
+if (search("^(Contact|m): .*@(192\.168\.|10\.|172\.16)")) {
+# .... 
+
+# this condition is true if request URI matches
+# the regular expression "@bat\.iptel\.org"
+    if (uri=~"@bat\.iptel\.org") {
+# ...
+
+# and this condition is true if a request came
+# from an IP address (useful for example for
+# authentication by IP address if digest is not
+# supported) AND the request method is INVITE
+
+# if ( (src_ip==192.68.77.110 and method=="INVITE")
+# ...
+</programlisting>
+		</example>
+	    </section> <!-- operators and operands -->
+	    <section>
+		<title>URI Matching</title>
+		<para>URI matching expressions have a broad use in a SIP server
+		    and deserve more explanation. Typical uses of
+		    URI matching include implementation of numbering plans,
+		    domain matching,
+		    binding external applications to specific URIs,
+		    etc. This section shows examples of typical applications
+		    of URI-matching.
+		</para>
+		<section id="domainmatching">
+		    <title>Domain Matching</title>
+		    <para>
+			One of most important uses of URI matching is deciding
+			whether a request is targeted to a served or outside domain.
+			Typically, different request
+			processing applies. Requests for outside domains
+			are simply forwarded to them, whereas
+			more complex logic applies to requests for a served domain.
+			The logic may include saving user's contacts
+			when REGISTER requests are received, forwarding requests
+			to current user's location or a PSTN gateways, 
+			interaction with external applications, etc.
+		    </para>
+		    <para>
+			The easiest way to decide whether a request belongs
+			a served domain is using the <command moreinfo="none">myself</command>
+			operand. 
+			The expression "uri==myself" returns true if domain name
+			in request URI matches name of the host at which
+			<application moreinfo="none">ser</application> is
+			running. This may be insufficient in cases when
+			server name is not equal to domain name for which the server
+			is responsible. For example, the "uri==myself" condition
+			does not match if a server "sipserver.foo.bar" 
+			receives a request for "sip:[email protected]". To
+			match other names in URI than server's own,
+			set up the <varname>alias</varname> configuration
+			option. The option may be used multiple times,
+			each its use adds a new item to a list of aliases.
+			The myself condition returns then  true 
+			also for any hostname on the list of aliases.
+			<example>
+			    <title>Use of uri==myself Expression</title>
+			    <programlisting format="linespecific">
+# ser powers a domain "foo.bar" and runs at host sipserver.foo.bar;
+# Names of served domains need to be stated in the aliases
+# option; myself would not match them otherwise and would only
+# match requests with "sipserver.foo.bar" in request-URI
+alias="foo.bar"
+alias="sales.foo.bar"
+route[0] {
+        if (uri==myself) {
+            # the request either has server name or some of the
+            # aliases in its URI
+            log(1,"request for served domain")
+            # some domain-specific logic follows here ....
+        } else {
+            # aha -- the server is not responsible for this
+            # requests; that happens for example with the following URIs
+            #  - sip:[email protected]
+            #  - sip:[email protected]
+            log(1,"request for outbound domain");
+            # outbound forwarding			  
+            t_relay();
+        };
+}			</programlisting>
+		    </example>
+		</para>
+		<para>
+		    It is possible to recognize whether a request belongs to
+		    a domain using regular expressions too. Care needs to
+		    be paid to construction of regular expressions. URI
+		    syntax is rich and an incorrect expression would result
+		    in incorrect call processing. The following example shows
+		    how an expression for domain matching can be formed.
+		    <example id="redomainmatching">
+			<title>Domain Matching Using Regular Expressions</title>
+			<para>
+			    In this example, server named "sip.foo.bar" with
+			    IP address 192.168.0.10 is responsible for the
+			    "foo.bar" domain. That means, requests with the
+			    following hostnames in URI should be matched:
+			    <itemizedlist>
+				<listitem>
+				    <para>
+					foo.bar, which is the name of server domain
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					sip.foo.bar, since it is server's name and some
+					devices put server's name in request URI
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					192.168.0.10, since it is server's IP address and
+					some devices put server's IP address in request URI
+				    </para>
+				</listitem>
+			    </itemizedlist>			
+			    Note how this regular expression is constructed. In particular:
+			    <itemizedlist>
+				<listitem>
+				    <para>
+					User name is optional (it is for example never included
+					in REGISTER requests) and there are no restrictions on
+					what characters it contains. That is what 
+					<emphasis>(.+@)?</emphasis> mandates. 
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Hostname must be followed by port number, parameters
+					or headers -- that is what the delimiters 
+					<emphasis>[:;\?]</emphasis> are good for. If none
+					it these follows, the URI must be ended 
+					(<emphasis>$</emphasis>). Otherwise, longer hostnames
+					such as 192.168.0.101 or foo.bar.otherdomain.com would
+					mistakenly match.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Matches are case-insensitive. All hostnames "foo.bar", "FOO.BAR"
+					and "FoO.bAr" match.
+				    </para>
+				</listitem>
+			    </itemizedlist>
+			</para>
+			<programlisting>
+if (uri=~"^sip:(.+@)?(192\.168\.0\.10|(sip\.)?foo\.bar)([:;\?].*)?$")
+      log(1, "yes, it is a request for our domain");
+      break;
+ };
+			</programlisting>
+		    </example>
+		</para>
+		</section> <!-- domain matching -->
+		<section id="numberingplans">
+		    <title>Numbering Plans</title>
+
+		    <para>
+			Other use of URI matching is implementation of dialing
+			plans. A typical task when designing a dialing plan for SIP networks
+			is to distinguish between "pure-IP" and PSTN destinations.
+			IP users typically have either alphanumerical or numerical
+			usernames. The numerical usernames are convenient for PSTN
+			callers who can only
+			use numeric keypads. Next-hop destination of IP users is looked up dynamically
+			using user location database. On the other hand, PSTN destinations are 
+			always indicated by nummerical usernames. Requests to PSTN are statically 
+			forwarded to well-known PSTN gateways.
+		    </para>
+		    <example>
+			<title>A simple Numbering Plan</title>
+			<para>
+			    This example shows a simple dialing plan which reserves
+			    dialing prefix "8" for IP users, other numbers
+			    are used for PSTN destinations and all other non-nummerical
+			    usernames are used for IP users.
+			</para>
+			<programlisting format="linespecific">
+# is it a PSTN destination? (is username nummerical and does not begin with 8?)
+if (uri=~"^sip:[0-79][0-9]*@") { # ... forward to gateways then;
+      # check first to which PSTN destination the requests goes;
+      # if it is US (prefix "1"), use the gateway 192.168.0.1...
+      if (uri=~"^sip:1") {
+           # strip the leading "1"
+           strip(1);
+           forward(192.168.0.1, 5060);
+      } else {
+           # ... use the gateway 10.0.0.1 for all other destinations
+           forward(10.0.0.1, 5060);
+      }
+      break;
+} else {
+      # it is an IP destination -- try to lookup it up in user location DB
+      if (!lookup("location")) {
+          # bad luck ... user off-line
+          sl_send_reply("404", "Not Found");
+          break;
+      }
+      # user on-line...forward to his current destination
+      forward(uri:host,uri:port);
+}
+			</programlisting>
+		    </example>
+		</section> <!-- numbering plans -->
+	    </section>
+	</section> <!-- conditional statements -->
+	
+	<section id="urirewriting">
+	    <title>Request URI Rewriting</title>
+
+	    <para>
+		The ability to give users and services a unique name using URI
+		is a powerful tool. It allows users to advertise how to reach
+		them, to state to whom they wish to communicate and what services 
+		they wish to use.
+		Thus, the ability to change URIs is very important and is
+		used for implementation of many services. 
+		"Unconditional forwarding" from user "boss" to user
+		"secretary" is a typical example of application relying
+		on change of URI address.
+	    </para>
+	    <para>
+		<application moreinfo="none">ser</application> has the ability
+		to change request URI in many ways.
+		A script can use any of the following
+		built-in actions to change request URI or a part of it:
+
+		<command>rewriteuri</command>, 
+		<command>rewritehost</command>, 
+		<command>rewritehostport</command>, 
+		<command>rewriteuser</command>, 
+		<command>rewriteuserpass</command> and 
+		<command>rewriteport</command>. 
+		When later in the script
+		a forwarding action is encountered, the action forwards
+		the request to address in the rewritten URI.
+		<example>
+		    <title>Rewriting URIs</title>
+		    <programlisting format="linespecific">
+if (uri=~"[email protected]") {
+    rewriteuri("sip:[email protected]")
+    # forward statelessly to the destination in current URI, i.e.,
+    # to sip:[email protected]:5060
+    forward( uri:host, uri:port);
+}
+		    </programlisting>
+		</example>
+	    </para>	    
+	    <para>Two more built-in URI-rewriting commands are of special importance
+		for implementation of dialing plans and manipulation of dialing
+		prefixes. <command>prefix(s)
+		</command>, inserts 
+		a string "s" in front of SIP address and 
+		<command>strip(n)</command> takes
+		away the first "n" characters of a SIP address.
+		See <xref linkend="urirewritingexamples"> for examples of use of
+		built-in URI-rewriting actions.
+	    </para>
+
+	    <para>
+		Commands exported by external modules can change URI too
+		and many do so.
+		The most important application is changing URI using the
+		user location database. The command 
+		<command>lookup(table)</command> looks up current
+		user's location and rewrites user's address with it.
+		If there is no registered contact, the 	command returns a negative value.
+
+
+		<example id=rewriteuri>
+		    <title>Rewriting URIs Using User Location Database</title>
+		    <programlisting format="linespecific">
+# store user location if a REGISTER appears
+if (method=="REGISTER") {
+   save("mydomain1");
+} else {
+# try to use the previously registered contacts to
+# determine next hop
+   if(lookup("mydomain1")) {
+     # if found, forward there...
+     t_relay();
+   } else {
+     # ... if no contact on-line, tell it upstream
+     sl_send_reply("404", "Not Found" );
+   };
+};
+		    </programlisting>
+		</example>
+	    </para>
+	    <para>
+		External applications can be used to rewrite URI too.
+		The "exec" module provides script actions, which start external programs
+		and read new URI value from their output. <command moreinfo="none">exec_uri</command>
+		and <command moreinfo="none">exec_user</command> both call an external program,
+		pass current URI or its user part to it respectively, wait until it completes,
+		and eventually rewrite current URI with its output.
+	    </para>
+	    <para>
+		It is important to realize that <application moreinfo="none">ser</application>
+		operates over <emphasis>current URI</emphasis> all the time. If an original
+		URI is rewritten by a new one, the original will will be forgotten and the new one will 
+		be used in any further processing. In particular, the uri matching operand
+		and the user location action <command moreinfo="none">lookup</command>
+		always take current URI as input, regardless what the original URI was.
+	    </para>
+	    <para>
+		<xref linkend="urirewritingexamples"> shows how URI-rewriting actions affect 
+		an example URI, sip:[email protected]:6060.
+		<table id="urirewritingexamples">
+		    <title>URI-rewriting Using Built-In Actions</title>
+		    <tgroup cols="2">
+			<thead>
+			    <row>
+				<entry>
+				    Example Action
+				</entry>				
+				<entry>
+				    Resulting URI
+				</entry>
+			    </row>
+			</thead>
+			<tbody>
+			    <row>
+				<entry>
+				    <command moreinfo="none">rewritehost("192.168.0.10")</command> rewrites
+				    the hostname in URI, other parts (including port number) remain unaffected.
+				</entry>
+				<entry>
+				    sip:[email protected]:6060
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">rewriteuri("sip:[email protected]");</command> rewrites
+				    the whole URI completely.
+				</entry>
+				<entry>
+				    sip:[email protected]
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">rewritehostport("192.168.0.10:3040")</command>rewrites 
+				    both hostname and port number in URI.
+				</entry>
+				<entry>
+				    sip:[email protected]:3040
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">rewriteuser("alice")</command> rewrites user part of URI.
+				</entry>
+				<entry>
+				    sip:[email protected]:6060
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">rewriteuserpass("alice:pw")</command> replaces the pair
+				    user:password in URI with a new value.
+				</entry>
+				<entry>
+				    sip:alice:[email protected]:6060
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">rewriteport("1234")</command> replaces port number in URI
+				</entry>
+				<entry>
+				    sip:[email protected]:1234
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">prefix("9")</command> inserts a string ahead of user part of URI
+				</entry>
+				<entry>
+				    sip:[email protected]:6060
+				</entry>
+			    </row>
+			    <row>
+				<entry>
+				    <command moreinfo="none">strip(2)</command> removes leading characters from user part of URI
+				</entry>
+				<entry>
+				    sip:[email protected]:6060
+				</entry>
+			    </row>
+
+
+			</tbody>
+		    </tgroup>
+		</table>
+	    </para>	    
+	    <para>
+		You can verify whether you understood URI processing by
+		looking at the following example. It rewrites URI
+		several times. The question is what is the final URI to which
+		the script fill forward any incoming request.
+		<example>
+		    <title>URI-rewriting Exercise</title>
+		    <programlisting format="linespecific">
+exec_uri("echo sip:[email protected]; echo > /dev/null");
+strip(2);
+if (uri=~"^sip:2") {
+    prefix("0");
+} else {
+    prefix("1");
+};			
+forward(uri:host, uri:port);
+		    </programlisting>
+		</example>
+	    </para>
+	    <para>
+		The correct answer is the resulting URI will be
+		"sip:[email protected]". <command moreinfo="none">exec_uri</command>
+		rewrites original URI to "sip:[email protected]", 
+		<command moreinfo="none">strip(2)</command> takes
+		two leading characters from username away resulting
+		in "[email protected]", the condition does not match
+		because URI does not begin with "2" any more,
+		so the prefix "1" is inserted.
+	    </para>
+
+
+	</section> <!-- URI rewriting -->
+
+	<section>
+	    <title>Destination Set</title>
+	    <para>
+		Whereas needs of many scenarios can by accommodated by maintaining
+		a single request URI, some scenarios are better served by
+		multiple URIs. Consider for example a user with address
+		[email protected]. The user wishes to be reachable at his 
+		home phone, office phone, cell phone, softphone, etc. 
+		However, he still wishes to maintain a single public address
+		on his business card.
+	    </para>
+	    <para>
+		To enable such scenarios, <application>ser</application>
+		allows translation of a single request URI into multiple
+		outgoing URIs. The ability to forward a request to multiple
+		destinations is known as <emphasis>forking</emphasis>
+		in SIP language. All outogoing URIs (in trivial case one of them)
+		are called <emphasis>destination set</emphasis>. The destination
+		set always includes one default URI, to which additional URIs
+		can be appended. Maximum size of a destination set is limited by 
+		a compile-time constant, MAX_BRANCHES,
+		in <filename moreinfo="none">config.h</filename>.
+	    </para>
+	    <para>
+		Some actions are designed for use with a single URI whereas
+		other actions work with the whole destination set.
+	    </para>
+	    <para>
+		Actions which are currently available for creating the destination
+		set are <command>lookup</command> from usrloc module and 
+		<command>exec_uri/exec_user</command> from exec module.
+		<command moreinfo="none">lookup</command> fills in the destination
+		set with user contact's registered previously with REGISTER
+		requests. The <command moreinfo="none">exec</command> actions
+		fill in the destination set with output of an external program.
+		In both cases, current destination set is completely rewritten.		
+		New URIs can be appended to destination set by a call to the built-in
+		action <command>append_branch(uri)</command>.
+	    </para>
+	    <para>		
+		Currently supported features which utilize destination sets
+		are <emphasis>forking</emphasis> and <emphasis>redirection</emphasis>. 
+		Action <command>t_relay</command> (TM module) for stateful
+		forwarding supports forking. If called with a non-trivial destination
+		set, <command moreinfo="none">t_relay</command> forks
+		incoming request to all URIs in current destination set.
+		See <xref linkend="rewriteuri">. If a user
+		previously registered from three locations, the destination set is filled with 
+		all of them by <command>lookup</command> and the <command>t_relay</command>
+		command forwards the incoming request to all these destinations.
+		Eventually, all user's phone will be ringing in parallel.
+	    </para>
+	    <para>
+		SIP redirection is another feature which leverages destination sets.
+		It is a very light-weighted method to establish communication
+		between two parties with minimum burden put on the server. In
+		<application>ser</application>, the action <command>sl_send_reply</command>
+		(SL module) is used for this purpose. This action 
+		allows to generate replies to SIP requests without keeping 
+		any state. If the status code passed to the action is 3xx, 
+		the current destination set is printed in reply's Contact header
+		fields. Such a reply instructs the originating client to 
+		retry at these addresses. (See <xref linkend="redirectexample">).
+	    </para>
+	    <para>
+		Most other  <application>ser</application> actions ignore destination
+		sets: they either do not relate to URI processing (<command moreinfo="none">
+		log</command>, for example) or they work only with the default URI.
+		All URI-rewriting functions such as
+		<command moreinfo="none">rewriteuri</command> belong in this
+		category. URI-comparison operands only refers to the first URI
+		(see <xref linkend="operators">). Also, the built-in action
+		for stateless forwarding, <command>forward</command> works only
+		with the default URI and ignores rest of the destination set. The reason 
+		is a proxy server willing to fork must guarantee that the burden
+		of processing multiple replies is not put unexpectedly on upstream
+		client. This is only achievable with stateful processing.  
+		Forking cannot be used along with stateless <command>forward</command>,
+		which thus only processes one URI out of the whole destination set.
+		Also, the uri comparison operand (see <xref linkend="operators">)
+		refers only to current URI and ignores the rest of destination
+		set.
+	    </para> 
+
+	</section> <!-- Destination Set -->
+
+	<section>
+	    <title>User Location</title>
+	    <para>
+		Mobility is a key feature of SIP. Users are able to use one
+		one or more SIP devices and be reachable at them. Incoming requests 
+		for users are forwarded to all user's devices in use. The key
+		concept is that of soft-state registration. Users can
+		-- if in possession of valid credentials -- link SIP
+		devices to their e-mail like address of record. Their SIP devices
+		do so using a REGISTER request, as in <xref linkend="register">.
+		The request creates a binding between the public address of
+		record (To header field) and SIP device's current address
+		(Contact header field). 
+		<example id="register">
+		    <title>REGISTER Request</title>
+		    <programlisting format="linespecific">
+REGISTER sip:192.168.2.16 SIP/2.0
+Via: SIP/2.0/UDP 192.168.2.16;branch=z9hG4bKd5e5.5a9947e4.0
+Via: SIP/2.0/UDP 192.168.2.33:5060
+From: sip:[email protected]
+To: sip:[email protected]
+Call-ID: [email protected]
+Date: Wed, 29 Jan 2003 18:13:15 GMT
+CSeq: 101 REGISTER
+User-Agent: CSCO/4
+Contact: sip:[email protected]:5060
+Content-Length: 0
+Expires: 600
+		    </programlisting>
+		</example>
+		Similar requests can be used to query all user's current contacts or to
+		delete them. All Contacts have certain time to live, when the time expires,
+		contact is removed and no longer used for processing of incoming requests.
+	    </para>
+	    <para>
+		<application moreinfo="none">ser</application> is built to do both: update
+		user location database from received REGISTER requests and look-up these
+		contacts when inbound requests for a user arrive. To achieve high performance,
+		the user location table is stored in memory. In regular intervals
+		(usrloc module's parameter <varname>timer_interval</varname> determines
+		their length), all changes to the in-memory table are backed up in
+		<application moreinfo="none">mysql</application> database to achieve
+		peristence accross server reboots. Administrators or application writers
+		can lookup list of current user's contacts stored in memory using the
+		<application moreinfo="none">serctl</application> tool (see <xref linkend="serctl">).
+		<example>
+		    <title>Use of <application>serctl</application> Tool to Query User Location</title>
+		    <screen format="linespecific">
+<![CDATA[
+[jiri@fox jiri]$ sc ul show jiri
+<sip:[email protected]>;q=0.00;expires=456
+<sip:[email protected]>;q=0.00;expires=36000
+]]>
+		    </screen>
+		</example>
+	    </para>
+	    <para>
+		Building user location in <application moreinfo="none">ser</application> scripts is
+		quite easy. One first needs to determine whether a request is for served domain,
+		as described in <xref linkend="domainmatching">. If that is the case, the script
+		needs to distinguish between REGISTER requests, that update user location table,
+		and all other requests for which next hop is determined from the table. The
+		<command moreinfo="none">save</command> action is used to update user location
+		(i.e., it writes to it). The <command moreinfo="none">lookup</command> actions
+		reads from the user location table and fills in destination set with current
+		user's contacts.
+		<example>
+		    <title>Use of User Location Actions</title>
+		    <programlisting format="linespecific">
+# is the request for my domain ?
+if (uri==myself) {
+    if (method=="REGISTER") { # REGISTERs are used to update
+         save("location");
+         break; # that's it, we saved the contacts, exit now
+    } else {
+         if (!lookup("location") { # no registered contact
+            sl_send_reply("404", "Not Found");
+            break;
+         }
+         # ok -- there are some contacts for the user; forward
+         # the incoming request to all of them
+         t_relay();
+    };
+};
+		    </programlisting>
+		</example>
+	    </para>
+	    <para>
+		Note that we used the action for stateful forwarding, 
+		<command moreinfo="none">t_relay</command>. That's is because
+		stateful forwarding allows to fork an incoming request to
+		multiple destinations. If we used stateful forwarding,
+		the request would be forwarded only to one uri out of
+		all user's contacts.
+	    </para>
+	</section> <!-- User Location -->
+	
+	<section>
+	    <title>External Modules</title>
+	    <para>
+		<application moreinfo="none">ser</application> provides the ability to link the server with external
+		third-party shared libraries. Lot of functionality which is
+		included in the <application moreinfo="none">ser</application> distribution is actually located in
+		modules to keep the server "core" compact and clean.
+		Among others, there are modules for checking max_forwards
+		value in SIP requests (maxfwd), transactional processing (tm),
+		record routing (rr), accounting (acc), authentication (auth),
+		SMS gateway (sms), replying requests (sl), user location
+		(usrloc, registrar) and more.
+	    </para>
+	    <para>
+		In order to utilize new actions exported by a module, 
+		ser must first load it. To load a module, the directive
+		<command moreinfo="none">loadmodule "filename"</command>
+		must be included in beginning of
+		a <application>ser</application> script file.
+	    </para>
+
+	    <example>
+		<title>Using Modules</title>
+		<para>
+		    This example shows how a script instructs 
+		    <application moreinfo="none">ser</application> to
+		    load a module and use actions exported by it.
+		    Particularly, the sl module exports an action
+		    <command>sl_send_reply</command> which makes 
+		    <application>ser</application> act as a stateless
+		    user agent and reply all incoming requests with 404.
+		</para>
+		<programlisting format="linespecific">
+# first of all, load the module!
+loadmodule "/usr/lib/ser/modules/sl.so
+route{
+    # reply all requests with 404
+    sl_send_reply("404", "I am so sorry -- user not found");
+}
+</programlisting>
+	    </example>
+	    <note>
+		<para>Note that unlike with core commands, all actions
+		    exported by modules must have parameters enclosed
+		    in quotation marks in current version of 
+		    <application moreinfo="none">ser</application>.
+		    In the following example, the built-in action
+		    <command moreinfo="none">forward</command> for
+		    stateless forwarding takes
+		    IP address and port numbers as parameters without
+		    quotation marks whereas a module action 
+		    <command moreinfo="none">t_relay</command> for
+		    stateful forwarding takes parameters enclosed in
+		    quotation marks.
+		    <example>
+			<title>Parameters in built-in and exported
+			actions</title>
+			<programlisting format="linespecific">
+# built-in action doesn't enclose IP addresses and port numbers
+# in quotation marks
+forward(192.168.99.100, 5060);
+# module-exported functions enclose all parameters in quotation
+# marks
+t_relay_to("192.168.99.100", "5060");
+			</programlisting>
+		    </example>
+		</para>
+	    </note>
+	    <para>
+		Many modules also allow users to change the way how they
+		work using predefined parameters. For example, the
+		authentication module needs to know location of MySQL
+		database which contains users' security credentials.
+		How module parameters
+		are set using the <command moreinfo="none">modparam</command>
+		directive is shown in <xref linkend="moduleparameters">. 
+		<command moreinfo="none">modparam</command>
+		always contains identification of module, parameter
+		name and parameter value. Description of parameters
+		available in modules is available in module documentation.
+	    </para>
+	    <para>
+		Yet another thing to notice in this example is module
+		dependency. Modules may depend on each other. For example,
+		the authentication modules leverages the mysql module
+		for accessing mysql databases and sl module for generating
+		authentication challenges. We recommend that modules are
+		loaded in dependency order to avoid ambiguous server
+		behaviour.
+	    </para>	    
+	    <para>
+		<example id="moduleparameters">
+		    <title>Module Parameters</title>
+		    <programlisting format="linespecific">
+# ------------------ module loading ----------------------------------
+
+# load first modules on which 'auth' module depends;
+# sl is used for sending challenges, mysql for storage
+# of user credentials
+loadmodule "modules/sl/sl.so"
+loadmodule "modules/mysql/mysql.so"
+loadmodule "modules/auth/auth.so"
+
+# ------------------ module parameters -------------------------------
+# tell the auth module the access data for SQL database:
+# username, password, hostname and database name
+modparam("auth", "db_url","sql://ser:secret@dbhost/ser")
+
+
+# -------------------------  request routing logic -------------------
+
+# authenticate all requests prior to forwarding them
+
+route{
+
+        if (!proxy_authorize("foo.bar" /* realm */,
+                        "subscriber" /* table name */ )) {
+                proxy_challenge("foo.bar", "0");
+                break;
+        };
+        forward(192.168.0.10,5060);
+}
+
+		    </programlisting>
+		</example>
+	    </para>
+	</section>
+
+	<section>
+	    <title>Writing Scripts</title>
+	    <para>
+		This section demonstrates simple examples
+		how to configure server's behaviour using the
+		<application moreinfo="none">ser</application>
+		request routing language. All scripts follow the 
+		<application moreinfo="none">ser</application> language 
+		syntax, which dictates the following block ordering:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>global configuration parameters</emphasis> --
+			    these value affect behaviour of the server such as port
+			    number at which it listens, number of spawned children
+			    processes, and log-level. See <xref linkend="coreoptions">
+			    for a list of available options.
+			</para>
+		    </listitem>
+
+		    <listitem>
+			<para>
+			    <emphasis>module loading</emphasis> -- these statements
+			    link external modules, such as transaction management
+			    (tm) or stateless UA server (sl)  dynamically. See
+			    <xref linkend="modulereference"> for a list of modules
+			    included in <application moreinfo="none">ser</application>
+			    distribution.
+			</para>
+			<note>
+				<para>
+					If modules depend on each other, than the depending
+					modules must be loaded after modules on which they
+					depend. We recommend to load first modules
+					<command>tm</command> and <command>sl</command>
+					because many other modules (authentication, user
+					location, accounting, etc.) depend on these.
+				</para>
+			</note>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>module-specific parameters</emphasis> -- determine
+			    how modules behave; for example, it is possible to configure
+			    database to be used by authentication module.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    one or more <emphasis>route blocks</emphasis> containing the
+			    request processing logic, which includes built-in actions
+			    as well as actions exported by modules. See <xref linkend="builtinref">
+			    for a list of built-in actions.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    optionally, if modules supporting reply
+			    processing (currently only TM) are loaded,
+			    one or more <emphasis>reply_route blocks</emphasis> containing
+			    logic triggered by received replies. Restrictions on use of
+			    actions within <command moreinfo="none">reply_route</command>
+			    blocks apply -- see <xref linkend="builtinref"> for more
+			    information.
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+
+	    <para>
+		For more complex examples, see the etc directory in
+		<application>ser</application> source distribution.
+		It contains the 
+		<filename moreinfo="none">iptel.cfg</filename> script which is
+		in production use at iptel.org's public SIP site and exploits most of 
+		<application>ser</application> features.
+	    </para>
+
+	    <section id="defaultscript">
+		<title>Default Configuration Script</title>		
+		<para>
+		    The configuration script, <filename moreinfo="none">ser.cfg</filename>,
+		    is a part of every <application moreinfo="none">ser</application>
+		    distribution and defines default behaviour. It allows users
+		    to register with the server and have requests proxied to each
+		    other.
+		</para>
+		<para>
+		    After performing
+		    routine checks, the script looks whether incoming request is for
+		    served domain. If so and the request is "REGISTER", <application moreinfo="none">ser</application>
+		    acts as SIP registrar and updates database of user's contacts.
+		    Optionally, it verifies user's identity first to avoid
+		    unauthorized contact manipulation.
+		</para>
+		<para>
+		    Non-REGISTER request for served domains are then processed using
+		    user location database. If a contact is found for requested URI,
+		    script execution proceeds to stateful forwarding, a negative 404
+		    reply is generated otherwise. Requests outside served domain
+		    are always statefully forwarded.
+		</para>
+		<para>
+		    Note that this simple script features several limitations:
+		    <itemizedlist>
+			<listitem>			    
+			    <para>
+				By default, authentication is turned off to avoid
+				dependency on mysql. Unless it it turned on, anyone
+				can register using any name and "steal" someone else's
+				calls.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				Even it authentication is turned on, there is no relationship
+				between authentication username and address of record. That
+				means that for example a user authenticating himself correctly
+				with "john.doe" id may register contacts for "gw.bush".
+				Site policy may wish to mandate authentication id to be equal
+				to username claimed in To header field. <action moreinfo="none">check_to</action>
+				action from auth module can be used to enforce such a policy.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				There is no dialing plan implemented. All users are supposed to
+				be reachable via user location database. See <xref linkend="numberingplans">
+				for more information.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				The script assumes users will be using server's name as a part of
+				their address of record. If users wish to use another name (domain
+				name for example), this must be set using the <varname>alias</varname>
+				options. See <xref linkend="domainmatching"> for more information.
+			    </para>
+			</listitem>
+			<listitem>
+			    <para>
+				If authentication is turned on by uncommenting related configuration
+				options, clear-text user passwords will by assumed in back-end database.
+			    </para>
+			</listitem>
+		    </itemizedlist>
+		</para>
+		<example>
+		    <title>Default Configuration Script</title>
+		    <programlisting format="linespecific">
+&defscr;			
+		    </programlisting>
+		</example>
+	    </section>
+
+	    <section id="statefulua">
+		<title>Stateful User Agent Server</title>
+		<para>
+		    This examples shows how to make ser act as a stateful user
+		    agent (UA). Ability to act as as a stateful UA is essential
+		    to many applications which terminate a SIP path. These
+		    applications wish to focus on their added value. They
+		    do not wish to be involved in all SIP gory details, such
+		    as request and reply retransmission, reply formatting, etc.
+		    For example, we use the UA functionality to shield 
+		    SMS gateway and instant message store from SIP transactional
+		    processing.
+		    The simple example bellow issues a log report on receipt
+		    of a new transaction. 
+		    If we did not use a stateful UA, every single request retransmission
+		    would cause the application to be re-executed which would result in
+		    duplicated SMS messages, instant message in message store or 
+		    log reports.
+		</para>
+		<para>
+		    The most important actions are <command moreinfo="none">
+			t_newtran</command> and <command moreinfo="none">
+			t_reply</command>. <command moreinfo="none">
+			
+		    t_newtran</command> shields subsequent code from retransmissions.
+		    It returns success and continues when a new request arrived.
+		    It exits current route block immediately on receipt of
+		    a retransmissions. It only returns a negative value when
+		    a serious error, such as lack of memory, occurs.
+		</para>
+		<para>
+		    <command moreinfo="none">t_reply</command> generates
+		    a reply for a request. It generates the reply statefully,
+		    i.e., it is kept for future retransmissions in memory.
+		</para>
+		<note>
+			<para>
+				Applications that do not need stateful processing
+				may act as stateless UA Server too. They just use
+				the <command>sl_send_reply</command> action to
+				send replies to requests without keeping any
+				state. The benefit is memory cannot run out,
+				the drawback is that each retransmission needs to
+				be processed as a new request. An example of use
+				of a stateless server is shown in
+		    	<xref linkend="redirectserver"> and
+		    	<xref linkend="executingscript">.
+			</para>
+		</note>
+		<example>
+		    <title>Stateful UA Server</title>
+		    <programlisting format="linespecific">
+			<!-- ../../examples/uas.cfg -->
+			&statefuluaexample;
+		    </programlisting>
+		</example>
+	    </section> <!-- Stateful UAS -->
+
+	    <section id="redirectserver">
+		<title>Redirect Server</title>
+		<para>
+		    The redirect example shows how to redirect a request
+		    to multiple destination using 3xx reply. Redirecting
+		    requests as opposed to proxying them is essential to
+		    various scalability scenarios. Once a message is
+		    redirected, <application moreinfo="none">ser</application>
+		    discards all related state and is no more involved
+		    in subsequent SIP transactions (unless the redirection
+		    addresses point to the same server again).
+		</para>
+		<para>
+		    The key <application>ser</application> actions in this example 
+		    are <command moreinfo="none">append_branch</command> and 
+		    <command moreinfo="none">sl_send_reply</command> (sl module).
+		</para>
+		<para>
+		    <command moreinfo="none">append_branch</command> adds
+		    a new item to the destination set. The destinations set always
+		    includes the current URI and may be enhanced up to
+		    <constant>MAX_BRANCHES</constant> items.
+		    <command moreinfo="none">sl_send_reply</command> command, 
+		    if passed SIP reply code 3xx, takes all values in current 
+		    destination set and adds them to Contact header field in 
+		    the reply being  sent.
+		</para>
+		<example id="redirectexample">
+		    <title>Redirect Server</title>
+		    <programlisting format="linespecific">
+			<!-- ../../examples/redirect.cfg -->
+			&redirectexample;
+		    </programlisting>
+		</example>
+	    </section> <!-- redirect server-->
+	    
+	    <section id="executingscript">
+		<title>Executing External Script</title>
+		<para>
+		    Like in the previous example, we show how to
+		    make ser act as a redirect server. The difference is 
+		    that we do not use redirection addresses hardwired in
+		    <application moreinfo="none">ser</application> script but
+		    get them from external shell commands. We also use
+		    ser's ability to execute shell commands to log
+		    source IP address of incoming SIP requests.
+		</para>
+		<para>
+		    The new commands introduced in this example are
+		    <command moreinfo="none">exec_msg</command> and
+		    <command moreinfo="none">exec_uri</command>.
+		    <command moreinfo="none">exec_msg</command> takes
+		    current requests, starts an external command, and
+		    passes the requests to the command's standard input.
+		    It also passes request's source IP address in
+		    environment variable named <constant>SRC_IP</constant>.
+		</para>
+		<para>
+		    <command moreinfo="none">exec_uri</command> serves
+		    for URI rewriting by external applications.  The
+		    <command moreinfo="none">exec_uri</command> action
+		    passes current URI to the called external program as
+		    command-line parameter, and rewrites current destination
+		    set with the program's output. An example use would
+		    be an implementation of a Least-Cost-Router, software which
+		    returns URI of the cheapest PSTN provider for a given
+		    destination based on some pricing tables. <xref linkend="execscript">
+		    is much easier: it prints fixed URIs on its output using
+		    shell script <command moreinfo="none">echo</command> command.
+		</para>
+		<note>
+			<para>
+				This script works statelessly -- it uses this action for
+				stateless replying, <command>sl_send_reply</command>.
+				No transaction is kept in memory and each request retransmission
+				is processed as a brand-new request. That may be a particular
+				concern if the server logic (<command>exec</command> actions
+				in this example) is too expensive. See 
+		    	<xref linkend="statefulua"> for instructions on how
+				to make server logic stateful, so that retransmissions
+				are absorbed and do not cause re-execution of the logic.
+			
+			</para>
+		</note>
+		<example id="execscript">
+		    <title>Executing External Script</title>
+		    <programlisting format="linespecific">
+			<!-- ../../examples/exec.cfg -->
+			&execexample;
+		    </programlisting>
+		</example>
+	    </section> <!-- exec example -->
+	    
+	    <section id="replyprocessingsection">
+		<title>On-Reply Processing (Forward on Unavailable)</title>
+		<para>
+		    Many services depend on status of messages relayed
+		    downstream: <emphasis>forward on busy</emphasis> and 
+		    <emphasis>forward on no reply</emphasis> to name the
+		    most well-known ones. To support implementation of
+		    such services, <application moreinfo="none">ser</application>
+		    allows to return to request processing when request
+		    forwarding failed. When a request is reprocessed,
+		    new request branches may be initiated or the transaction
+		    can be completed at discretion of script writer.
+		</para>
+		<para>
+		    The primitives used are <command moreinfo="none">t_on_negative(r)</command>
+		    and <command moreinfo="none">reply_route[r]{}.</command> If
+		    <command>t_on_negative</command> is called before
+		    a request is statefuly forwarded and a forwarding failure occurs, 
+		    <application moreinfo="none">ser</application>
+		    will return to request processing in a <command moreinfo="none">reply_route</command>
+		    block. Failures include receipt of a SIP error
+		    (status code >= 300 ) from upstream or not receiving
+		    any final reply within final response period.
+		</para>
+		<para>
+		    The length of the timer is governed by parameters of the
+		    tm module. <varname>fr_timer</varname> is the length of
+		    timer set for non-INVITE transactions and INVITE transactions
+		    for which no provisional response is received. If a timer
+		    hits, it indicates that a downstream server is unresponsive.
+		    <varname>fr_inv_timer</varname> governs time to wait for 
+		    a final reply for an INVITE. It is typically longer than
+		    <varname>fr_timer</varname> because final reply may take
+		    long time until callee (finds a mobile phone in a pocket and)
+		    answers the call.
+		</para>
+		<para>
+		    In <xref linkend="replyprocessing">, <command moreinfo="none">reply_route[1]</command>
+		    is set to be entered on error using the <command moreinfo="none">t_on_negative(1)</command>
+		    action. Within this reply block, <application moreinfo="none">ser</application>
+		    is instructed to initiate a new branch and try to reach called party
+		    at another destination (sip:[email protected]). To deal with the case when neither the alternate
+		    destination succeeds, <application moreinfo="none">t_on_negative</application>
+		    is set again. If the case really occurs, <command moreinfo="none">reply_route[2]</command>
+		    is entered and a last resort destination (sip:[email protected]) is tried.
+		</para>
+		<example id="replyprocessing">
+		    <title>On-Reply Processing</title>
+		    <programlisting format="linespecific">
+			<!-- ../../examples/onr.cfg -->
+			&replyexample;
+		    </programlisting>
+
+		</example>
+	    </section> <!-- reply processing -->
+	</section> <!-- examples -->
+    </chapter>

+ 1480 - 0
doc/seruser/operation.sgml

@@ -0,0 +1,1480 @@
+    <chapter>
+	<title>Server Operation</title>
+	<section id="operationalpractices">
+	    <title>Recommended Operational Practices</title>
+
+	    <para>
+		Operation of a SIP server is not always easy task.
+		Server administrators are challenged by broken or
+		misconfigured user agents, network and host failures,
+		hostile attacks and other stress-makers. All such
+		situations may lead to an operational failure. It is sometimes
+		very difficult to figure out the root reason of
+		a failure, particularly in a distributed environment
+		with many SIP components involved.		
+		In this section,
+		we share some of our practices and refer to tools
+		which have proven to
+		make life of administrators easier
+	    </para>
+
+	<qandaset>
+	    <qandaentry>
+		<question>
+		    <para>
+			Keeping track of messages is good
+		    </para>
+		</question>
+		<answer>
+			<para>
+			    Frequently, operational errors are discovered or reported
+			    with a delay.
+			    Users frustrated by an error
+			    frequently approach administrators
+			    and scream "even though my SIP requests were absolutely ok
+			    yesterday, they were mistakenly denied by your server".
+			    If administrators do not record all SIP traffic at
+			    their site, they will be no more able to identify
+			    the problem reason.
+			    We thus recommend that site
+			    operators record all messages passing their site and keep them
+			    stored for some period of time.
+			They may use utilities such as 
+			<application>ngrep 
+			</application> or 
+			<application>tcpdump
+			</application>.
+			There is also a utility <application moreinfo="none">
+			    scripts/harv_ser.sh</application> in <application moreinfo="none">
+			ser</application> distribution for post-processing
+			of captured messages. It summarizes messages captured
+			by reply status and user-agent header field.
+		    </para>
+		</answer>
+	    </qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			Real-time Traffic Watching
+		    </para>
+		</question>
+		<answer>
+			<para>
+		    Looking at SIP messages in real-time may help to gain
+		    understanding of problems. Though there are commercial
+		    tools available, using a simple, text-oriented tool
+		    such as <application>ngrep</application> makes the job very well thanks to SIP's textual nature.
+			</para>
+		    <example id="usingngrep">
+			<title>Using <application>ngrep</application>
+			</title>
+			<para>In this example, all messages at port 5060
+			which include the string "bkraegelin" are captured
+			and displayed</para>
+			<programlisting format="linespecific">
+[jiri@fox s]$ ngrep bkraegelin@ port 5060
+interface: eth0 (195.37.77.96/255.255.255.240)
+filter: ip and ( port 5060 )
+match: bkraegelin@
+#
+U +0.000000 153.96.14.162:50240 -> 195.37.77.101:5060
+REGISTER sip:iptel.org SIP/2.0.
+Via: SIP/2.0/UDP 153.96.14.162:5060.
+From: sip:[email protected].
+To: sip:[email protected].
+Call-ID: [email protected].
+Date: Thu, 26 Sep 2002 22:03:55 GMT.
+CSeq: 101 REGISTER.
+Expires: 10.
+Content-Length: 0.
+.
+
+#
+U +0.000406 195.37.77.101:5060 -> 153.96.14.162:5060
+SIP/2.0 401 Unauthorized.
+Via: SIP/2.0/UDP 153.96.14.162:5060.
+From: sip:[email protected].
+To: sip:[email protected].
+Call-ID: [email protected].
+CSeq: 101 REGISTER.
+WWW-Authenticate: Digest realm="iptel.org", nonce="3d9385170000000043acbf6ba9c9741790e0c57adee73812", algorithm=MD5.
+Server: Sip EXpress router(0.8.8 (i386/linux)).
+Content-Length: 0.
+Warning: 392 127.0.0.1:5060 "Noisy feedback tells: pid=31604 req_src_ip=153.96.14.162 in_uri=sip:iptel.org out_uri=sip:iptel.org via_cnt==1".
+
+			</programlisting>
+		    </example>
+		</answer>
+	    </qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			Tracing Errors in Server Chains
+		    </para>
+		</question>
+		<answer>
+			<para>
+			    A request may pass any number of proxy servers on
+			    its path to its destination. If an error occurs
+			    in the chain, it is difficult for upstream troubleshooters
+			    and/or users complaining to administrators to learn 
+			    more about error circumstances. 
+			    <application moreinfo="none">ser
+			    </application> does its best and displays extensive
+			    diagnostics information in SIP replies. It allows 
+			    troubleshooters and/or users who report to troubleshooters
+			    to gain additional knowledge about request processing
+			    status. 
+			    This extended debugging information is part of the warning 
+			    header field. See <xref linkend="usingngrep"> for an illustration
+			    of a reply that includes such a warning header field. The header
+			    field contains the following pieces of information:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				Server's IP Address -- good to identify
+				from which server in a chain the reply
+				came.
+				    </para>
+			    </listitem>
+			    <listitem>
+				    <para>
+					Incoming and outgoing URIs -- good to
+					learn for which URI the reply was
+					generated, as it may be rewritten
+					many times in the path. Particularly
+					useful for debugging of numbering plans.
+				    </para>
+			    </listitem>
+			    <listitem>
+				<para>
+					Number of Via header fields in replied
+					request -- that helps in assessment of
+					request path length. Upstream clients would
+					not know otherwise, how far away in terms
+					of SIP hops their requests were replied.
+				</para>
+			    </listitem>
+				<listitem>
+				    <para>
+					Server's process id. That is useful for
+					debugging to discover situations when
+					mutliple servers listen at the same
+					address.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					IP address of previous SIP hop as seen by
+					the SIP server.
+				    </para>
+				</listitem>
+			</itemizedlist>
+		    </para>
+			<para>
+			    If server administrator is not comfortable with
+			    disclosing all this information, he can turn them
+			    off using the <varname>sip_warning</varname> configuration
+			    option.
+			</para>
+		    <para>
+			A nice utility for debugging server chains is
+			<application moreinfo="none">sipsak</application>,
+			Swiss Army Knife, traceroute-like tool for SIP
+			developed at iptel.org. It allows you to send
+			OPTIONS request with low, increasing Max-Forwards 
+			header-fields and follow how it propagates in
+			SIP network. See its webpage at
+			<ulink url="http://sipsak.berlios.de/">
+			    http://sipsak.berlios.de/
+			</ulink>.
+		    </para>
+		    <example>
+			<title>Use of SIPSak for Learning SIP Path</title>
+			<programlisting format="linespecific">
+[jiri@bat sipsak]$ ./sipsak -T -s sip:[email protected]
+warning: IP extract from warning activated to be more informational
+0: 127.0.0.1 (0.456 ms) SIP/2.0 483 Too Many Hops
+1: ?? (31.657 ms) SIP/2.0 200 OK
+	without Contact header
+
+			</programlisting>
+			<para>
+			    Note that in this example, the second hop
+			    server does not issue any warning header fields
+			    in replies and it is thus impossible to display 
+			    its IP address in <application moreinfo="none">
+			    SIPsak</application>'s output.
+			</para>
+		    </example>
+		</answer>
+	    </qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			Watching Server Health
+		    </para>
+		</question>
+		<answer>
+		    <para>
+			Watching Server's operation status in real-time may
+			also be a great aid for trouble-shooting. 
+			<application>ser</application> has an excellent 
+			facility, a FIFO server, which allows UNIX
+			tools to access server's internals. (It is 
+			similar to how Linux tool access Linux kernel
+			via the proc file system.) The FIFO server
+			accepts commands via a FIFO (named pipe) and
+			returns data asked for. Administrators do not
+			need to learn details of the FIFO communication
+			and can serve themselves using a front-end
+			utility <application moreinfo="none">serctl</application>.
+			Of particular interest for 
+			monitoring server's operation are 
+			<application moreinfo="none">serctl</application>
+			commands
+			<command moreinfo="none">ps</command> and
+			<command moreinfo="none">moni</command>.
+			The former displays running 
+			<application moreinfo="none">ser</application>
+			processes, whereas the latter shows statistics.
+		    </para>
+		    <example>
+			<title>serctl ps command</title>
+			<para>
+			    This example shows 10 processes running at a host.
+			    The process 0, "attendant" watches child processes
+			    and terminates all of them if a failure occurs in
+			    any of them. Processes 1-4 listen at local
+			    interface and processes 5-8 listen at Ethernet
+			    interface at port number 5060. Process number
+			    9 runs FIFO server, and process number 10
+			    processes all server timeouts.
+			</para>
+			<programlisting format="linespecific">
+[jiri@fox jiri]$ serctl ps
+0	31590	attendant
+1	31592	receiver child=0 sock=0 @ 127.0.0.1::5060
+2	31595	receiver child=1 sock=0 @ 127.0.0.1::5060
+3	31596	receiver child=2 sock=0 @ 127.0.0.1::5060
+4	31597	receiver child=3 sock=0 @ 127.0.0.1::5060
+5	31604	receiver child=0 sock=1 @ 195.37.77.101::5060
+6	31605	receiver child=1 sock=1 @ 195.37.77.101::5060
+7	31606	receiver child=2 sock=1 @ 195.37.77.101::5060
+8	31610	receiver child=3 sock=1 @ 195.37.77.101::5060
+9	31611	fifo server
+10	31627	timer
+			  
+			</programlisting>
+		    </example>
+		</answer>
+	    </qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			Is Server Alive
+		    </para>
+		</question>
+		<answer>
+		    <para>
+			It is essential for solid operation to know
+			continuously that server is alive. We've been
+			using two tools for this purpose. 
+			<application moreinfo="none">sipsak</application>
+			does a great job of "pinging" a server, which
+			may be used for alerting on unresponsive servers.
+		    </para>
+		    <para>
+			<application moreinfo="none">monit</application> is
+			a server watching utility which alerts when
+			a server dies.
+		    </para>
+		</answer>
+	    </qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			Dealing with DNS
+		    </para>
+		</question>
+		<answer>
+		    <para>
+			SIP standard leverages DNS. Administrators of
+			<application moreinfo="none">ser</application> should
+			be aware of impact of DNS on server's operation.
+			Server's attempt to resolve an unresolvable address
+			may block a server process in terms of seconds. To be
+			safer that the server doesn't stop responding
+			due to being blocked by DNS resolving, we recommend
+			the following practices:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    Start a sufficient number of children processes.
+				    If one is blocked, the other children will
+				    keep serving.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    Use DNS caching. For example, in Linux,
+				    there is an <application moreinfo="none">
+				    nscd</application> daemon available for
+				    this purpose.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    Process transactions statefully if memory
+				    allows. That helps to absorb retransmissions
+				    without having to resolve DNS for each of
+				    them.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		</answer>
+	    </qandaentry>
+		<qandaentry>
+			<question>
+				<para>
+					Logging
+				</para>
+			</question>
+			<answer>
+			<anchor id="logging">
+			<para>
+			    <application>ser</application> by default logs
+			    to <application>syslog</application> facility.
+			    It is very useful to watch log messages for
+			    abnormal behaviour. Log messages, subject to
+			    <application>syslog</application> configuration
+			    may be stored at different files, or even at remote
+			    systems. A typical location of the log file is
+			    <filename>/var/log/messages</filename>.
+			</para>
+			<note>
+			    <para>
+				One can also use other <application>syslogd</application>
+				implementation. <application>metalog</application>
+				(<ulink url="http://http://metalog.sourceforge.net//">
+				    http://metalog.sourceforge.net/
+				</ulink>)
+				features regular expression matching that enables
+				to filter and group log messages.
+			    </para>
+			</note>
+			<para>
+			    For the purpose of debugging configuration scripts, one may
+			    want to redirect log messages to console not to pollute
+			    syslog files. To do so configure <application moreinfo="none">ser</application>
+			    in the following way:
+			    <itemizedlist>
+				<listitem>
+				    <para>
+					Attach ser to console by setting <varname>fork=no</varname>.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Set explicitely at which address 
+					<application moreinfo="none">ser</application>
+					should be listening, e.g., <varname>listen=192.168.2.16</varname>.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Redirect log messages to standard error by setting
+					<varname>log_stderror=yes</varname>
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Set appropriately high log level. (Be sure that you redirected logging
+					to standard output. Flooding system logs with many detailed messages
+					would make the logs difficult to read and use.) You can set the global
+					logging threshold value with the option <varname>debug=nr</varname>,
+					where the higher <varname>nr</varname> the more detailed output.
+					If you wish to set log level only for some script events, include
+					the desired log level as the first parameter of the
+					<command moreinfo="none">log</command> action in your script.
+					The messages will be then printed if <command moreinfo="none">log</command>'s
+					level is lower than the global threshold, i.e., the lower the more
+					noisy output you get.
+					<example>
+					    <title>Logging Script</title>
+					    <programlisting format="linespecific">
+&logging;
+					    </programlisting>
+					    <para>
+						The following SIP message causes then logging output as shown
+						bellow.
+					    </para>
+					    <programlisting format="linespecific">
+REGISTER sip:192.168.2.16 SIP/2.0
+Via: SIP/2.0/UDP 192.168.2.33:5060
+From: sip:[email protected]
+To: sip:[email protected]
+Call-ID: [email protected]
+Date: Thu, 27 Feb 2003 15:10:52 GMT
+CSeq: 101 REGISTER
+User-Agent: CSCO/4
+Contact: sip:[email protected]:5060
+Content-Length: 0
+Expires: 600                                 
+					    </programlisting>
+					    <programlisting format="linespecific">
+[jiri@cat sip_router]$ ./ser -f examples/logging.cfg 
+Listening on 
+              192.168.2.16 [192.168.2.16]::5060
+Aliases: cat.iptel.org:5060 cat:5060 
+WARNING: no fork mode 
+ 0(0) INFO: udp_init: SO_RCVBUF is initially 65535
+ 0(0) INFO: udp_init: SO_RCVBUF is finally 131070
+ 0(17379) REGISTER received
+ 0(17379) request for other domain received					
+					    </programlisting>
+					</example>
+				    </para>
+				</listitem>
+			    </itemizedlist>
+			</para>
+			</answer>
+		</qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			Labeling Outbound Requests
+		    </para>
+		</question>
+		<answer>
+		    <para>
+		    Without knowing, which pieces of script code a relayed
+		    request visited, trouble-shooting would be difficult.
+		    Scripts typically apply different processing to
+		    different routes such as to IP phones and PSTN
+		    gateways. We thus recommend to label outgoing
+		    requests with a label describing the type of processing
+		    applied to the request.
+			</para>
+		    <para>
+			Attaching "routing-history" hints to relayed
+			requests is as easy as using the 
+			<command moreinfo="none">append_hf</command>
+			action exported by textops module. The following
+			example shows how different labels are attached
+			to requests to which different routing logic
+			was applied.
+			<example>
+			    <title>"Routing-history" labels</title>
+			    <programlisting format="linespecific">
+# is the request for our domain?
+# if so, process it using UsrLoc and label it so.
+if (uri=~[@:\.]domain.foo") {
+   if (!lookup("location")) {
+    sl_send_reply("404", "Not Found");
+    break;
+   };
+   # user found -- forward to him and label the request
+   append_hf("P-hint: USRLOC\r\n");
+} else {
+# it is an outbound request to some other domain --
+# indicate it in the routing-history label
+   append_hf("P-hint: OUTBOUND\r\n");
+};
+t_relay();
+			    </programlisting>
+			    <para>
+				This is how such a labeled requests looks
+				like. The last header field includes
+				a label indicating the script processed
+				the request as outbound.
+			    </para>
+			    <programlisting format="linespecific">
+#
+U 2002/09/26 02:03:09.807288 195.37.77.101:5060 -> 203.122.14.122:5060
+SUBSCRIBE sip:[email protected] SIP/2.0.
+Max-Forwards: 10.
+Via: SIP/2.0/UDP 195.37.77.101;branch=53.b44e9693.0.
+Via: SIP/2.0/UDP 203.122.14.115:16819.
+From: sip:[email protected];tag=5c7cecb3-cfa2-491d-a0eb-72195d4054c4.
+To: sip:[email protected].
+Call-ID: [email protected].
+CSeq: 2 SUBSCRIBE.
+Contact: sip:203.122.14.115:16819.
+User-Agent: Windows RTC/1.0.
+Proxy-Authorization: Digest username="rajeshacl", realm="iptel.org", algorithm="MD5", uri="sip:[email protected]", nonce="3d924fe900000000fd6227db9e565b73c465225d94b2a938", response="a855233f61d409a791f077cbe184d3e3".
+Expires: 1800.
+Content-Length: 0.
+P-hint: OUTBOUND.			    </programlisting>
+			</example>
+		</para>
+		</answer>
+	    </qandaentry>
+	</qandaset>
+	</section> <!-- operational practises -->
+
+	<section>
+	    <title>HOWTOs</title>
+	    <para>
+		This section is a "cookbook" for dealing with common tasks,
+		such as user management or controlling access
+		to PSTN gateways.
+	    </para>
+	    <section>
+		<title>User Management</title>
+
+			<para>
+			    There are two tasks related to management of SIP users:
+			    maintaining user accounts and maintaining user contacts.
+			    Both these jobs can be done using the 
+			    <application moreinfo="none">serctl</application>
+			    command-line tool. Also, the complimentary web
+			    interface, <application moreinfo="none">serweb</application>,
+			    can be used for this purpose as well.
+			</para>
+			<para>
+			    If user authentication is turned on, which is a highly
+			    advisable practice, user account must be created before
+			    a user can log in. To create a new user account, call the
+			    <command moreinfo="none">serctl add</command> utility
+			    with username, password and email as parameters. It
+			    is important that the environment <varname>SIP_DOMAIN</varname>
+			    is set to your realm and matches realm values used in
+			    your script. The realm value is used for calculation
+			    of credentials stored in subscriber database, which are
+			    bound permanently to this value.
+			    <screen format="linespecific">
+[jiri@cat gen_ha1]$ export SIP_DOMAIN=foo.bar
+[jiri@cat gen_ha1]$ serctl add newuser secret [email protected]
+MySql Password: 
+new user added
+			    </screen>
+			</para>
+			<para><application moreinfo="none">serctl</application> can
+			    also change user's password or remove existing accounts
+			    from system permanently.
+			    <screen format="linespecific">
+[jiri@cat gen_ha1]$ serctl passwd newuser newpassword
+MySql Password: 
+password change succeeded
+[jiri@cat gen_ha1]$ serctl rm newuser                
+MySql Password: 
+user removed
+			    </screen>
+			</para>
+			<para>
+			    User contacts are typically automatically uploaded by SIP phones
+			    to server during registration process and administrators do not
+			    need to worry about them. However, users
+			    may wish to append permanent contacts to PSTN gateways
+			    or to locations in other administrative domains. 
+			    To manipulate the contacts in such cases, use
+			    <application moreinfo="none">serctl ul</application>
+			    tool. Note that this is the only correct way
+			    to update contacts -- direct changes to back-end
+			    MySql database do not affect server's memory. Also note,
+			    that if persistence is turned off (usrloc "db_mode"
+			    parameter set to "0"), all contacts are gone on server
+			    reboot. Make sure that persistence is enabled if you
+			    add permanent contacts.
+			</para>
+			<para>
+			    To add a new permanent contact for a user, call 
+			    <application moreinfo="none">serctl ul add &lt;username&gt
+			    &lt;contact&gt;</application>. To delete 
+			    all user's contacts, call 
+			    <application>serctl ul rm &lt;username&gt;</application>.
+			    <application moreinfo="none">serctl ul show &lt;username&gt;</application>
+			    prints all current user's contacts.
+			    <screen format="linespecific">
+[jiri@cat gen_ha1]$ serctl ul add newuser sip:[email protected]
+sip:[email protected]
+200 Added to table
+('newuser','sip:[email protected]') to 'location'
+[jiri@cat gen_ha1]$ serctl ul show newuser
+&lt;sip:[email protected]&gt;;q=1.00;expires=1073741812
+[jiri@cat gen_ha1]$ serctl ul rm newuser  
+200 user (location, newuser) deleted
+[jiri@cat gen_ha1]$ serctl ul show newuser
+404 Username newuser in table location not found
+			    </screen>
+			</para>
+	    </section> <!-- user management -->
+	    <section>
+		<title>User Aliases</title>
+
+			<para>
+			    Frequently, it is desirable for a user to have multiple
+			    addresses in a domain. For example, a user with username "john.doe" wants to be
+			    reachable at a shorter address "john" or at a nummerical address
+			    "12335", so that PSTN callers with digits-only key-pad can reach
+			    him too.
+			</para>
+			<para>
+			    With <application moreinfo="none">ser</application>, you can maintain
+			    a special user-location table and translate existing aliases to canonical
+			    usernames using the <command moreinfo="none">lookup</command>
+			    action from usrloc module. The following script fragment demonstrates
+			    use of <command moreinfo="none">lookup</command> for this purpose.
+			    <example>
+				<title>Configuration of Use of Aliases</title>
+				<programlisting format="linespecific">
+if (!uri==myself) { # request not for our domain...
+  route(1); # go somewhere else, where outbound requests are processed
+  break;
+};
+# the request is for our domain -- process registrations first
+if (method=="REGISTER") { route(3); break; };
+
+# look now, if there is an alias in the "aliases" table; don't care
+# about return value: whether there is some or not, move ahead then
+lookup("aliases");
+
+# there may be aliases which translate to other domain and for which
+# local processing is not appropriate; check again, if after the
+# alias translation, the request is still for us
+if (!uri==myself) { route(1); break; };
+
+# continue with processing for our domain...
+...
+  
+				</programlisting>
+			    </example>
+			</para>
+			<para>
+			    The table with aliases is updated using the
+			    <application moreinfo="none">serctl</application>
+			    tool. <application moreinfo="none">
+			    serctl alias add &lt;alias&gt; &lt;uri&gt;</application>
+			    adds a new alias, 
+			    <application moreinfo="none">serctl alias show &lt;user&gt;</application>
+			    prints an existing alias, and
+			    <application moreinfo="none">serctl alias rm &lt;user&gt;</application>
+			    removes it.
+			    <screen format="linespecific">
+[jiri@cat sip_router]$ serctl alias add 1234 sip:[email protected]
+sip:[email protected]
+200 Added to table
+('1234','sip:[email protected]') to 'aliases'
+[jiri@cat sip_router]$ serctl alias add john sip:[email protected]
+sip:[email protected]
+200 Added to table
+('john','sip:[email protected]') to 'aliases'
+[jiri@cat sip_router]$ serctl alias show john                    
+&lt;sip:[email protected]&gt;;q=1.00;expires=1073741811
+[jiri@cat sip_router]$ serctl alias rm john  
+200 user (aliases, john) deleted				
+			    </screen>
+			</para>
+			<para>
+			    Note that persitence needs to be turned on in usrloc
+			    module. All changes to aliases will be otherwise lost
+			    on server reboot. To enable persistence, set the
+			    db_mode usrloc parameter to a non-zero value.
+			    <programlisting format="linespecific">
+# ....load module ...
+loadmodule "modules/usrloc/usrloc.so"
+# ... turn on persistence -- all changes to user tables are immediately
+# flushed to mysql
+modparam("usrloc", "db_mode",   1)
+# the SQL address:
+modparam("usrloc", "db_url","sql://ser:secret@dbhost/ser")
+			    </programlisting>
+			</para>
+	    </section> <!-- user aliases -->
+	    <section id=acl>
+		<title>Access Control (PSTN Gateway)</title>
+			<para>
+			    It is sometimes important to exercise some sort of
+			    access control. A typical use case is when 
+			    <application moreinfo="none">ser</application> is used
+			    to guard a PSTN gateway. If a gateway was not well guarded,
+			    unauthorized users would be able to use it to terminate calls in PSTN,
+			    and cause high charges to its operator.
+			</para>
+			<para>
+			    There are few issues you need to understand when
+			    configuring <application moreinfo="none">ser</application>
+			    for this purpose. First, if a gateway is built or configured to
+			    accept calls from anywhere, callers may easily bypass your
+			    access control server and communicate with the gateway
+			    directly. You then need to enforce at transport layer
+			    that signaling is only accepted if coming via
+			    <application moreinfo="none">ser</application> and
+			    deny SIP packets coming from other hosts and port numbers.
+			    Your network must be configured not to allow forged
+			    IP addresses. Also, you need to turn on record-routing
+			    to assure that all session requests will travel via 
+			    <application moreinfo="none">ser</application>.			    
+			    Otherwise, caller's devices would send subsequent SIP requests 
+			    directly to your gateway, which would fail because of transport 
+			    filtering.
+			</para>
+			<para>
+			    Authorization (i.e., the process of determining who may call where)
+			    is facilitated in <application moreinfo="none">ser</application>
+			    using <emphasis>group membership</emphasis> concept. Scripts make 
+			    decisions on whether a caller is authorized to make a call to
+			    a specific destination based on user's membership in a group.
+			    For example a policy may be set up to allow calls to international
+			    destinations only to users, who are members of an "int" group.			    
+			    Before user's group membership is checked, his identity
+			    must be verified first. Without cryptographic verification of user's
+			    identity, it would be impossible to assert that a caller really
+			    is who he claims to be.
+			</para>
+			<para>
+			    The following script demonstrates, how to configure <application moreinfo="none">ser</application>
+			    as an access control server for a PSTN gateway. The script verifies user
+			    identity using digest authentication, checks user's privileges,
+			    and forces all requests to visit the server.
+			    <example>
+				<title>Script for Gateway Access Control</title>
+				<programlisting format="linespecific">
+&gatewayacl;
+				</programlisting>
+			    </example>
+			</para>
+			<para>
+			    Use the <application moreinfo="none">serctl</application> tool to
+			    maintain group membership. 
+			    <application moreinfo="none">serctl acl grant &lt;username&gt; &lt;group&gt;</application>
+			    makes a user member of a group, 
+			    <application>serctl acl show &lt;username&gt;</application> shows groups
+			    of which a user is member, and
+			    <application>serctl acl revoke &lt;username&gt; [&lt;group&gt;]</application>
+			    revokes user's membership in one or all groups.
+			    <screen format="linespecific">
+[jiri@cat sip_router]$ serctl acl grant john int
+MySql Password: 
++------+-----+---------------------+
+| user | grp | last_modified       |
++------+-----+---------------------+
+| john | int | 2002-12-08 02:09:20 |
++------+-----+---------------------+
+			    </screen>
+			</para>
+	    </section> <!-- access control -->
+	    <section>
+		<title>Accounting</title>
+			<para>
+			    In some scenarios, like termination of calls in PSTN, SIP administrators
+			    may wish to keep track of placed calls. <application moreinfo="none">ser</application>
+			    can be configured to report on completed transactions. Reports are sent
+			    by default to <application moreinfo="none">syslog</application> facility.
+			    Experimental support for RADIUS and mysql accounting exists as well.
+			</para>
+			<para>
+			    Note that <application moreinfo="none">ser</application> is no way 
+			    call-stateful. It reports on completed transactions, i.e., after 
+			    a successful call set up is reported, it drops any call-related 
+			    state. When a call is terminated, transactional state for BYE request
+			    is created and forgotten again after the transaction completes.
+			    This is a feature and not a bug -- keeping only transactional
+			    state allows for significantly higher scalability. It is then
+			    up to the accounting application to correlate call initiation
+			    and termination events.
+			</para>
+			<para>
+			    To enable call accounting, tm and acc modules need to be loaded,
+			    requests need to be processed statefuly and labeled for
+			    accounting. That means, if you want a transaction to be reported,
+				the initial request must have taken the path 
+				"<command>setflag(X)</command>, <command>t_relay</command>"
+				in <application>ser</application> script. X must have the
+				value configured in <varname>acc_flag</varname>
+				configuration option.
+			</para>
+			<para>
+				Also note, that by default only transactions that initiate
+				a SIP dialog (typically INVITE) visit a proxy server.
+				Subsequent transactions are exhanged directly between
+				end-devices, do not visit proxy server and cannot be
+				reported. To be able to report on subsequent transactions,
+				you need to force them visit proxy server by turning 
+				record-routing on. 
+			</para>
+			<para>
+				
+			    <example>
+				<title>Configuration with Enabled Accounting</title>
+				<programlisting format="linespecific">
+&accountingexample;
+				</programlisting>
+			    </example>
+			</para>
+	    </section> <!-- accounting -->
+	    <section>
+		<title>Reliability</title>
+
+			<para>
+			    It is essential to guarantee continuous
+			    service operation even under erroneous conditions, 
+			    such as host or network failure. The major issue in such
+			    situations is transfer of operation to a backup
+			    infrastructure and making clients use it.
+			</para>
+			<para>
+			    The SIP standard's use of DNS SRV records has been
+			    explicitly constructed to handle with server failures.
+			    There may be multiple servers responsible for a domain
+			    and referred to by DNS. If it is impossible to communicate
+			    with a primary server, a client can proceed to another one.
+			    Backup servers may be located in a different geographic
+			    area to minimize risk caused by areal operational
+			    disasters: lack of power, flooding, earthquake, etc.
+			    <note>
+				<sidebar>
+				    <para>Unless there are redundant DNS
+				    servers, fail-over capability cannot be guaranteed.
+				    </para>
+				</sidebar>
+			    </note>
+			    Unfortunately, at the moment of writing this documentation
+			    (end of December 2002) only very few SIP products
+			    actually implement the DNS fail-over mechanism. Unless
+			    networks with SIP devices supporting this mechanism are
+			    built, alternative mechanisms must be used to force 
+			    clients to use backup servers. Such a mechanism is
+			    disconnecting primary server and replacing him with
+			    a backup server locally.
+			    It unfortunately precludes geographic dispersion and
+			    requires network multihoming to avoid dependency on
+			    single IP access. Another method is to update DNS
+			    when failure of the primary server is detected.
+			    The primary drawback of this method is its latency:
+			    it may take long time until all clients learn to use
+			    the new server.
+			</para>
+			<para>
+			    The easier part of the redundancy story is replication of 
+			    <application moreinfo="none">ser</application>
+			    data. <application moreinfo="none">ser</application>
+			    relies on replication capabilities of its back-end database.
+			    This works with one exception: user location database.
+			    User location database is a frequently accessed table,
+			    which is thus cached in server's memory to improve
+			    performance. Back-end replication does not affect
+			    in-memory tables, unless server reboots. To facilitate
+			    replication of user location database, 
+			    server's SIP replication feature must be enabled
+			    in parallel with back-end replication.
+			</para>
+			<para>
+			    The design idea of replication of user location database
+			    is easy: Replicate any successful REGISTER requests to
+			    a peer server. To assure that digest credentials can
+			    be properly verified, both servers need to use the same
+			    digest generation secret and maintain synchronized time.
+			    A known limitation of this method is it does not replicate
+			    user contacts entered in another way, for example using
+			    web interface through FIFO server.
+			    The following script example shows configuration of
+			    a server that replicates all REGISTERs.
+			    <example>
+				<title>Script for Replication of User Contacts</title>
+				<programlisting format="linespecific">
+&replicateexample;				    
+				</programlisting>
+			    </example>
+			</para>
+	    </section> <!-- reliability -->
+	    <section>
+		<title>Stateful versus Stateless Forwarding</title>
+		<para>
+		    <application moreinfo="none">ser</application> allows both stateless
+		    and stateful request processing. This memo explains what are pros and cons of
+		    using each method. The rule of thumb is "stateless for scalability,
+		    stateful for services". If you are unsure which you need, stateful
+		    is a safer choice which supports more usage scenarios.
+		</para>
+			<para>
+			    Stateless forwarding with the
+			    <command moreinfo="none">forward(uri:host, uri:port)</command> action
+			    guarantees high scalability. It withstands high load and
+			    does not run out of memory. A perfect use of stateless forwarding
+			    is load distribution.
+			</para>
+			<para>
+			    Stateful forwarding using the <command moreinfo="none">t_relay()</command>
+			    action is known to scale worse. It can quickly run out of memory and
+			    consumes more CPU time. Nevertheless, there are scenarios which are
+			    not implementable without stateful processing. In particular:
+			    <itemizedlist>
+				<listitem>
+				    <para>
+					<emphasis>Accounting</emphasis> requires stateful processing
+					to be able to collect transaction status and issue a single
+					report when a transaction completes.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					<emphasis>Forking</emphasis> only works with stateful forwarding.
+					Stateless forwarding only forwards to the default URI out of the
+					whole destination set.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					<emphasis>DNS resolution</emphasis>. DNS resolution may be
+					better server with stateful processing. If a request is forwarded
+					to a destination whose address takes long time to resolve,
+					a server process is blocked and unresponsive. Subsequent 
+					request retransmissions from client will cause other processes
+					to block too if requests are processed statelessly. As a result,
+					<application moreinfo="none">ser</application> will quickly
+					run out of available processes. With stateful forwarding,
+					retransmissions are absorbed and do not cause blocking of
+					another process.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					<emphasis>Forwarding Services</emphasis>. All sort of services 
+					with the "forward_on_event" logic, which rely on 
+					<command moreinfo="none">t_on_negative</command> tm
+					action must be processed statefuly.
+				    </para>
+				</listitem>
+			<listitem>
+			    <para>
+				<emphasis>
+				    Fail-over.
+				</emphasis>
+				If you wish to try out another destination, after a primary destination
+				failed you need to use stateful processing. With stateless processing
+				you never know with what status a forwarded request completed downstream
+				because you immediately release all processing information after the 
+				request is sent out. 
+
+				<note>
+				    <para>
+					Positive return value of stateless
+					<command moreinfo="none">forward</command> action only indicates that
+					a request was successfuly sent out, and does not gain any knowledge
+					about whether it was successfuly received or replied. Neither does
+					the return value of
+					the stateful <command moreinfo="none">t_relay</command> action family
+					gain you this knowledge. However, these actions store transactional
+					context with which includes original request and allows you to
+					take an action when a negative reply comes back or a timer strikes.
+					See <xref linkend="replyprocessingsection"> for an example script 
+					which launches another
+					branch if the first try fails.
+				    </para>
+				</note>
+
+			    </para>
+			</listitem>
+			    </itemizedlist>
+			</para>
+	    </section> <!-- stateful vs. stateless -->
+	    <section>
+		<title>Serving Multiple Domains</title>
+			<para>
+			    <application moreinfo="none">ser</application> can be configured to
+			    serve multiple domains. To do so, you need to take the following steps:
+			    <orderedlist>
+				<listitem id="createtable">
+				    <para>
+					Create separate subscriber and location database table
+					for each domain served and name them uniquely.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Configure your script to distinguish between multiple
+					served domains. Use regular expressions for domain
+					matching as described in <xref linkend="redomainmatching">.
+				    </para>
+				</listitem>
+				<listitem>
+				    <para>
+					Update table names in usrloc and auth actions to reflect
+					names you created in <xref linkend="createtable">.
+				    </para>
+				</listitem>
+				
+			    </orderedlist>
+			</para>
+	    </section> <!-- multiple domains -->
+	    <section id="missedcalls">
+		<title>Reporting Missed Calls</title>
+			<para>
+			    <application moreinfo="none">ser</application> can report missed
+			    calls via <application moreinfo="none">syslog</application> facility
+			    or to mysql. Mysql reporting can be utilized by 
+			    <application moreinfo="none">ser</application>'s 
+			    complementary web-interface, <application moreinfo="none">serweb</application>.
+			    (See more in <xref linkend="serweb">).
+			</para>
+			<para>
+			    Reporting on missed calls is enabled by acc module.
+			    There are two cases, on which you want to report. The first
+			    case is when a callee is off-line. The other case is when
+			    a user is on-line, but call establishment fails. There
+			    may be many failure reasons (call cancellation, inactive phone,
+			    busy phone, server timer, etc.), all of them leading to
+			    a negative (>=300) reply sent to caller. The acc module
+			    can be configured to issue a missed-call report whenever
+			    a transaction completes with a negative status. Two following
+			    script fragment deals with both cases.
+			</para>
+			<para>
+			    First, it reports
+			    on calls missed due to off-line callee status
+			    using the <command moreinfo="none">acc_request</command>
+			    action. The action is wrapped in transactional
+			    processing (<command moreinfo="none">t_newtran</command>)
+			    to guarantee that reports are not
+			    duplicated on receipt of retransmissions.
+			    </para>
+			<para>
+			    Secondly, transaction to on-line users are marked
+			    to be reported on failure. That is what the 
+			    <command moreinfo="none">setflag(3)</command> action
+			    is responsible for, along with the configuration option
+			    "missed_flag". This option configures <application moreinfo="none">ser</application>
+			    to report on all transactions, which were marked
+			    with flag 3.			   
+			    <programlisting format="linespecific">
+loadmodule("modules/tm/tm.so");
+loadmodule("modules/acc/acc.so");
+....
+# if a call is labeled using setflag(3) and is missed, it will
+# be reported
+...
+modparam("acc", "missed_flag", 3 );
+if (!lookup("location")) {
+     # call invitations to off-line users are reported using the
+     # acc_request action; to avoid duplicate reports on request
+     # retransmissions, request is processed statefuly (t_newtran,
+     # t_reply)
+     if ((method=="INVITE" || method=="ACK") && t_newtran() ) {
+          t_reply("404", "Not Found");
+	  acc_request("404 Not Found");
+          break;
+     };
+     # all other requests to off-line users are simply replied
+     # statelessly and no reports are issued
+    sl_send_reply("404", "Not Found");
+    break;
+} else {
+     # user on-line; report on failed transactions; mark the
+     # transaction for reporting using the same number as 
+     # configured above; if the call is really missed, a report
+     # will be issued
+     setflag(3);
+     # forward to user's current destination
+     t_relay();
+     break;
+};
+			    </programlisting>
+			    
+			</para>
+	    </section> <!-- missed calls -->
+	    <section>
+		<title>NAT Traversal</title>
+		<para>
+		    NATs are worst things that ever happened to SIP. These devices
+		    are very popular because they help to conserve IP address space
+		    and save money charged for IP addresses. Unfortunately, they
+		    translate addresses in a way which is not compatible with SIP.
+		    SIP advertises receiver addresses in its payload. The advertised
+		    addresses are invalid out of NATted networks. As a result,
+		    SIP communication does not work accross NATs without extra
+		    effort.
+		</para>
+		<para>
+		    There are few methods that may be deployed to traverse NATs.
+		    How proper their use is depends on the deployment scenario.
+		    Unfortunatelly, all the methods have some limitations and
+		    there is no straight-forward solution addressing all
+		    scenarios. Note that none of these methods takes explicit
+		    support in <application moreinfo="none">ser</application>.
+		</para>
+		<para>
+		    The first issue is whether SIP users are in control of 
+		    their NATs. If not (NATs are either operated by ISP or
+		    they are sealed to prevent users setting them up), the
+		    only method is use of a STUN-enabled phone. STUN is 
+		    a very simple protocol used to fool NAT in such a way,
+		    they permit SIP sessions. Currently, we are aware of
+		    one softphone (kphone) and one hardphone (snom) with
+		    STUN support, other vendors are working on STUN support
+		    too. Unfortunately, STUN gives no NAT traversal
+		    guarantee -- there are types of NATs, so called
+		    symmetric NATs, over which STUN fails to work.
+		    <note>
+			<para>
+			    There is actually yet another method to address
+			    SIP-unaware, user-uncontrolled NATs. It is based
+			    on a proxy server, which relays all signaling and
+			    media and mangles packets to make them more
+			    NAT-friendly. The very serious problem with this
+			    method is it does not scale.
+			</para>
+		    </note>
+		</para>
+		<para>
+		    If users are in control of their own NAT, as typically residential
+		    users are, they can still use STUN. However, they may use other
+		    alternatives too. One of them is to replace their NAT with
+		    a SIP-aware NAT. Such NATs have built-in SIP awareness,
+		    that patches problems caused by address translations. Prices
+		    of such devices are getting low and there are available
+		    implementations (Intertex, Cisco/PIX). No special support
+		    in phones is needed.
+		</para>
+		<para>
+		    Other emerging option is UPnP. UPnP is a protocol that allows
+		    phones to negotiate with NAT boxes. You need UPnP support in
+		    both, NAT and phones. As UPnP NATs are quite affordable,
+		    costs are not an obstacle. Currently, we are aware of one
+		    SIP phone (SNOM) with UPnP support.
+		</para>
+		<para>
+		    Geeks not wishing to upgrade their firewall to a SIP-aware or
+		    UPnP-enabled one may try to configure static address translation.
+		    That takes phones with configuration ability to use fixed port
+		    numbers and advertise outside address in signaling. Cisco phones
+		    have this capability, for example. The NAT devices need to
+		    be configured to translate outside port ranges to the 
+		    ranges configured in phones.		    
+		</para>
+	    </section> <!-- NAT traversal -->
+	    <section>
+		<title>Authentication Policy: Prevention of Unauthorized Domain 
+		    Name Use in From and More</title>
+		<para>
+		    Malicous users can claim a name of domain, to which they do 
+		    not administratively belong, in From header field. This
+		    behaviour cannot be generally prevented. The reason is
+		    that requests with such a faked header field do not need
+		    to visit servers of the domain in question. However, if they
+		    do so, it is desirable to assure that users claiming
+		    membership in a domain are actually associated with it.
+		    Otherwise the faked requests would be relayed and appear
+		    as coming from the domain, which would increase
+		    credibility of the faked address and decrease credibility of
+		    the proxy server.
+		</para>
+		<para>
+		    Preventing unathorized domain name use in relayed requests 
+		    is not difficult.
+		    One needs to authenticate each request with name of the
+		    served domain in From header field. To do so, one can
+		    search for such a header field using <command moreinfo="none">search</command>
+		    action (textops module) and force authentication if the
+		    search succeeds.
+		    <note>
+			<para>
+			    A straight-forward solution might be to authenticate
+			    ALL requests. However, that only works in closed
+			    networks in which all users have an account in the
+			    server domain. In open networks, it is desirable to permit
+			    incoming calls from callers from other domains without
+			    any authentication. For example, a company may wish
+			    to accept calls from unknown callers who are
+			    new prospective customers.
+			    
+			</para>
+		    </note>
+		    <programlisting format="linespecific">
+# does the user claim our domain "foo.bar" in From?
+if (search("^(f|From):.*foo.bar")) {
+        # if so, verify credential
+	if (!proxy_authorize("foo.bar", "subscriber")) { 
+              # don't proceed if credentials broken; challenge
+	      proxy_challenge("foo.bar", "0");
+	      break;
+        };
+};
+		    </programlisting>
+		</para>
+		<para>
+		    In general, the authentication policy may be very rich. You may not
+		    forget each request deserves its own security and you need to 
+		    decide whether it shall be authenticated or not. As mentioned
+		    above, in closed networks, you may want to authenticate absolutely 
+		    every request. That however prohibits traffic from users from
+		    other domains. A pseudo-example of a reasonable policy is attached:
+		    it looks whether a request is registration, it claims to originate
+		    from our domain in From header field, or is a local request to
+		    another domain.
+		    <programlisting format="linespecific">
+# (example provided by Michael Graff on [serusers] mailing list
+if (to me):
+    if register
+          www_authorize or fail if not a valid register
+          done
+    if claiming to be "From" one of the domains I accept registrations for
+          proxy_authorize
+          done
+    if not to me (I'm relaying for a local phone to an external address)
+          proxy_authorize
+          done
+		    </programlisting>
+		</para>
+		<para>
+		    You also may want to apply additional restriction to how
+		    digest username relates to usernames claimed in From and
+		    To header fields. For example, the <command moreinfo="none">check_to</command>
+		    action enforces the digest id to be equal to username
+		    in To header fields. That is good in preventing someone
+		    with valid credentials to register as someone else
+		    (e.g., sending a REGISTER with valid credentials of
+		    "joe" and To belonging to "alice"). Similarly,
+		    <command moreinfo="none">check_from</command> is used
+		    to enforce username in  from to equal to digest id.
+		    <note>
+			<para>
+			    There may be a need for a more complex relationship
+			    between From/To username and digest id. For example,
+			    providers with an established user/password database
+			    may wish to keep using it, whereas permitting users
+			    to claim some telephone numbers in From. To address
+			    such needs generally, there needs to be a 1:N mapping
+			    between digest id and all usernames that are acceptable
+			    for it. This is being addressed in a newly contributed
+			    module "domain", which also addresses more generally
+			    issues of domain matching for multidomain scenarios.
+			</para>
+		    </note>
+		</para>
+		<para>
+		    Other operational aspect affecting the authentication policy
+		    is guarding PSTN gateways (see <xref linkend="acl">). There
+		    may be destinations that are given away for free whereas
+		    other destinations may require access control using
+		    group membership, to which  authentication is a prerequisity.
+		</para>
+
+	    </section> <!-- authentication policy, faked froms -->
+	    <section>
+		<title>Connecting to PBX Voicemail Using a Cisco Gateway</title>
+		<para>
+		    In some networks, administrators may wish to utilize their
+		    PBX voicemail systems behind PSTN gateways. There is a practical problem
+		    in many network settings: it is not clear for whom a call to
+		    voicemail is. If voicemail is identified by a single number,
+		    which is then put in INVITE's URI, there is no easy way to
+		    learn for whom a message should be recorded. PBX voicemail
+		    utilize that PSTN protocols signal the number of originally
+		    called party. If you wish to make the PBX voicemail work,
+		    you need to convey the number in SIP and translate it in
+		    PSTN gateways to its PSTN counterpart.
+		</para>
+		<para>
+		    There may be many different ways to achieve this scenario. Here
+		    we describe the proprietary mechanism Cisco gateways use and how to 
+		    configure <application moreinfo="none">ser</application> to
+		    make the gateways happy. Cisco gateways expect the number
+		    of originally called party to be located in proprietary
+		    <varname>CC-Diversion</varname> header field. When a SIP 
+		    INVITE sent via a PSTN gateway to PBX voicemail has number
+		    of originally called party in the header field, the voicemail
+		    system knows for whom the incoming message is. That is at least
+		    true for AS5300/2600 with Cisco IOS 12.2.(2)XB connected to
+		    Nortel pbxs via PRI. (On the other hand, 12.2.(7b) is known
+		    not to work in this scenario.)
+		</para>
+		<para>
+		    <application moreinfo="none">ser</application> needs then to
+		    be configured to append the <varname>CC-Diversion</varname>
+		    header field name for INVITEs sent to PBX voicemail.
+		    The following script shows that: when initial forwarding
+		    fails (nobody replies, busy is received, etc.), a new branch
+		    is initiated to the pbx's phone number. 
+		    <command moreinfo="none">append_urihf</command> is used to
+		    append the <varname>CC-Diversion</varname> header field. It
+		    takes two parameters: prefix, which includes header name,
+		    and suffix which takes header field separator. 
+		    <command moreinfo="none">append_urihf</command> inserts
+		    original URI between those two.
+		    <example>
+			<title>Forwarding to PBX/Voicemail via Cisco Gateways</title>
+			<programlisting format="linespecific">
+&ccdiversion;
+			</programlisting>
+		    </example>
+		    
+		</para>
+	    </section>
+	</section> <!-- howtos -->
+
+	<section>
+	    <title>Troubleshooting</title>
+	    <para>
+		This section gathers practices how to deal with errors
+		known to occur frequently. To understand how to watch
+		SIP messages, server logs, and in genereal how to
+		troubleshoot, read also <xref linkend="operationalpractices">. 
+	    </para>
+	    <qandaset>
+		<qandaentry>
+		    <question>
+			<para>
+			SIP requests are replied by <application>ser</application> with
+			"483 Too Many Hops" or "513 Message Too Large"
+		        </para>
+		    </question>
+
+		    <answer>
+			<para>
+			    In both cases, the reason is probably an error in
+			    request routing script which caused an infinite loop.
+			    You can easily verify whether this happens by
+			    watching SIP traffic on loopback interface. A typical
+			    reason for misrouting is a failure to match local
+			    domain correctly. If a server fails to recognize
+			    a request for itself, it will try to forward it
+			    to current URI in believe it would forward them
+			    to a foreign domain. Alas, it forwards the request
+			    to itself again. This continues to happen until
+			    value of max_forwards header field reaches zero
+			    or the request grows too big. Solutions is easy:
+			    make sure that domain matching is correctly
+			    configured. See <xref linkend="domainmatching">
+			    for more information how to get it right.
+			</para>
+		    </answer>		    
+		</qandaentry>
+		<qandaentry>
+			
+		    <question>
+			        
+			<para>
+			
+			    Windows Messenger authentication fails.
+			</para>
+		    </question>
+		    <answer>
+			<anchor id="msmbug">
+			<para>
+			    The most likely reason for this problem is a bug
+			    in Windows Messenger. WM only authenticates if
+			    server name in request URI equals authentication
+			    realm. After a challenge is sent by SIP server,
+			    WM does not resubmit the challenged request at all
+			    and pops up authentication window again.
+			    If you want to authenticate WM, you need to
+			    set up your realm value to equal server name.
+			    If your server has no name, IP address can be used
+			    as realm too. The realm value is configured in
+				scripts as the first parameter of all
+				<command>{www|proxy}_{authorize|challenge}</command>
+				actions.
+			</para>
+		    </answer>
+		</qandaentry>
+		<qandaentry>
+		    <question>
+			<para>
+			    On a multihomed host, forwarded messages carry other 
+			    interface in Via than used for sending, or messages 
+			    are not sent and an error log is issued "invalid 
+			    sendtoparameters one possible reason is the server 
+			    is bound to localhost".
+			</para>
+		    </question>
+		    <answer>
+			<anchor id="mhomed">
+			<para>
+			    Set the configuration option <varname>mhome</varname>
+			    to "1". <application moreinfo="none">ser</application>
+			    will then attempt to calculate the correct interface.
+			    It's not done by default as it degrades performance
+			    on single-homed hosts or multi-homed hosts that are
+			    not set-up as routers.
+			</para>
+		    </answer>
+		</qandaentry>
+		<qandaentry>
+		    <question>
+			<para>
+			    I receive "ERROR: t_newtran: transaction already in process" in my logs.
+			</para>
+		    </question>
+		    <answer>
+			<para>
+			    That looks like an erroneous use of tm module in script.
+			    tm can handle only one transaction per request. If you
+			    attempt to instantiate a transaction multiple times,
+			    <application moreinfo="none">ser</application> will complain.
+			    Anytime any of <command moreinfo="none">t_newtran</command>,
+			    <command moreinfo="none">t_relay</command> or 
+			    <command moreinfo="none">t_relay_to</command> actions is
+			    encountered, tm attempts to instantiate a transaction.
+			    Doing so twice fails. Make sure that any of this
+			    commands is called only once during script execution.
+			</para>
+		    </answer>
+		</qandaentry>
+		<qandaentry>
+		    <question>
+			<para>
+			    I try to add an alias but 
+			    <command moreinfo="none">serctl</command>
+			    complains that table does not exist.
+			</para>
+		    </question>
+		    <answer>
+			<para>
+			    You need to run <application moreinfo="none">ser</application>
+			    and use the command
+			    <command moreinfo="none">lookup("aliases")</command>
+			    in its routing script. That's because the table 
+			    of aliases is
+			    stored in cache memory for high speed. The cache
+			    memory is only set up when the 
+			    <application moreinfo="none">ser</application>
+			    is running and configured to use it. If that is
+			    not the case, 
+			    <application moreinfo="none">serctl</application>
+			    is not able to manipulate the aliases table.
+			</para>
+		    </answer>
+		</qandaentry>
+
+	    <qandaentry>
+		<question>
+		    <para>I started <application>ser</application> with
+			<varname>children=4</varname> but many more processes
+			were started. What is wring?
+			</para>
+		    </question>
+		<answer>
+		    <para>
+			That's ok. The <varname>children</varname> parameter defines
+			how many children should process each transport protocol in
+			parallel. Typically, the server listens to multiple protocols
+			and starts other supporting processes like timer or FIFO
+			server too. Call <application>serctl ps</application> to watch
+			running processes.
+			</para>
+		    </answer>
+		</qandaentry>
+	    <qandaentry>
+		<question>
+		    <para>
+			I decided to use a compiled version of <application>ser</application>
+			but it does not start any more.
+			</para>
+		    </question>
+		<answer>
+		    <para>
+			You probably kept the same configuration file, which tries to load modules
+			from the binary distribution you used previously. Make sure that modules
+			paths are valid and point to where you compiled <application>ser</application>.
+			Also, watch logs for error messages "ERROR: load_module: could not open 
+			module".
+			</para>
+		    </answer>
+		</qandaentry>
+	    
+	    </qandaset>
+	</section> <!-- troubleshooting -->
+    </chapter> <!-- operation -->

+ 133 - 0
doc/seruser/otherapps.sgml

@@ -0,0 +1,133 @@
+    <chapter id="complementaryapps">
+	<title>Complementary Applications</title>
+	<section id="serctl">
+	    <title><application>serctl</application> command-line tool</title>
+	    <para>
+		<application>serctl</application> is a command-line utility which allows to
+		perform most of management tasks needed to operate
+		<application moreinfo="none">ser</application>: adding users, changing their passwords,
+		watching server status, etc. Usage of utility is
+		as follows:
+
+		<example>
+		    <title><application>serctl</application> usage</title>
+		    <programlisting format="linespecific">
+
+usage: 
+           * subscribers *
+ serctl add &lt;username&gt; &lt;password&gt; &lt;email&gt; .. add a new subscriber (*)
+ serctl passwd &lt;username&gt; &lt;passwd&gt; ......... change user's password (*)
+ serctl rm &lt;username&gt; ...................... delete a user (*)
+ serctl mail &lt;username&gt; .................... send an email to a user
+ serctl alias show [&lt;alias&gt;] ............... show aliases
+ serctl alias rm &lt;alias&gt; ................... remove an alias
+ serctl alias add &lt;alias&gt; &lt;uri&gt; ............ add an aliases 
+
+           * access control lists *
+ serctl acl show [&lt;username&gt;] .............. show user membership
+ serctl acl grant &lt;username&gt; &lt;group&gt; ....... grant user membership (*)
+ serctl acl revoke &lt;username&gt; [&lt;group&gt;] .... grant user membership(s) (*)
+
+           * usrloc *
+ serctl ul show [&lt;username&gt;]................ show in-RAM online users
+ serctl ul rm &lt;username&gt; ................... delete user's UsrLoc entries
+ serctl ul add &lt;username&gt; &lt;uri&gt; ............ introduce a permanent UrLoc entry
+ serctl showdb [&lt;username&gt;] ................ show online users flushed in DB
+
+           * server health *
+ serctl monitor ............................ show internal status
+ serctl ps ................................. show runnig processes 
+ serctl fifo ............................... send raw commands to FIFO
+
+   Commands labeled with (*) will prompt for a MySQL password.
+   If the variable PW is set, the password will not be prompted.
+
+ </programlisting>
+		</example>
+	    </para>
+	    <note>
+		<para>
+
+		Prior to using the utility, you have to first 
+		set the environment variable <constant>SIP_DOMAIN</constant>
+		to locally appropriate value (e.g., "foo.com"). It is
+		needed for calculation of user credentials, which depend
+		    on SIP digest realm. 
+		    (see also <link linkend="msmbug">MSM Authentication Issue</link>)
+	        </para>
+	    </note>
+
+	    <example>
+		<title>Example Output of Server Watching Command 
+		    <command moreinfo="none">sc monitor</command>
+		</title>
+		<programlisting format="linespecific">
+
+[cycle #: 2; if constant make sure server lives and fifo is on]
+Server: Sip EXpress router(0.8.8 (i386/linux))
+Now: Thu Sep 26 23:16:48 2002
+Up Since: Thu Sep 26 12:35:27 2002
+Up time: 38481 [sec]
+
+Transaction Statistics
+Current: 0 (0 waiting) Total: 606 (0 local)       
+Replied localy: 34      
+Completion status 6xx: 0, 5xx: 1, 4xx: 86, 3xx: 0,2xx: 519      
+
+Stateless Server Statistics
+200: 6218 202: 0 2xx: 0      
+300: 0 301: 0 302: 0 3xx: 0      
+400: 0 401: 7412 403: 2 404: 1258 407: 116 408: 0 483: 0 4xx: 25      500: 0 5xx: 0      
+6xx: 0      
+xxx: 0      
+failures: 0      
+
+UsrLoc Stats
+Domain Registered Expired
+'aliases' 9 0
+'location' 29 17
+
+		</programlisting>
+
+	    </example>
+	</section>
+
+	<section id="serweb">
+	    <title>Web User Provisioning -- <application>serweb</application></title>
+	    <para>
+		To make provisioning of user accounts convenient, 
+		a web front-end to <application moreinfo="none">ser</application>,
+		<application moreinfo="none">serweb</application> has been
+		developed. <application moreinfo="none">serweb</application>,
+		a PHP-written web application,
+		allows users to apply for new <application moreinfo="none">ser</application>
+		accounts, and maintain these.
+		Users can manipulate their contacts, keep a phone-book
+		with SIP addresses, change password, send instant SIP messages,
+		and more. Administrators can manipulate any accounts and
+		grant or revoke user privileges.
+	    </para>
+	    <para>
+		<application moreinfo="none">serweb</application> is freely
+		available from berlios site at
+		<ulink url="http://developer.berlios.de/cvs/?group_id=500">
+		http://developer.berlios.de/cvs/?group_id=500</ulink>. Installation
+		takes unpacking tarball to a safe destination at web server
+		(better not in the HTML tree) and configuring 
+		<filename moreinfo="none">config.php</filename> accordingly
+		to local conditions.
+	    </para>
+	    <para>
+		Running <application moreinfo="none">serweb</application> can
+		be seen at iptel.org's SIP site. Just create and use a SIP
+		account at <ulink url="http://www.iptel.org/user/">http://www.iptel.org/user/</ulink>
+	    </para>
+	</section> <!-- serweb -->
+
+
+    <section>
+	<title>Voicemail</title>
+&voicemail;
+    </section> <!-- voicemail -->
+
+    </chapter> <!-- other apps -->

+ 1406 - 0
doc/seruser/reference.sgml

@@ -0,0 +1,1406 @@
+    <chapter>
+	<title>Reference</title>
+	<section id="coreoptions">
+	    <title>Core Options</title>
+	    <para>Core options are located in beginning of configuration file and
+	    affect behaviour of the server.</para>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<varname>debug</varname> - Set log level, this is number between 0 and 9. Default 
+			is 0.
+			
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>fork</varname> - If set to yes, the server will spawn children. If set to no, the main
+			process will be processing all messages. Default is yes.
+			<note>
+			    <para>
+				Disabling child spawning is useful mainly for
+				debugging. When <varname>fork</varname> is turned off,
+				some features are unavailable: 
+				there is no attendant process, no pid file is generated,
+				and server listens only at one address. Make sure you
+				are debugging the same interface at which 
+				<application moreinfo="none">ser</application> listens.
+				The easiest way to do so is to set the interface using
+				<varname>listen</varname> option explicitly.
+				</para>
+			</note>
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>log_stderror</varname> - If set to yes, the server will print its debugging 
+			information to standard error output. If set to no, <command moreinfo="none">syslog</command> 
+			will be used. Default is no (printing to syslog).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>listen</varname> - list of all IP addresses or hostnames SER should listen on.
+			<note>
+				<para>
+					This parameter may repeat several times, then SER will
+					listen on all addresses. For example, the following
+					command-line options (equivalent to "listen" config
+					option) may be used: 
+					<command>
+						ser -l foo  -l bar -p 5061 -l x -l y 
+					</command>
+					will listen on foo:5060, bar:5061 & x:5061 & y:5061
+
+				</para>
+			</note>
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>alias</varname> - Add IP addresses or hostnames to list of name aliases.
+			All requests with hostname matching an alias will satisfy the condition 
+			"uri==myself".
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>dns</varname> - Uses dns to check if it is necessary to add a "received=" field to a via.
+			Default is no.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>rev_dns</varname> - Same as dns but use reverse DNS. Default is no.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>port</varname> - Listens on the specified port (default 5060). It applies to the last 
+			address specified in listen and to all the following that do not have a corresponding "port" option.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>maxbuffer</varname> - Maximum receive buffer size which will not be exceeded by 
+			the auto-probing procedure even if the OS allows. Default value is MAX_RECV_BUFFER_SIZE,
+			which is 256k.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>children</varname> - Specifies how many processes should be started
+		        for each transport protocol. 
+		    Running multiple children allows a server to 
+			server multiple requests in parallel when request processing block (e.g., on DNS
+			lookup). Note that <application>ser</application> typically spawns additional
+			processes, such as timer process or FIFO server. If FIFO server is turned on,
+			you can watch running processes using the <application moreinfo="none">serctl</application>
+			utility.
+
+
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>check_via</varname> - Turn on or off Via host checking when forwarding replies.
+			Default is no.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>syn_branch</varname> - Shall the server use stateful synonym branches? It is faster but not 
+			reboot-safe. Default is yes.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>memlog</varname> - Debugging level for final memory statistics report. Default is L_DBG --
+			memory statistics are dumped only if <varname>debug</varname> is set high.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>sip_warning</varname> - Should replies include extensive warnings? By default yes,
+			it is good for trouble-shooting.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>fifo</varname> - FIFO special file pathname, for example "/tmp/ser_fifo". Default is
+			no filename -- no FIFO server is started then. We recommend to set it so that
+			accompanying applications such as <application moreinfo="none">serweb</application> or
+			<application moreinfo="none">serctl</application> can communicate with
+			<application moreinfo="none">ser</application>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>fifo_mode</varname> - Permissions of the FIFO special file.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>server_signature</varname> - Should locally-generated messages include server's signature?
+			By default yes, it is good for trouble-shooting.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>reply_to_via</varname> - A hint to reply modules
+			whether they should send reply
+			to IP advertised in Via.
+			Turned off by default, which means that replies are
+			sent to IP address from which requests came from. 
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>user | uid</varname> - uid to be used by the server. 
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>group | gid</varname> - gid to be used by the server.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>mhomed</varname> -- enable calculation of 
+			outbound interface; useful on multihomed servers,
+			ser <link linkend="mhomed"></link>.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>loadmodule</varname> - Specifies a module to be loaded (for example "/usr/lib/ser/modules/tm.so")
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<varname>modparam</varname> - Module parameter configuration. The commands takes three parameters:
+			<itemizedlist>
+			    <listitem>
+				<para>
+				    <emphasis>module</emphasis> - Module in which the parameter resides.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>parameter</emphasis> - Name of the parameter to be configured.
+				</para>
+			    </listitem>
+			    <listitem>
+				<para>
+				    <emphasis>value</emphasis> - New value of the parameter.
+				</para>
+			    </listitem>
+			</itemizedlist>
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section>
+	<section id="builtinref">
+	    <title>Core Commands</title>
+
+
+	    <itemizedlist id="routeblocks">
+		<title>Route Blocks and Process Control</title>
+		<!--<para>
+		    Route block and process control keywords determine
+		    the order in which SIP requests are processed.
+		</para>-->
+		<listitem>
+		    <para>
+			<command>route[number]{...}</command> - This marks a "route block" in configuration files.
+			route blocks are basic building blocks of <application>ser</application> scripts. 
+			Each route block contains a sequence of 
+			<application>SER</application> actions enclosed in braces. Multiple route blocks
+			can be included in a configuration file.
+			When script execution begins on request receipt, 
+			route block number 0 is entered. Other route blocks serve as a kind of sub-routines and 
+			may be entered by calling the action <command>route(n)</command>, 
+			where n is number of the block. The action <command>break</command>
+			exits currently executed route block. It stops script execution for
+			route block number 0 or returns to calling route block otherwise.
+		    </para>
+		    <example>
+			<title>route</title>
+			<programlisting format="linespecific">
+route[0] {
+        # call routing block number 2
+	route(2);
+}
+
+route[2] {
+    forward("host.foo.bar", 5060);
+}
+</programlisting>
+		    </example>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>reply_route</command> is used to restart request processing
+			when a negative reply for a previously relayed request is received. It is only
+			used along with tm module, which stores the original requests and
+			can return to their processing later. To activate processing
+			of a <command>reply_route</command> block, call the TM action
+			<command>t_on_negative(route_number)</command> before calling
+			<command moreinfo="none">t_relay</command>. When a negative reply
+			comes back, the desired <command moreinfo="none">reply_route</command>
+			will be entered and processing of the original request may
+			continue. 
+			</para>
+		    <para>
+			The set of actions applicable from within
+			<command moreinfo="none">reply_route</command> blocks is limited.
+			Permitted actions are URI-manipulation actions, logging and
+			sending stateful replies using <command moreinfo="none">t_reply</command>.
+			Use of other actions may lead to
+			unpredictable results. (We plan to add syntactical checks in the future
+			so that improper action use will be detected during server start-up.)
+		    </para>
+		    <example>
+			<title>reply_route</title>
+			<programlisting format="linespecific">
+reply_route[1] {
+    # for some reason, the original forwarding attempt
+    # failed, try at another URI
+    append_branch("sip:[email protected]");
+    # if this new attempt fails too, try another reply_route
+    t_on_negative("2");
+}
+</programlisting>
+		    </example>
+		</listitem>
+
+		<listitem>
+		    <para>
+		    	The action <command>break</command> exits currently executed route block. 
+			It stops script execution for route block number 0 or returns to calling 
+			route block otherwise.
+			<note>
+			    <para>
+				We recommend to use <command moreinfo="none">break</command>
+				after any request forwarding or replying. This practice
+				helps to avoid erroneous scripts that 
+				continue execution and mistakenly send another reply or
+				forward a request to another place, resulting in
+				protocol confusion.
+			    </para>
+			</note>
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> break;
+		    </para>
+		</listitem>
+
+		<listitem>
+		    <para>
+			<command>route(n)</command> - call routing block route[n]{...};
+			when the routing block n finishes processing, control is passed
+			back to current block and processing continues.
+		    </para>
+		</listitem>
+
+		<listitem>
+		    <para>
+			<command>if (condition) statement</command> - Conditional statement.
+		    </para>
+		    <example>
+			<title>Use of <command>if</command></title>
+			<programlisting format="linespecific">
+if (method=="REGISTER) {
+    log("register received\n");
+};
+</programlisting>
+		    </example>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>if - else</command> - If-Else Conditional statement.
+		    </para>
+		    <example>
+			<title>Use of <command>if-else</command></title>
+			<programlisting format="linespecific">
+if (method=="REGISTER) {
+    log("register received\n");
+} else {
+    log("non-register received\n");
+};
+</programlisting>
+		    </example>
+		</listitem>
+
+	    </itemizedlist>
+	    <itemizedlist>
+		<title>Flag Manipulation</title>
+		<listitem>
+		    <para>
+			<command>setflag</command> - Set flag in the message.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> setflag(1);
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>resetflag</command> - Reset flag in the message.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> resetflag(1);
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>isflagset</command> - Test whether a particular flag is set.
+		    </para>
+		    <example>
+			<title>isflagset</title>
+			<programlisting format="linespecific">
+if (isflagset(1)) {
+    ....
+};
+</programlisting>
+		    </example>
+		</listitem>
+	    </itemizedlist>
+	    <itemizedlist>
+		<title>Manipulation of URI and Destination Set</title>
+		<listitem>
+		    <para>
+			<command>rewritehost | sethost | seth</command> - Rewrite host part of the Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> sethost("foo.bar.com");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>rewritehostport | sethostport | sethp</command> - Rewrite host and port part of the Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> sethostport("foo.bar.com:5060");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>rewriteuser | setuser | setu</command> - Rewrite or set username part of the Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> setuser("joe");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>rewriteuserpass | setuserpass | setup</command> - Rewrite or set username and password part
+			of the Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> setuserpass("joe:mypass");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>rewriteport | setport | setp</command> - Rewrite or set port of the Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> setport("5060");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>rewriteuri | seturi</command> - Rewrite or set the whole Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> seturi("sip:[email protected]:5060");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>revert_uri</command> - Revert changes made to the Request URI and use original Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> revert_uri();
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>prefix</command> - Add prefix to username in Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> prefix("123");
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>strip</command> - Remove first n characters of username in Request URI.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> strip(3);
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>append_branch</command> - Append a new destination to destination set of the message.
+		    </para>
+		    <para>
+			<example>
+			    <title>Use of <command>append_branch</command></title>
+			    <programlisting format="linespecific">
+# redirect to these two destinations: [email protected] and [email protected]
+# 1) rewrite the current URI
+rewriteuri("sip:[email protected]");
+# 2) append another entry to the destination ser
+append_branch("sip:[email protected]");
+# redirect now
+sl_send_reply("300", "redirection");
+			    </programlisting>
+			</example>
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    <itemizedlist>
+		<title>Message Forwarding</title>
+		<listitem>
+		    <para>
+			<command>forward(uri, port)</command> - Forward the request to given 
+			destination statelessly.  The uri and port parameters may take special 
+			values 'uri:host'
+			and 'uri:port' respectively, in which case SER forwards to destination
+			set in current URI. All other elements in a destination set are
+			ignored by stateless forwarding.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> forward("foo.bar.com"); # port defaults to 5060
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<command>send</command> - Send the message as is to a third party 
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> send("foo.bar.com");
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    <itemizedlist>
+		<title>Logging</title>
+		
+
+		<listitem>
+		    
+		    <para>
+			<command>log([level], message)</command> - Log a message.
+		    </para>
+		    <para>
+			<emphasis>Example:</emphasis> log(1, "This is a message with high log-level set to 1\n");
+		    </para>
+		    <para>
+			Logging is very useful for troubleshooting or attracting administrator's
+			attention to unusual situations. <application moreinfo="none">ser</application>
+			reports log messages to <application moreinfo="none">syslog</application>
+			facility unless it is configured to print them to <filename moreinfo="none">stderr</filename>
+			with the <varname>log_stderr</varname> configuration option. Log messages
+			are only issued if their log level exceeds threshold set with the
+			<varname>debug</varname> configuration option. If log level is omitted,
+			messages are issued at log level 4.
+		</para>
+		</listitem>
+
+	    </itemizedlist>
+
+
+
+
+	    <itemizedlist>
+		<title>Miscellaneous</title>
+		<listitem>
+		    <para>
+			<command>len_gt</command> - If length of the message is greater than value given as parameter, the
+			command will return 1 (indicating true). Otherwise -1 (indicating false) will be returned. It may 
+			take 'max_len' as parameter, in which case message size is limited
+			to internal buffer size BUF_SIZE (3040 by default).
+		    </para>
+		    <example>
+			<title>Use of <command>len_gt</command></title>
+			<programlisting format="linespecific">
+# deny all requests larger in size than 1 kilobyte
+if (len_gt(1024)) {
+    sl_send_reply("513", "Too big");
+    break;
+};
+			</programlisting>
+		    </example>
+		</listitem>
+	    </itemizedlist>
+	</section>
+	<section>
+	    <title>Command Line Parameters</title>
+	    <note>
+		<para>
+		    Command-Line parameters may be overridden by configuration
+		    file options which take precedence over them.
+		</para>
+	    </note>
+	    <itemizedlist>
+		<listitem>
+		    <para>
+			<emphasis>-h</emphasis> - Displays a short usage description, including all available options.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-c</emphasis> - Performs loop checks and computes branches.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-r</emphasis> - Uses dns to check if it is necessary to add a "received=" field to a via.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-R</emphasis> - Same as -r but uses reverse dns.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-v</emphasis> - Turns on via host checking when forwarding replies.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-d</emphasis> - Turns on debugging, multiple -d increase debugging level.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-D</emphasis> - Runs ser in the foreground (it doesn't fork into daemon mode).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-E</emphasis> - Sends all the log messages to stderr.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-V</emphasis> - Displays the version number.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-f config-file</emphasis> - Reads the configuration from "config-file" (default ./ser.cfg).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-l address</emphasis> - Listens on the specified address. Multiple -l mean listening 
+			on multiple addresses. The default behaviour is to listen on all the ipv4 interfaces.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-p port</emphasis> - Listens on the specified port (default 5060). It applies to the last 
+			address specified with -l and to all the following that do not have a corresponding -p.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-n processes-no</emphasis> - Specifies the number of children processes forked per 
+			interface (default 8).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-b max_rcv_buf_size</emphasis> - Maximum receive buffer size which will not be exceeded by 
+			the auto-probing procedure even if the OS allows.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-m shared_mem_size</emphasis> - Size of the shared memory which will be allocated (in Megabytes).
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-w working-dir</emphasis> - Specifies the working directory. In the very improbable event 
+			that will crash, the core file will be generated here.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-t chroot-dir</emphasis> - Forces ser to chroot after reading the config file.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-u uid</emphasis> - Changes the user id under which ser runs.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-g gid</emphasis> - Changes the group id under which ser runs.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-P pid-file</emphasis> - Creates a file containing the pid of the main ser process.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para>
+			<emphasis>-i fifo-path</emphasis> - Creates a fifo, useful for monitoring ser status.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	</section>
+
+
+
+
+	<section id="modulereference">
+	    <title>Modules</title>
+	    <para>
+		Module description is currently located in READMEs of
+		respective module directories. <filename moreinfo="none">README-MODULES</filename>
+		lists all available modules, including their maturity status.
+		In the current <application moreinfo="none">ser</application>
+		distribution, there are the following modules:
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    <emphasis>
+				acc
+			    </emphasis>
+			    -- call accounting using <application moreinfo="none">syslog</application> facility.
+			    Depends on tm.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				auth
+			    </emphasis>
+			    -- digest authentication. Depends on sl and mysql.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				exec
+			    </emphasis>
+			    -- execution of shell programs.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				jabber
+			    </emphasis> -- gateway between SIMPLE and Jabber instant messaging. Depends
+			    on tm and mysql.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				maxfwd
+			    </emphasis>
+			    -- checking max-forwards header field.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>msilo</emphasis>
+
+			-- message silo. Store for undelivered instant messages. Depends on tm and mysql.
+			    </para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				mysql
+			    </emphasis>
+			    -- mysql database back-end.
+			    </para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				registrar, usrloc
+			    </emphasis>
+			    -- User Location database. Works in in-memory mode or with mysql persistence
+			    support. Depends on sl, and on mysql if configured for use with mysql.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				rr
+			    </emphasis>
+			    -- Record Routing (strict and loose)
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				sl
+			    </emphasis>
+			    -- stateless User Agent server.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				sms
+			    </emphasis>
+			    -- SIMPLE/SMS gateway. Depends on tm. Takes special hardware.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    <emphasis>
+				textops
+			    </emphasis>
+			    -- textual request operations.
+			</para>
+		    </listitem>
+		    <listitem>			
+			<para>
+			    <emphasis>
+				tm
+			    </emphasis>
+			    -- transaction manager (stateful processing).
+			</para>
+		    </listitem>
+		</itemizedlist>
+	    </para>
+	    <para>
+		The most frequently used actions exported by modules are summarized
+		in <xref linkend="moduleactions">. For a full explanation of 
+		module actions, see documentation in respective module directories
+		in source distribution of <application moreinfo="none">ser</application>.
+	    </para>
+	    <table id="moduleactions">
+		<title>Frequently Used Module Actions</title>
+		<tgroup cols="4">
+		    <thead>
+			<row>			    
+			    <entry>
+				Command
+			    </entry>
+			    <entry>
+				Modules
+			    </entry>
+			    <entry>
+				Parameters
+			    </entry>
+			    <entry>
+				Comments
+			    </entry>
+			</row>
+		    </thead>
+
+		    <tbody>
+
+			<row>
+			    <entry>
+				append_hf
+			    </entry>
+			    <entry>
+				textops
+				</entry>
+			    <entry>
+				header field
+				</entry>
+			    <entry>
+				append a header field to the end of request's header
+				</entry>
+			    </row>
+			<row>
+			    <entry>
+				check_from
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				none
+			    </entry>
+			    <entry>
+				check if username in from header field matches authentication id
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				check_to
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				none
+			    </entry>
+			    <entry>
+				check if username in To header field matched authentication id
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				exec_dset
+			    </entry>
+			    <entry>
+				exec
+			    </entry>
+			    <entry>
+				command name
+			    </entry>
+			    <entry>
+				execute an external command and replace destination set with
+				its output
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				exec_msg
+			    </entry>
+			    <entry>
+				exec
+			    </entry>
+			    <entry>
+				command name
+			    </entry>
+			    <entry>
+				execute an external command and pass received SIP request
+				to its input
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				is_in_group
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				group name
+			    </entry>
+			    <entry>
+				check if a user, as identified by digest credentials, 
+				is a member of a group`
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				is_user
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				user id
+			    </entry>
+			    <entry>
+				returns true if request credentials belong to a user
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				is_user_in
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				user, group
+			    </entry>
+			    <entry>
+				check if user is member of a group; user can be gained
+				from request URI ("Request-URI"), To header field ("To"),
+				From header field ("From") or digest credentials
+				("Credentials")
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				lookup
+			    </entry>
+			    <entry>
+				usrloc
+			    </entry>
+			    <entry>
+				table name
+			    </entry>
+			    <entry>
+				attempt to translate request URI using user location database;
+				returns false if no contact for user found;
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				loose_route
+			    </entry>
+			    <entry>
+				rr
+			    </entry>
+			    <entry>
+				none
+			    </entry>
+			    <entry>
+				process loose routes in requests
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				mf_process_maxfwd_header
+			    </entry>
+			    <entry>
+				maxfwd
+			    </entry>
+			    <entry>
+				default max_forwards value
+			    </entry>
+			    <entry>
+				return true, if request's max_forwards value has not
+				reached zero yet; if none is included in the request,
+				set it to value in parameter
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				proxy_authorize
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				realm, subscriber table
+			    </entry>
+			    <entry>
+				returns true if requests contains proper credentials, false
+				otherwise
+			    </entry>
+			</row>
+
+
+
+
+
+
+			<row>
+			    <entry>
+				proxy_challenge
+			    </entry>
+			    <entry>
+				auth
+			    </entry>
+			    <entry>
+				realm, qop
+			    </entry>
+			    <entry>
+				challenge user to submit digest credentials; qop may be turned
+				off for backwards compatibility with elderly implementations
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				record_route
+			    </entry>
+			    <entry>
+				rr
+			    </entry>
+			    <entry>
+				loose routing (1=on, 0=off)
+			    </entry>
+			    <entry>
+				record-route a request
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				replace
+			    </entry>
+			    <entry>
+				textops
+			    </entry>
+			    <entry>
+				RegExp, Substitute
+			    </entry>
+			    <entry>
+				find the first occurence of a string matching the regular 
+				expression in header or body and replace it with a substitute
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				replace_all
+			    </entry>
+			    <entry>
+				textops
+			    </entry>
+			    <entry>
+				RegExp, Substitute
+			    </entry>
+			    <entry>
+				find all occurences of a string matching the regular 
+				expression in header or body and replace it with a substitute
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				save
+			    </entry>
+			    <entry>
+				usrloc
+			    </entry>
+			    <entry>
+				table name
+			    </entry>
+			    <entry>
+				for use in registrar: save content of Contact header fields
+				in user location database and reply with 200
+			    </entry>
+			</row>
+			<row>
+			    <entry>
+				search
+			    </entry>
+			    <entry>
+				textops
+			    </entry>
+			    <entry>
+				regular expression
+			    </entry>
+			    <entry>
+				search for a regular expression match in request header of body
+			    </entry>
+			</row>
+
+			<row>
+			    <entry>
+				sl_send_reply
+			    </entry>
+			    <entry>
+				sl
+			    </entry>
+			    <entry>
+				status code, reason phrase
+			    </entry>
+			    <entry>
+				reply a request statelessly
+			    </entry>
+			</row>
+
+			<row>
+			    <entry>
+				t_relay
+			    </entry>
+			    <entry>
+				tm
+			    </entry>
+			    <entry>
+				none
+			    </entry>
+			    <entry>
+				stateful forwarding to locations in current destination set
+			    </entry>
+			</row>
+
+			<row>
+			    <entry>
+				t_on_negative
+			    </entry>
+			    <entry>
+				tm
+			    </entry>
+			    <entry>
+				reply_route number
+			    </entry>
+			    <entry>
+				set reply_route block which shall be entered if stateful
+				forwarding fails
+			    </entry>
+			</row>
+
+			<row>
+			    <entry>
+				t_replicate
+			    </entry>
+			    <entry>
+				tm
+			    </entry>
+			    <entry>
+				host, port number
+			    </entry>
+			    <entry>
+				replicate a request to a destination
+			    </entry>
+			</row>
+
+
+		    </tbody>
+		</tgroup>
+	    </table>
+	</section> <!-- modules -->
+	<section id="fiforeference">
+	    <title>FIFO Commands Reference</title>
+	    <para>
+		This section lists currently supported FIFO commands. Some of them are
+		built-in in <application moreinfo="none">ser</application> core, whereas
+		others are exported by modules. The most important exporters are now
+		tm and usrloc module. tm FIFO commands allow users to initiate transactions
+		without knowledge of underlying SIP stack. usrloc FIFO commands allow
+		users to access in-memory user-location database. Note that that is the
+		only way how to affect content of the data-base in real-time. Changes
+		to MySql database do not affect in-memory table unless <application moreinfo="none">ser</application>
+		is restarted.
+	    </para>
+	    <table>
+		
+		<title>FIFO Commands</title>
+		<tgroup cols="4">
+		    <thead>
+			<row>
+			    <entry>
+				Command
+			    </entry>
+			    <entry>
+				Module
+			    </entry>
+			    <entry>
+				Parameters
+			    </entry>			    
+			    <entry>
+				Comments
+			    </entry>
+			</row>
+		    </thead>
+		    <tbody>
+			<row>
+			    <entry>
+				ps
+			    </entry>
+			    <entry>
+				core
+			    </entry>
+			    <entry>
+				none
+			    </entry>
+			    <entry>
+				prints running <application moreinfo="none">ser</application> processes
+			    </entry>
+			</row>
+			<row>
+			    <entry>which</entry>
+			    <entry>core</entry>
+			    <entry>none</entry>
+			    <entry>prints list of available FIFO commands</entry>
+			</row>
+			<row>
+			    <entry>arg</entry>
+			    <entry>core</entry>
+			    <entry>none</entry>
+			    <entry>prints list of command-line arguments with which 
+				<application moreinfo="none">ser</application> was started</entry>
+			</row>
+			<row>
+			    <entry>pwd</entry>
+			    <entry>core</entry>
+			    <entry>none</entry>
+			    <entry>prints <application moreinfo="none">ser</application>'s working
+			    directory</entry>
+			</row>
+			<row>
+			    <entry>version</entry>
+			    <entry>core</entry>
+			    <entry>none</entry>
+			    <entry>prints version of <application moreinfo="none">ser</application></entry>
+			</row>
+			<row>
+			    <entry>uptime</entry>
+			    <entry>core</entry>
+			    <entry>none</entry>
+			    <entry>prints <application moreinfo="none">ser</application>'s running time</entry>
+			</row>
+			<row>
+			    <entry>sl_stats</entry>
+			    <entry>sl</entry>
+			    <entry>none</entry>
+			    <entry>prints statistics for sl module</entry>
+			</row>
+			<row>
+			    <entry>t_stats</entry>
+			    <entry>tm</entry>
+			    <entry>none</entry>
+			    <entry>print statistics for tm module</entry>
+			</row>
+			<row>
+			    <entry>t_hash</entry>
+			    <entry>tm</entry>
+			    <entry>none</entry>
+			    <entry>print occupation of transaction table (mainly for debugging)</entry>
+			</row>
+			<row>
+			    <entry>t_uac_dlg</entry>
+			    <entry>tm</entry>
+			    <entry>method, request URI, outbound URI (if none, empty line with a single dot),
+					dot-line-terminated header fields, optionaly dot-line terminated message
+					body. 
+				</entry>
+					
+			    <entry>initiate a transaction.
+					From and To header fields must be present in header field list,
+					so does Content-Type if body is present. If CSeq, CallId and From-tag
+					are not present, ephemeral values are generated. Content_length is
+					calculated automatically if body present.
+				</entry>
+			</row>
+			<row>
+			    <entry>ul_stats</entry>
+			    <entry>usrloc</entry>
+			    <entry>none</entry>
+			    <entry>print usrloc statistics</entry>
+			</row>
+			<row>
+			    <entry>ul_rm</entry>
+			    <entry>usrloc</entry>
+			    <entry>table name, user name</entry>
+			    <entry>remove all user's contacts from user-location database</entry>
+			</row>
+			<row>
+			    <entry>ul_rm_contact</entry>
+			    <entry>usrloc</entry>
+			    <entry>table name, user name, contact</entry>
+			    <entry>remove a user's contact from user-location database</entry>
+			</row>
+			<row>
+			    <entry>ul_dump</entry>
+			    <entry>usrloc</entry>
+			    <entry>none</entry>
+			    <entry>print content of in-memory user-location database</entry>
+			</row>
+			<row>
+			    <entry>ul_flush</entry>
+			    <entry>usrloc</entry>
+			    <entry>none</entry>
+			    <entry>flush content of in-memory user-location cache in
+			    persistent database (MySQL)</entry>
+			</row>
+			<row>
+			    <entry>ul_add</entry>
+			    <entry>usrloc</entry>
+			    <entry>table name, user name, contact, expiration, priority (q)</entry>
+			    <entry>insert a contact address in user-location database</entry>
+			</row>
+			<row>
+			    <entry>ul_show_contact</entry>
+			    <entry>usrloc</entry>
+			    <entry>table, user name</entry>
+			    <entry>show user's contact addresses in user-location database</entry>
+			</row>
+		    </tbody>
+		</tgroup>
+	    </table>
+	</section>
+	<section>
+	    <title>Used Database Tables</title>
+	    <para>
+		<application moreinfo="none">ser</application> includes MySQL support
+		to guarantee data persistence across server reboots and storage
+		of users' web environment. The data stored in
+		the database include user profiles, access control lists, user location,
+		etc. Note that users are not supposed to alter the data directly, as it
+		could introduce inconsistency between data on persistence storage and
+		in server's memory.
+		The following list enumerates used tables and explains their purpose.
+
+		<itemizedlist>
+		    <listitem>
+			<para>
+			    subscriber -- table of users. It includes user names and
+			    security credentials, as well as additional user information.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    reserved -- reserved user names. <application moreinfo="none">serweb</application>
+			    does not permit creation of accounts with name on this list.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    phonebook -- user's personal phonebooks. Accessible via
+			    <application moreinfo="none">serweb</application>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    pending -- table of unconfirmed subscription requests. Used by
+			    <application moreinfo="none">serweb</application>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    missed_calls -- table of missed calls. Can be fed by acc modules
+			    if mysql support is turned on. Displayed by <application moreinfo="none">serweb</application>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    location -- user contacts. Typically updated through
+			    <application moreinfo="none">ser</application>'r registrar
+			    functionality.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    grp -- group membership. Used by auth module to determine
+			    whether a user belongs to a group.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    event -- allows users to subscribe to additional services.
+			    Currently unused.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    aliases -- keeps track of alternative user names.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    active_sessions -- keeps track of currently active web sessions.
+			    For use by <application moreinfo="none">serweb</application>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    acc -- keeps track of accounted calls.  Can be fed by acc module
+			    if mysql support is turned on. Displayed by <application moreinfo="none">serweb</application>.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    config -- maintains attribute-value pairs for keeping various information.
+			    Currently not used.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    silo -- message store for instant messages which could not have been
+			    delivered.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+			    version -- keeps version number of each table definition.
+			</para>
+		    </listitem>
+		</itemizedlist>
+		
+	    </para>
+	</section>
+    </chapter> <!-- reference -->

+ 16 - 5691
doc/seruser/seruser.sgml

@@ -24,6 +24,12 @@
 <!ENTITY install SYSTEM "../../INSTALL">
 <!ENTITY voicemail SYSTEM "voicemail.sgml">
 <!ENTITY voicemailcfg SYSTEM "../../modules/vm/etc/ser.cfg">
+<!ENTITY intro SYSTEM "intro.sgml">
+<!ENTITY operation SYSTEM "operation.sgml">
+<!ENTITY apps SYSTEM "apps.sgml">
+<!ENTITY reference SYSTEM "reference.sgml">
+<!ENTITY general SYSTEM "general.sgml">
+<!ENTITY otherapps SYSTEM "otherapps.sgml">
 
 
 
@@ -35,23 +41,23 @@
 <?dbhtml filename="index.html">
 
    
-    <title>iptel.org SIP Express Router v0.9.0 -- Admin's Guide</title>
+    <title>iptel.org SIP Express Router v0.11.0 -- Admin's Guide</title>
     <bookinfo>
 	<authorgroup>
 	    <author>
 		<firstname>Jiri</firstname>
 		<surname>Kuthan</surname>
-		<email>[email protected]</email>
+		<!-- <email>[email protected]</email>  -->
 	    </author>
 	    <author>
 		<firstname>Jan</firstname>
 		<surname>Janak</surname>
-		<email>[email protected]</email>
+		<!-- <email>[email protected]</email> -->
 	    </author>
 	    <author>
 		<firstname>Yacine</firstname>
 		<surname>Rebahi</surname>
-		<email>[email protected]</email>
+		<!-- <email>[email protected]</email> -->
 	    </author>
 
 	</authorgroup>
@@ -106,5700 +112,19 @@
     </bookinfo>
 
     <toc></toc>
-    
-    <chapter id="general">
-	<title>General Information</title>
-	<section id="aboutser">
-	    <title>About <acronym>SIP</acronym> Express Router (<acronym>SER</acronym>)</title>
-	    <para>
-		SIP Express Router (<acronym>SER</acronym>) is an industrial-strength, free VoIP 
-		server based on the Session Initiation Protocol (<acronym>SIP</acronym>, RFC3261). 
-		It is engineered to power <acronym>IP</acronym> telephony infrastructures up to large 
-		scale. The server keeps track of users, sets up VoIP sessions, 
-		relays instant messages and creates space for new plug-in applications. 
-		Its proven interoperability guarantees seamless integration with 
-		components from other vendors, eliminating the risk of a single-vendor 
-		trap. It has successfully participated in various interoperability 
-		tests in which it worked with the products of other leading <acronym>SIP</acronym> vendors.
-	    </para>
-	    <para>
-		The <acronym>SIP</acronym> Express Router enables a flexible plug-in model for new 
-		applications: Third parties can easily link their plug-ins with 
-		the server code and provide thereby advanced and customized services. 
-		In this way, plug-ins such as <acronym>SNMP</acronym> support, RADIUS accounting,
-		or SMS gateway have already been developed and are provided as 
-		advanced features. Other modules are underway: Presence server,
-		firewall control, and more.
-	    </para>
-	    <para>
-		Its performance and robustness allows it to serve millions of users 
-		and accommodate needs of very large operators. With a $3000 dual-CPU PC, the 
-		<acronym>SIP</acronym> Express Router is able to power <acronym>IP</acronym> telephony services in an area 
-		as large as the Bay Area during peak hours. Even on an IPAQ <acronym>PDA</acronym>, the server 
-		withstands 150 calls per second (<acronym>CPS</acronym>)! The server has been powering our 
-		iptel.org free <acronym>SIP</acronym> site withstanding heavy daily load that is further 
-		increasing with the popularity of Microsoft's Windows Messenger.  
-	    </para>
-	    <para>
-		The <acronym>SIP</acronym> Express Router is extremely configurable to allow the creation of 
-		various routing and admission policies as well as setting up new and 
-		customized services. Its configurability allows it to serve many roles: 
-		network security barrier, application server, or <acronym>PSTN</acronym> gateway guard for 
-		example.
-	    </para>
-	    <para>
-		<application moreinfo="none">ser</application> can be also
-		used with contributed applications. Currently, 
-		<application moreinfo="none">serweb</application>, a
-		<application moreinfo="none">ser</application> web interface,
-		and <application moreinfo="none">SIPSak</application>
-		diagnostic tool are available. Visit our site, 
-		<ulink url="http://www.iptel.org/">http://www.iptel.org/</ulink>, 
-                for more information on contributed packages.
-	    </para>
-	</section> 
-
-	<section id="aboutiptel">
-	    <title>About iptel.org</title>
-	    <para>
-		iptel.org is a know-how company spun off from Germany's national 
-		research company FhG Fokus. One of the first <acronym>SIP</acronym> implementations ever, 
-		low-QoS enhancements, interoperability tests and VoIP-capable firewall 
-		control concepts are examples of well-known FhG's work.
-	    </para>
-	    <para>
-		iptel.org continues to keep this know-how leadership in <acronym>SIP</acronym>. 
-		The access rate of the company's site, a well-known source of 
-		technological information, is a best proof of interest. Thousands 
-		of hits come every day from the whole Internet.
-	    </para>
-	    <para>
-		The iptel.org site, powered by SER, offers SIP services on the public 
-		Internet. Feel free to apply for a free SIP account at
-		<ulink url="http://www.iptel.org/user/">http://www.iptel.org/user/
-		</ulink>
-	    </para>
-
-	    
-	</section> <!-- iptel -->
-	<section id="serfeatures">
-	    <title>Feature List</title>
-	    <para>
-		Based on the latest standards, the <acronym>SIP</acronym> Express Router (<acronym>SER</acronym>) includes 
-		support for registrar, proxy and redirect mode. Further it acts as 
-		an application server with support for instant messaging and 
-		presence including a <acronym>2G/SMS</acronym> and Jabber gateway, a call control policy 
-		language, call number translation, private dial plans and accounting, 
-		authorization and authentication (<acronym>AAA</acronym>) services. <application>SER</application> runs on Sun/Solaris, 
-		PC/Linux, PC/BSD, IPAQ/Linux platforms and supports  both <acronym>IPv4</acronym> and <acronym>IPv6</acronym>. 
-		Hosting multiple domains and database redundancy is supported.
-	    </para>
-	    <para>
-		Other extensions are underway: presence server, firewall control and more.
-	    </para>
-	    <para>
-		<application>ser</application> has been carefully engineered with the following 
-		design objectives in mind:
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    <emphasis>Speed</emphasis> - With <application>ser</application>, 
-			    thousands of calls per seconds are achievable 
-			    even on low-cost platforms. This competitive capacity allows 
-			    setting up networks which are inexpensive and easy to manage 
-			    due to low number of devices required. The processing capacity 
-			    makes dealing with many stress factors easier. The stress
-			    factors may include but are not limited to broken configurations and implementations,
-			    boot avalanches on power-up, high-traffic applications such as presence, 
-			    redundancy replications and denial-of-service attacks.
-			</para>
-			<para> The speed has been achieved by extensive code optimization, use of customized code, 
-			    <acronym>ANSI C</acronym> combined with assembly instructions and leveraging latest 
-			    <acronym>SIP</acronym> improvements. When powered by a dual-CPU Linux PC, 
-			    <application>ser</application> is able to process thousands of calls per second,
-			    capacity needed to serve call signaling demands of Bay Area population.
-			   
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>Flexibility</emphasis> - <application>SER</application> allows its users 
-			    to define its behavior. 
-			    Administrators may write textual scripts which determine <acronym>SIP</acronym> routing 
-			    decisions, the main job of a proxy server. They may use the script to 
-			    configure numerous parameters and introduce additional logic. For example, 
-			    the scripts can determine for which destinations record routing should be 
-			    performed, who will be authenticated, which transactions should be processed 
-			    statefully, which requests will be proxied or redirected, etc.
-			</para>
-
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>Extensibility</emphasis> - <application>SER</application>'s extensibility allows linking of 
-			    new C code to ser to 
-			    redefine or extend its logic. The new code can be developed independently 
-			    on <application>SER</application> core and linked to it in run-time. The concept is similar to 
-			    the module concept known for example in Apache Web server. Even such essential parts such 
-			    as transaction management have been developed as modules to keep the <application>SER</application> core 
-			    compact and fast.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				Portability.
-			    </emphasis>
-			    <application>ser</application> has been written in ANSI C. It has been extensively tested 
-			    on PC/Linux and Sun/Solaris. Ports to BSD and IPAQ/Linux exist.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>			   
-				Interoperability. 
-			</emphasis>
-			<application>ser</application> is based on the open <acronym>SIP</acronym> standard. 
-			    It has undergone extensive tests with products of other vendors both in iptel.org
-			    labs and in the SIP Interoperability Tests (SIPIT). <application>ser</application> 
-			    powers the public iptel.org site 24 hours a day, 356 days a year 
-			    serving numerous SIP implementations using this site.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>Small size.</emphasis>
-			    Footprint of the core is 300k, add-on modules take up to 630k.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </para>
-	</section> <!-- serfeatures -->
-
-	<section id="usecases">
-	    <title>Use Cases</title>
-	    <para>
-		This section illustrates the most frequent uses of SIP. In all these scenarios, 
-		the SIP Express Router (SER) can be easily deployed as the glue connecting all 
-		SIP components together, be it soft-phones, hard-phones, PSTN gateways or any other 
-		SIP-compliant devices.
-	    </para>
-	    <section>
-		<title>Added-Value ISP Services</title>
-		<para>
-		    To attract customers, ISPs frequently offer applications bundled with IP access. 
-		    With SIP, the providers can conveniently offer a variety of services running on top 
-		    of a single infrastructure. Particularly, deploying VoIP and instant messaging and 
-		    presence services is as easy as setting up a SIP server and guiding customers to use 
-		    Windows Messenger. Additionally, the ISPs may offer advanced services such as PSTN 
-		    termination, user-driven call handling or unified messaging all using the same infrastructure.
-		</para>
-		<para>
-		    SIP Express Router has been engineered to power large scale networks: its capacity can deal 
-		    with large number of customers under high load caused by modern applications. Premium 
-		    performance allows deploying a low number of boxes while keeping investments and operational 
-		    expenses extremely low. ISPs can offer SIP-based instant messaging services and interface
-		    them to other instant messaging systems (Jabber, SMS). VoIP can be easily integrated along
-		    with added-value services, such as voicemail.
-		</para>
-	    </section> <!-- Added-value ISP -->
-	    <section>
-		<title>PC2Phone</title>
-		<para>
-		    Internet Telephony Service Providers (ITSPs) offer the service of interconnecting 
-		    Internet telephony users using PC softphone or appliances to PSTN. Particularly with 
-		    long-distance and international calls, competitive pricing can be achieved by 
-		    routing the calls over the Internet.
-		</para>
-		<para>
-		    SIP Express Router can be easily configured to serve pc2phone users, distribute
-		    calls to geographically appropriate PSTN gateway, act as a security barrier and keep 
-		    track of charging. 
-		</para>
-	    </section>
-	    <section>
-		<title>PBX Replacement</title>
-		<para>
-		    Replacing a traditional PBX in an enterprise can achieve reasonable 
-		    savings. Enterprises can deploy a single infrastructure for both voice 
-		    and data and bridge distant locations over the Internet. Additionally, they can 
-		    benefit of integration of voice and data.
-		</para>
-		<para>
-		    The SIP Express Router scales from SOHOs to large, international enterprises. 
-		    Even a single installation on a common PC is able to serve VoIP signaling of any 
-		    world's enterprise. Its policy-based routing language makes implementation of numbering 
-		    plans of companies spread across the world very easy. ACL features allow for protection of 
-		    PSTN gateway from unauthorized callers.
-		</para>
-		<para>
-		    SIP Express Router's support for programmable routing and accounting efficiently allows for 
-		    implementation of such a scenario.
-		</para>
-	    </section>
-	</section> <!-- Use Cases -->
-	<section id="aboutsip">
-	    <title>About SIP Technology</title>
-	    <para>
-		The SIP protocol family is the technology which integrates services. 
-		With SIP, Internet users can easily contact each other; figure out 
-		willingness to have a conversation and couple different applications such as VoIP, video 
-		and instant messaging. Integration with added-value services is seamless and easy. Examples 
-		include integration with web (click-to-dial), E-mail (voice2email, UMS), and PSTN-like 
-		services (conditional forwarding).
-	    </para>
-	    <para>
-		The core piece of the technology is the Session Initiation Protocol (SIP, RFC3261) standardized by IETF. 
-		Its main function is to establish communication sessions between users connected to the public 
-		Internet and identified by e-mail-like addresses. One of SIP's greatest features is its transparent 
-		support for multiple applications: the same infrastructure may be used for voice, video, gaming 
-		or instant messaging as well as any other communication application.
-	    </para>
-	    <para>
-		There are numerous scenarios in which SIP is already deployed: PBX replacement allows for 
-		deployment of single inexpensive infrastructure in enterprises; PC-2-phone long-distance 
-		services (e.g., Deltathree) cut callers long-distance expenses; instant messaging offered 
-		by public severs (e.g., iptel.org) combines voice and text services with presence information. 
-		New deployment scenarios are underway: SIP is a part of UMTS networks and research publications 
-		suggest the use of SIP for virtual home environments or distributed network games.
-	    </para>
-	</section> <!-- about sip -->
-	<section id="serlimitations">
-	    <title>Known SER Limitations</title>
-	    <para>
-		The following items are not part of current distribution and are planned for next releases:
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    TCP transport
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    Script processing of multiple branches on forking
-			</para>
-
-			<warning>
-			    <para>
-				<application>ser</application>'s request processing language allows 
-				to make request decisions based on current URI. 
-				When a request if forked to multiple destinations, only the first branch's URI is used as 
-				input for script processing. This might lead to unexpected results. Whenever a URI resolves 
-				to multiple different next-hop URIs, only the first is processed which may result in handling 
-				not appropriate for the other branch. For example, a URI might resolve to an IP phone SIP 
-				address and PSTN gateway SIP address. If the IP phone address is the first, then script 
-				execution ignores the second branch. If a script includes checking gateway address in
-				request URI, the checks never match. That might result in ignoring of 
-				gateway admission control rules or applying them unnecessarily to non-gateway 
-				destinations.
-			    </para>
-			</warning>
-		    </listitem>
-		</itemizedlist>
-	    </para>
-	    <para>
-		List of known bugs is publicly available at
-		<ulink url="http://developer.berlios.de/bugs/?group_id=480">
-		    http://developer.berlios.de/bugs/?group_id=480
-		</ulink>.
-	    </para>
-	</section> <!-- limitations -->
-	<section id="licensing">
-	    <title>Licensing</title>
-	    <para>
-		<application>ser</application> is freely available under terms and
-		conditions of the GNU General Public License.
-	    </para>	
-	    <!-- COPYING -->
-	    <screen>
-	    	    &gpllicense;
-	    </screen>
-	    
-	</section>
-	<section id="support">
-	    <title>Obtaining Technical Assistance</title>
-	    <para>
-		We offer best-effort free support for <application>ser</application>.
-		"best-effort" means that we try to solve your problems via email
-		as soon as we can, subject to available manpower. If you need
-		commercial support, contact [email protected].
-	    </para>
-	    <para>
-		To receive feedback to your inquiries, we recommend you to subscribe
-		to the <emphasis>serusers</emphasis> mailing list and post your
-		queries there. This mailing list is set up for mutual help by
-		the community of <application>ser</application> users and developers.
-	    </para>
-	    <itemizedlist>
-		<title>Mailing List Instructions</title>
-		<listitem>
-		    <para>
-			Public archives and subscription form:
-			<ulink url="http://mail.iptel.org/mailman/listinfo/serusers">
-			    http://mail.iptel.org/mailman/listinfo/serusers
-			</ulink>			
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			To post, send an email to [email protected]
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			If you think you encountered an error, please submit the
-			following information to avoid unnecessary round-trip times:			
-			<itemizedlist>
-			    <listitem>
-				<para>
-				    Name and version of your operating system --
-				    you can obtain it by calling
-				    <command>uname -a</command>
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    <application>ser</application> distribution: 
-				    release number and package				    
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    <application>ser</application> build -- 
-				    you can obtain it by calling 
-				    <command moreinfo="none">ser -V</command>
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    Your <application>ser</application> configuration file
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    <application>ser</application> logs -- with default settings
-				    few logs are printed to <command>syslog</command> facility which
-				    typically dumps them to 
-				    <filename moreinfo="none">/var/log/messages</filename>. To 
-				    enable detailed logs dumped to <filename>stderr</filename>,
-				    apply the following configuration options: <command moreinfo="none">
-				    debug=8, log_stderror=yes, fork=no</command>.
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    Captured SIP messages -- you can obtain them 
-				    using tools such as <application>ngrep</application>
-				    or <application moreinfo="none">ethereal</application>.
-				</para>
-			    </listitem>
-			</itemizedlist>
-		    </para>
-		    
-		</listitem>
-	    </itemizedlist>	    
-	
-	    <para>
-		If you are concerned about your privacy and do not wish your
-		queries to be posted and archived publicly, you may post to
-		[email protected]. E-mails to this address are only forwarded
-		to iptel.org's <application>ser</application> development team.
-		However, as the team is quite busy you should not be surprised
-		to get replies with considerable delay.
-
-	    </para>
-	</section>
-        
-	<section id="moreinfo">
-	    <title>More Information</title>
-	    <para>
-		Most up-to-date information including latest and most complete version
-		of this documentation is always available at our website,
-		<ulink url="http://www.iptel.org/ser/">http://www.iptel.org/ser/</ulink>.
-		The site includes links to other important information about
-		<application moreinfo="none">ser</application>, such
-		as installation guidelines (INSTALL), download links,
-		development pages, programmer's manual, etc.
-	    </para>
-	    <para>
-		A SIP tutorial (slide set) is available at 
-		<ulink url="http://www.iptel.org/sip/">http://www.iptel.org/sip/</ulink> .
-	    </para>
-	</section> <!-- info -->
-
-	<section>
-	    <title>Release Notes</title>
-	    <literallayout format="linespecific" class="normal">
-&releasenotes;
-	    </literallayout>
-	</section> <!-- release notes -->
-
-
-    </chapter> <!-- general -->
-
-    <chapter>
-	<title>Introduction to SER</title>
-
-	<section id="requestrouting">
-	    <title>Request Routing and SER Scripts</title>
-	    <para>
-		The most important concept of every SIP server is that of
-		request routing. The request routing logic determines the next
-		hop of a request. It can be for example used to implement user 
-		location service or enforce static routing to a gateway. Real-world
-		deployments actually ask for quite complex routing logic, which
-		needs to reflect static routes to PSTN gateways, dynamic routes
-		to registered users, authentication policy, capabilities of
-		SIP devices, etc.
-	    </para>
-	    <para>
-		SER's answer to this need for routing flexibility is a routing
-		language, which allows administrators to define the SIP request
-		processing logic in a detailed manner. They can for example easily
-		split SIP traffic by method or destination, perform user location, 
-		trigger authentication, verify access permissions, and so on.
-	    </para>
-	    <para>
-		The primary building block of the routing language are <emphasis>actions</emphasis>. 
-		There are built-in actions (like <command>forward</command> for stateless forwarding
-		or <command>strip</command> for stripping URIs) as 
-		well as external actions imported from shared library modules. All actions can 
-		be combined in compound actions by enclosing them in braces, 
-		e.g. <command>{a1(); a2();}</command>. 
-		Actions are aggregated in one or more <emphasis>route blocks</emphasis>.
-		Initially, only the default routing block denoted by <command>route[0]</command>
-		is called. Other routing blocks can be called by the action
-		<command>route(blocknumber)</command>, recursion is permitted.
-		The language includes <emphasis>conditional statements</emphasis>. 
-	    </para>
-
-	    <para>
-		The routing script is executed for every received request in sequential order. 
-		Actions may return positive/negative/zero value. 
-
-		Positive values are considered success and evaluated as
-		TRUE in conditional expressions. Negative values are considered FALSE. 
-
-		Zero value means error and leaves execution of currently processed
-		route block. The route block is left too, if <command>break</command> is explicitly
-		called from it.
-
-	    </para>
-	    <para>
-		The easiest and still very useful way for <application>ser</application>
-		users to affect request routing logic is
-		to determine next hop statically. An example is
-		routing to a PSTN gateway whose static IP address is well known.
-		To configure static routing, simply use the action
-		<command>forward( IP_address, port_number)</command>.
-		This action forwards an incoming request "as is" to the
-		destination described in action's parameters.
-	    </para>
-
-	    <example>
-		<title>Static Forwarding</title>
-		<programlisting format="linespecific">
-# if requests URI is numerical and starts with
-# zero, forward statelessly to a static destination
-
-if (uri=~"^sip:0[0-9]*@iptel.org) {
-    forward( 192.168.99.3, 5080 );
-} 
-		</programlisting>
-	    </example>
-
-	    <para>
-		However, static forwarding is not sufficient in many cases.
-		Users desire mobility and change their location frequently.
-		Lowering costs for termination of calls in PSTN requires
-		locating a least-cost gateway. Which next-hop is taken may
-		depend on user's preferences. These and many other scenarios
-		need the routing logic to be more dynamic. We describe in
-		<xref linkend="conditions"> how to make request processing
-		subject to various conditions and in 
-		<xref linkend="urirewriting"> how to determine next SIP hop.
-	    </para>
-	</section>
-
-	<section id="conditions">
-	    <title>Conditional Statements</title>
-	    <para>
-		A very useful feature is the ability to make routing
-		logic depend on a condition. A script condition may for
-		example distinguish between request processing for
-		served and foreign domains, IP and PSTN routes,
-		it may split traffic by method or username, it
-		may determine whether a request should be authenticated
-		or not, etc. <application moreinfo="none">ser</application>
-		allows administrators to form conditions based on
-		properties of processed request, such as method or uri,
-		as well as on virtually any piece of data on the
-		Internet.
-	    </para>
-	    <example>
-		<title>Conditional Statement</title>
-		<para>
-		    This example shows how a conditional statement is
-		    used to split incoming requests between a PSTN
-		    gateway and a user location server based on
-		    request URI.
-		</para>
-		<programlisting format="linespecific">
-# if request URI is numerical, forward the request to PSTN gateway...
-if (uri=~"^sip:[0-9][email protected]") { # match using a regular expression
-    forward( gateway.foo.bar, 5060 );
-} else { # ... forward the request to user location server otherwise
-    forward( userloc.foo.bar, 5060 );
-};
-		</programlisting>
-	    </example>
-
-	    <para>
-		Conditional statements in <application>ser</application> scripts may depend
-		on a variety of  expressions. The simplest expressions are 
-		action calls. They return true if they completed successfully or false otherwise. 
-		An example of an action frequently used in conditional statements is
-		<command moreinfo="none">search</command> imported from textops module.
-		<command moreinfo="none">search</command> action leverages textual
-		nature of SIP and compares SIP requests against a regular expression.
-		The action returns true if the expression matched, false otherwise.
-		<example>
-		    <title>Use of <command>search</command> Action in Conditional Expression</title>
-		    <programlisting format="linespecific">
-# prevent strangers from claiming to belong to our domain;
-# if sender claims to be in our domain in From header field,
-# better authenticate him 
-if (search("(f|From): .*@mydomain.com)) {
-    if (!(proxy_authorize("mydomain.com" /* realm */,"subscriber" /* table name */ ))) {
-           proxy_challenge("mydomain.com /* ream */, "1" /* use qop */ );
-           break;
-    }
-}
- 		    </programlisting>
-		</example>
-	    </para>
-	    <para>
-		As modules may be created, which export new functions, there is virtually
-		no limitation on what functionality <application moreinfo="none">ser</application>
-		conditions are based on. Implementers may introduce new actions whose
-		return status depends on request content or any external data as well. Such actions
-		can query SQL, web, local file systems or any other place which can provide
-		information wanted for request processing.
-	    </para>
-	    <para>
-		Furthermore, many request properties may be examined using existing built-in operands
-		and operators. Available left-hand-side operands and legal combination with
-		operators and right-hand-side operands are described in <xref linkend="logicalexpr">.
-		Expressions may be grouped together using logical operators:
-		negation (<command>!</command>), AND (<command>&&</command>), OR (<command moreinfo="none">
-		||</command> and precedence parentheses (<command>()</command>).
-	    </para>
-
-	    <section id="operators">
-		<title>Operators and Operands</title>
-		<para>
-		    There is a set of predefined operators and operands
-		    in ser, which in addition to actions may be evaluated
-		    in conditional expressions. 
-		</para>
-		<para>
-		    Left hand-side operands, which <application>ser</application>
-		    understands are the following:
-		    <itemizedlist>
-			<listitem>
-			    <para>
-				<emphasis>method</emphasis>, which refers to 
-				request method
-				such as REGISTER or INVITE
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				<emphasis>uri</emphasis>, which refers to current request URI,
-				such as 
-				"sip:[email protected]"
-				<note>
-				    <para>
-					Note that "uri" always refers to current
-					value of URI, which is subject to change
-					be uri-rewriting actions.
-				    </para>
-				</note>
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				<emphasis>src_ip</emphasis>, which refers to IP address from 
-				which a request came.
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				<emphasis>dst_ip</emphasis> refers to server's IP address 
-				at which a request was received
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				<emphasis>src_port</emphasis> port number from which a SIP
-				request came
-			    </para>
-			</listitem>
-		    </itemizedlist>
-		</para>
-		<para>
-		    ser understands the following operators:
-		    <itemizedlist>
-			<listitem>
-			    <para>
-				== stands for equity
-			    </para>
-			    
-			</listitem>
-			<listitem>
-			    <para>
-				=~ stands for regular expression matching
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				logical operators: and, or, negation, parentheses
-				(C-notation for the operators may be used too)
-			    </para>
-			</listitem>
-		    </itemizedlist>
-		</para>
-
-	    <table id="logicalexpr">
-		<title>Valid Combinations of Operands and Operators in Expressions</title>
-		<tgroup cols="4">
-		    <thead>
-			<row>
-			    <entry>
-				left-hand-side operand
-			    </entry>			    
-			    <entry>
-				valid operators
-			    </entry>
-			    <entry>
-				valid right-hand side operators
-			    </entry>
-			    <entry>
-				examples/comments
-			    </entry>
-			</row>
-
-		    </thead>
-		    <tbody>
-
-			<row>
-			    <entry>
-				method
-			    </entry>			    
-			    <entry>
-				== (exact match), =~ (regular expression matching)
-			    </entry>
-			    <entry>
-				string
-			    </entry>
-			    <entry>
-				method=="INVITE" || method=="ACK" || method=="CANCEL"
-			    </entry>
-			</row>			
-
-			<row>
-			    <entry>
-				uri
-			    </entry>			    
-			    <entry>
-				== (exact match), =~ (regular expression matching)
-			    </entry>
-			    <entry>
-				string
-			    </entry>
-			    <entry>
-				uri=="sip:[email protected]" matches only if exactly this uri
-				is in request URI
-
-			    </entry>
-			</row>				
-
-			<row>
-			    <entry>
-				
-			    </entry>			    
-			    <entry>
-				== (exact match)
-			    </entry>
-			    <entry>
-				myself
-			    </entry>
-			    <entry>
-				
-				the expression uri==myself is true if the host part in 
-				request URI equals a server name or a server alias (set using
-				the alias option in configuration file)
-				
-			    </entry>
-			</row>				
-
-			<row>
-			    <entry>
-				src_ip
-			    </entry>			    
-			    <entry>
-				== (match)
-			    </entry>
-			    <entry>
-				IP, IP/mask_length, IP/mask, hostname, myself
-			    </entry>
-			    <entry>
-				src_ip==192.168.0.0/16 matches requests coming from
-				a private network
-			    </entry>
-			</row>
-
-			<row>
-			    <entry>
-				dst_ip				
-			    </entry>			    
-			    <entry>
-				== (match)
-			    </entry>
-			    <entry>
-				IP, IP/mask_length, IP/mask, hostname, myself
-			    </entry>
-			    <entry>
-				dst_ip==127.0.0.1 matches if a request was received
-				via loopback interface
-			    </entry>
-			</row>
-
-			<row>
-			    <entry>
-				    src_port
-			    </entry>			    
-			    <entry>
-				== (match)
-			    </entry>
-			    <entry>
-				port number
-			    </entry>
-			    <entry>
-				port number from which a request was sent, e.g. src_port==5060
-			    </entry>
-			</row>			    
-
-
-		    </tbody>
-		</tgroup>
-	    </table>
-	    
-
-		<example>
-		    <title>
-			More examples of use of <application>ser</application> operators and operands in conditional
-			statements
-		    </title>
-		    <programlisting format="linespecific">
-# using an action as condition input; in this
-# case, an actions 'search' looks for Contacts
-# with private IP address in requests; the condition
-# is processed if such a contact header field is
-# found
-
-if (search("^(Contact|m): .*@(192\.168\.|10\.|172\.16)")) {
-# .... 
-
-# this condition is true if request URI matches
-# the regular expression "@bat\.iptel\.org"
-    if (uri=~"@bat\.iptel\.org") {
-# ...
-
-# and this condition is true if a request came
-# from an IP address (useful for example for
-# authentication by IP address if digest is not
-# supported) AND the request method is INVITE
-
-# if ( (src_ip==192.68.77.110 and method=="INVITE")
-# ...
-</programlisting>
-		</example>
-	    </section> <!-- operators and operands -->
-	    <section>
-		<title>URI Matching</title>
-		<para>URI matching expressions have a broad use in a SIP server
-		    and deserve more explanation. Typical uses of
-		    URI matching include implementation of numbering plans,
-		    domain matching,
-		    binding external applications to specific URIs,
-		    etc. This section shows examples of typical applications
-		    of URI-matching.
-		</para>
-		<section id="domainmatching">
-		    <title>Domain Matching</title>
-		    <para>
-			One of most important uses of URI matching is deciding
-			whether a request is targeted to a served or outside domain.
-			Typically, different request
-			processing applies. Requests for outside domains
-			are simply forwarded to them, whereas
-			more complex logic applies to requests for a served domain.
-			The logic may include saving user's contacts
-			when REGISTER requests are received, forwarding requests
-			to current user's location or a PSTN gateways, 
-			interaction with external applications, etc.
-		    </para>
-		    <para>
-			The easiest way to decide whether a request belongs
-			a served domain is using the <command moreinfo="none">myself</command>
-			operand. 
-			The expression "uri==myself" returns true if domain name
-			in request URI matches name of the host at which
-			<application moreinfo="none">ser</application> is
-			running. This may be insufficient in cases when
-			server name is not equal to domain name for which the server
-			is responsible. For example, the "uri==myself" condition
-			does not match if a server "sipserver.foo.bar" 
-			receives a request for "sip:[email protected]". To
-			match other names in URI than server's own,
-			set up the <varname>alias</varname> configuration
-			option. The option may be used multiple times,
-			each its use adds a new item to a list of aliases.
-			The myself condition returns then  true 
-			also for any hostname on the list of aliases.
-			<example>
-			    <title>Use of uri==myself Expression</title>
-			    <programlisting format="linespecific">
-# ser powers a domain "foo.bar" and runs at host sipserver.foo.bar;
-# Names of served domains need to be stated in the aliases
-# option; myself would not match them otherwise and would only
-# match requests with "sipserver.foo.bar" in request-URI
-alias="foo.bar"
-alias="sales.foo.bar"
-route[0] {
-        if (uri==myself) {
-            # the request either has server name or some of the
-            # aliases in its URI
-            log(1,"request for served domain")
-            # some domain-specific logic follows here ....
-        } else {
-            # aha -- the server is not responsible for this
-            # requests; that happens for example with the following URIs
-            #  - sip:[email protected]
-            #  - sip:[email protected]
-            log(1,"request for outbound domain");
-            # outbound forwarding			  
-            t_relay();
-        };
-}			</programlisting>
-		    </example>
-		</para>
-		<para>
-		    It is possible to recognize whether a request belongs to
-		    a domain using regular expressions too. Care needs to
-		    be paid to construction of regular expressions. URI
-		    syntax is rich and an incorrect expression would result
-		    in incorrect call processing. The following example shows
-		    how an expression for domain matching can be formed.
-		    <example id="redomainmatching">
-			<title>Domain Matching Using Regular Expressions</title>
-			<para>
-			    In this example, server named "sip.foo.bar" with
-			    IP address 192.168.0.10 is responsible for the
-			    "foo.bar" domain. That means, requests with the
-			    following hostnames in URI should be matched:
-			    <itemizedlist>
-				<listitem>
-				    <para>
-					foo.bar, which is the name of server domain
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					sip.foo.bar, since it is server's name and some
-					devices put server's name in request URI
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					192.168.0.10, since it is server's IP address and
-					some devices put server's IP address in request URI
-				    </para>
-				</listitem>
-			    </itemizedlist>			
-			    Note how this regular expression is constructed. In particular:
-			    <itemizedlist>
-				<listitem>
-				    <para>
-					User name is optional (it is for example never included
-					in REGISTER requests) and there are no restrictions on
-					what characters it contains. That is what 
-					<emphasis>(.+@)?</emphasis> mandates. 
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Hostname must be followed by port number, parameters
-					or headers -- that is what the delimiters 
-					<emphasis>[:;\?]</emphasis> are good for. If none
-					it these follows, the URI must be ended 
-					(<emphasis>$</emphasis>). Otherwise, longer hostnames
-					such as 192.168.0.101 or foo.bar.otherdomain.com would
-					mistakenly match.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Matches are case-insensitive. All hostnames "foo.bar", "FOO.BAR"
-					and "FoO.bAr" match.
-				    </para>
-				</listitem>
-			    </itemizedlist>
-			</para>
-			<programlisting>
-if (uri=~"^sip:(.+@)?(192\.168\.0\.10|(sip\.)?foo\.bar)([:;\?].*)?$")
-      log(1, "yes, it is a request for our domain");
-      break;
- };
-			</programlisting>
-		    </example>
-		</para>
-		</section> <!-- domain matching -->
-		<section id="numberingplans">
-		    <title>Numbering Plans</title>
-
-		    <para>
-			Other use of URI matching is implementation of dialing
-			plans. A typical task when designing a dialing plan for SIP networks
-			is to distinguish between "pure-IP" and PSTN destinations.
-			IP users typically have either alphanumerical or numerical
-			usernames. The numerical usernames are convenient for PSTN
-			callers who can only
-			use numeric keypads. Next-hop destination of IP users is looked up dynamically
-			using user location database. On the other hand, PSTN destinations are 
-			always indicated by nummerical usernames. Requests to PSTN are statically 
-			forwarded to well-known PSTN gateways.
-		    </para>
-		    <example>
-			<title>A simple Numbering Plan</title>
-			<para>
-			    This example shows a simple dialing plan which reserves
-			    dialing prefix "8" for IP users, other numbers
-			    are used for PSTN destinations and all other non-nummerical
-			    usernames are used for IP users.
-			</para>
-			<programlisting format="linespecific">
-# is it a PSTN destination? (is username nummerical and does not begin with 8?)
-if (uri=~"^sip:[0-79][0-9]*@") { # ... forward to gateways then;
-      # check first to which PSTN destination the requests goes;
-      # if it is US (prefix "1"), use the gateway 192.168.0.1...
-      if (uri=~"^sip:1") {
-           # strip the leading "1"
-           strip(1);
-           forward(192.168.0.1, 5060);
-      } else {
-           # ... use the gateway 10.0.0.1 for all other destinations
-           forward(10.0.0.1, 5060);
-      }
-      break;
-} else {
-      # it is an IP destination -- try to lookup it up in user location DB
-      if (!lookup("location")) {
-          # bad luck ... user off-line
-          sl_send_reply("404", "Not Found");
-          break;
-      }
-      # user on-line...forward to his current destination
-      forward(uri:host,uri:port);
-}
-			</programlisting>
-		    </example>
-		</section> <!-- numbering plans -->
-	    </section>
-	</section> <!-- conditional statements -->
-	
-	<section id="urirewriting">
-	    <title>Request URI Rewriting</title>
-
-	    <para>
-		The ability to give users and services a unique name using URI
-		is a powerful tool. It allows users to advertise how to reach
-		them, to state to whom they wish to communicate and what services 
-		they wish to use.
-		Thus, the ability to change URIs is very important and is
-		used for implementation of many services. 
-		"Unconditional forwarding" from user "boss" to user
-		"secretary" is a typical example of application relying
-		on change of URI address.
-	    </para>
-	    <para>
-		<application moreinfo="none">ser</application> has the ability
-		to change request URI in many ways.
-		A script can use any of the following
-		built-in actions to change request URI or a part of it:
-
-		<command>rewriteuri</command>, 
-		<command>rewritehost</command>, 
-		<command>rewritehostport</command>, 
-		<command>rewriteuser</command>, 
-		<command>rewriteuserpass</command> and 
-		<command>rewriteport</command>. 
-		When later in the script
-		a forwarding action is encountered, the action forwards
-		the request to address in the rewritten URI.
-		<example>
-		    <title>Rewriting URIs</title>
-		    <programlisting format="linespecific">
-if (uri=~"[email protected]") {
-    rewriteuri("sip:[email protected]")
-    # forward statelessly to the destination in current URI, i.e.,
-    # to sip:[email protected]:5060
-    forward( uri:host, uri:port);
-}
-		    </programlisting>
-		</example>
-	    </para>	    
-	    <para>Two more built-in URI-rewriting commands are of special importance
-		for implementation of dialing plans and manipulation of dialing
-		prefixes. <command>prefix(s)
-		</command>, inserts 
-		a string "s" in front of SIP address and 
-		<command>strip(n)</command> takes
-		away the first "n" characters of a SIP address.
-		See <xref linkend="urirewritingexamples"> for examples of use of
-		built-in URI-rewriting actions.
-	    </para>
-
-	    <para>
-		Commands exported by external modules can change URI too
-		and many do so.
-		The most important application is changing URI using the
-		user location database. The command 
-		<command>lookup(table)</command> looks up current
-		user's location and rewrites user's address with it.
-		If there is no registered contact, the 	command returns a negative value.
-
-
-		<example id=rewriteuri>
-		    <title>Rewriting URIs Using User Location Database</title>
-		    <programlisting format="linespecific">
-# store user location if a REGISTER appears
-if (method=="REGISTER") {
-   save("mydomain1");
-} else {
-# try to use the previously registered contacts to
-# determine next hop
-   if(lookup("mydomain1")) {
-     # if found, forward there...
-     t_relay();
-   } else {
-     # ... if no contact on-line, tell it upstream
-     sl_send_reply("404", "Not Found" );
-   };
-};
-		    </programlisting>
-		</example>
-	    </para>
-	    <para>
-		External applications can be used to rewrite URI too.
-		The "exec" module provides script actions, which start external programs
-		and read new URI value from their output. <command moreinfo="none">exec_uri</command>
-		and <command moreinfo="none">exec_user</command> both call an external program,
-		pass current URI or its user part to it respectively, wait until it completes,
-		and eventually rewrite current URI with its output.
-	    </para>
-	    <para>
-		It is important to realize that <application moreinfo="none">ser</application>
-		operates over <emphasis>current URI</emphasis> all the time. If an original
-		URI is rewritten by a new one, the original will will be forgotten and the new one will 
-		be used in any further processing. In particular, the uri matching operand
-		and the user location action <command moreinfo="none">lookup</command>
-		always take current URI as input, regardless what the original URI was.
-	    </para>
-	    <para>
-		<xref linkend="urirewritingexamples"> shows how URI-rewriting actions affect 
-		an example URI, sip:[email protected]:6060.
-		<table id="urirewritingexamples">
-		    <title>URI-rewriting Using Built-In Actions</title>
-		    <tgroup cols="2">
-			<thead>
-			    <row>
-				<entry>
-				    Example Action
-				</entry>				
-				<entry>
-				    Resulting URI
-				</entry>
-			    </row>
-			</thead>
-			<tbody>
-			    <row>
-				<entry>
-				    <command moreinfo="none">rewritehost("192.168.0.10")</command> rewrites
-				    the hostname in URI, other parts (including port number) remain unaffected.
-				</entry>
-				<entry>
-				    sip:[email protected]:6060
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">rewriteuri("sip:[email protected]");</command> rewrites
-				    the whole URI completely.
-				</entry>
-				<entry>
-				    sip:[email protected]
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">rewritehostport("192.168.0.10:3040")</command>rewrites 
-				    both hostname and port number in URI.
-				</entry>
-				<entry>
-				    sip:[email protected]:3040
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">rewriteuser("alice")</command> rewrites user part of URI.
-				</entry>
-				<entry>
-				    sip:[email protected]:6060
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">rewriteuserpass("alice:pw")</command> replaces the pair
-				    user:password in URI with a new value.
-				</entry>
-				<entry>
-				    sip:alice:[email protected]:6060
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">rewriteport("1234")</command> replaces port number in URI
-				</entry>
-				<entry>
-				    sip:[email protected]:1234
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">prefix("9")</command> inserts a string ahead of user part of URI
-				</entry>
-				<entry>
-				    sip:[email protected]:6060
-				</entry>
-			    </row>
-			    <row>
-				<entry>
-				    <command moreinfo="none">strip(2)</command> removes leading characters from user part of URI
-				</entry>
-				<entry>
-				    sip:[email protected]:6060
-				</entry>
-			    </row>
-
-
-			</tbody>
-		    </tgroup>
-		</table>
-	    </para>	    
-	    <para>
-		You can verify whether you understood URI processing by
-		looking at the following example. It rewrites URI
-		several times. The question is what is the final URI to which
-		the script fill forward any incoming request.
-		<example>
-		    <title>URI-rewriting Exercise</title>
-		    <programlisting format="linespecific">
-exec_uri("echo sip:[email protected]; echo > /dev/null");
-strip(2);
-if (uri=~"^sip:2") {
-    prefix("0");
-} else {
-    prefix("1");
-};			
-forward(uri:host, uri:port);
-		    </programlisting>
-		</example>
-	    </para>
-	    <para>
-		The correct answer is the resulting URI will be
-		"sip:[email protected]". <command moreinfo="none">exec_uri</command>
-		rewrites original URI to "sip:[email protected]", 
-		<command moreinfo="none">strip(2)</command> takes
-		two leading characters from username away resulting
-		in "[email protected]", the condition does not match
-		because URI does not begin with "2" any more,
-		so the prefix "1" is inserted.
-	    </para>
-
-
-	</section> <!-- URI rewriting -->
-
-	<section>
-	    <title>Destination Set</title>
-	    <para>
-		Whereas needs of many scenarios can by accommodated by maintaining
-		a single request URI, some scenarios are better served by
-		multiple URIs. Consider for example a user with address
-		[email protected]. The user wishes to be reachable at his 
-		home phone, office phone, cell phone, softphone, etc. 
-		However, he still wishes to maintain a single public address
-		on his business card.
-	    </para>
-	    <para>
-		To enable such scenarios, <application>ser</application>
-		allows translation of a single request URI into multiple
-		outgoing URIs. The ability to forward a request to multiple
-		destinations is known as <emphasis>forking</emphasis>
-		in SIP language. All outogoing URIs (in trivial case one of them)
-		are called <emphasis>destination set</emphasis>. The destination
-		set always includes one default URI, to which additional URIs
-		can be appended. Maximum size of a destination set is limited by 
-		a compile-time constant, MAX_BRANCHES,
-		in <filename moreinfo="none">config.h</filename>.
-	    </para>
-	    <para>
-		Some actions are designed for use with a single URI whereas
-		other actions work with the whole destination set.
-	    </para>
-	    <para>
-		Actions which are currently available for creating the destination
-		set are <command>lookup</command> from usrloc module and 
-		<command>exec_uri/exec_user</command> from exec module.
-		<command moreinfo="none">lookup</command> fills in the destination
-		set with user contact's registered previously with REGISTER
-		requests. The <command moreinfo="none">exec</command> actions
-		fill in the destination set with output of an external program.
-		In both cases, current destination set is completely rewritten.		
-		New URIs can be appended to destination set by a call to the built-in
-		action <command>append_branch(uri)</command>.
-	    </para>
-	    <para>		
-		Currently supported features which utilize destination sets
-		are <emphasis>forking</emphasis> and <emphasis>redirection</emphasis>. 
-		Action <command>t_relay</command> (TM module) for stateful
-		forwarding supports forking. If called with a non-trivial destination
-		set, <command moreinfo="none">t_relay</command> forks
-		incoming request to all URIs in current destination set.
-		See <xref linkend="rewriteuri">. If a user
-		previously registered from three locations, the destination set is filled with 
-		all of them by <command>lookup</command> and the <command>t_relay</command>
-		command forwards the incoming request to all these destinations.
-		Eventually, all user's phone will be ringing in parallel.
-	    </para>
-	    <para>
-		SIP redirection is another feature which leverages destination sets.
-		It is a very light-weighted method to establish communication
-		between two parties with minimum burden put on the server. In
-		<application>ser</application>, the action <command>sl_send_reply</command>
-		(SL module) is used for this purpose. This action 
-		allows to generate replies to SIP requests without keeping 
-		any state. If the status code passed to the action is 3xx, 
-		the current destination set is printed in reply's Contact header
-		fields. Such a reply instructs the originating client to 
-		retry at these addresses. (See <xref linkend="redirectexample">).
-	    </para>
-	    <para>
-		Most other  <application>ser</application> actions ignore destination
-		sets: they either do not relate to URI processing (<command moreinfo="none">
-		log</command>, for example) or they work only with the default URI.
-		All URI-rewriting functions such as
-		<command moreinfo="none">rewriteuri</command> belong in this
-		category. URI-comparison operands only refers to the first URI
-		(see <xref linkend="operators">). Also, the built-in action
-		for stateless forwarding, <command>forward</command> works only
-		with the default URI and ignores rest of the destination set. The reason 
-		is a proxy server willing to fork must guarantee that the burden
-		of processing multiple replies is not put unexpectedly on upstream
-		client. This is only achievable with stateful processing.  
-		Forking cannot be used along with stateless <command>forward</command>,
-		which thus only processes one URI out of the whole destination set.
-		Also, the uri comparison operand (see <xref linkend="operators">)
-		refers only to current URI and ignores the rest of destination
-		set.
-	    </para> 
-
-	</section> <!-- Destination Set -->
-
-	<section>
-	    <title>User Location</title>
-	    <para>
-		Mobility is a key feature of SIP. Users are able to use one
-		one or more SIP devices and be reachable at them. Incoming requests 
-		for users are forwarded to all user's devices in use. The key
-		concept is that of soft-state registration. Users can
-		-- if in possession of valid credentials -- link SIP
-		devices to their e-mail like address of record. Their SIP devices
-		do so using a REGISTER request, as in <xref linkend="register">.
-		The request creates a binding between the public address of
-		record (To header field) and SIP device's current address
-		(Contact header field). 
-		<example id="register">
-		    <title>REGISTER Request</title>
-		    <programlisting format="linespecific">
-REGISTER sip:192.168.2.16 SIP/2.0
-Via: SIP/2.0/UDP 192.168.2.16;branch=z9hG4bKd5e5.5a9947e4.0
-Via: SIP/2.0/UDP 192.168.2.33:5060
-From: sip:[email protected]
-To: sip:[email protected]
-Call-ID: [email protected]
-Date: Wed, 29 Jan 2003 18:13:15 GMT
-CSeq: 101 REGISTER
-User-Agent: CSCO/4
-Contact: sip:[email protected]:5060
-Content-Length: 0
-Expires: 600
-		    </programlisting>
-		</example>
-		Similar requests can be used to query all user's current contacts or to
-		delete them. All Contacts have certain time to live, when the time expires,
-		contact is removed and no longer used for processing of incoming requests.
-	    </para>
-	    <para>
-		<application moreinfo="none">ser</application> is built to do both: update
-		user location database from received REGISTER requests and look-up these
-		contacts when inbound requests for a user arrive. To achieve high performance,
-		the user location table is stored in memory. In regular intervals
-		(usrloc module's parameter <varname>timer_interval</varname> determines
-		their length), all changes to the in-memory table are backed up in
-		<application moreinfo="none">mysql</application> database to achieve
-		peristence accross server reboots. Administrators or application writers
-		can lookup list of current user's contacts stored in memory using the
-		<application moreinfo="none">serctl</application> tool (see <xref linkend="serctl">).
-		<example>
-		    <title>Use of <application>serctl</application> Tool to Query User Location</title>
-		    <screen format="linespecific">
-<![CDATA[
-[jiri@fox jiri]$ sc ul show jiri
-<sip:[email protected]>;q=0.00;expires=456
-<sip:[email protected]>;q=0.00;expires=36000
-]]>
-		    </screen>
-		</example>
-	    </para>
-	    <para>
-		Building user location in <application moreinfo="none">ser</application> scripts is
-		quite easy. One first needs to determine whether a request is for served domain,
-		as described in <xref linkend="domainmatching">. If that is the case, the script
-		needs to distinguish between REGISTER requests, that update user location table,
-		and all other requests for which next hop is determined from the table. The
-		<command moreinfo="none">save</command> action is used to update user location
-		(i.e., it writes to it). The <command moreinfo="none">lookup</command> actions
-		reads from the user location table and fills in destination set with current
-		user's contacts.
-		<example>
-		    <title>Use of User Location Actions</title>
-		    <programlisting format="linespecific">
-# is the request for my domain ?
-if (uri==myself) {
-    if (method=="REGISTER") { # REGISTERs are used to update
-         save("location");
-         break; # that's it, we saved the contacts, exit now
-    } else {
-         if (!lookup("location") { # no registered contact
-            sl_send_reply("404", "Not Found");
-            break;
-         }
-         # ok -- there are some contacts for the user; forward
-         # the incoming request to all of them
-         t_relay();
-    };
-};
-		    </programlisting>
-		</example>
-	    </para>
-	    <para>
-		Note that we used the action for stateful forwarding, 
-		<command moreinfo="none">t_relay</command>. That's is because
-		stateful forwarding allows to fork an incoming request to
-		multiple destinations. If we used stateful forwarding,
-		the request would be forwarded only to one uri out of
-		all user's contacts.
-	    </para>
-	</section> <!-- User Location -->
-	
-	<section>
-	    <title>External Modules</title>
-	    <para>
-		<application moreinfo="none">ser</application> provides the ability to link the server with external
-		third-party shared libraries. Lot of functionality which is
-		included in the <application moreinfo="none">ser</application> distribution is actually located in
-		modules to keep the server "core" compact and clean.
-		Among others, there are modules for checking max_forwards
-		value in SIP requests (maxfwd), transactional processing (tm),
-		record routing (rr), accounting (acc), authentication (auth),
-		SMS gateway (sms), replying requests (sl), user location
-		(usrloc, registrar) and more.
-	    </para>
-	    <para>
-		In order to utilize new actions exported by a module, 
-		ser must first load it. To load a module, the directive
-		<command moreinfo="none">loadmodule "filename"</command>
-		must be included in beginning of
-		a <application>ser</application> script file.
-	    </para>
-
-	    <example>
-		<title>Using Modules</title>
-		<para>
-		    This example shows how a script instructs 
-		    <application moreinfo="none">ser</application> to
-		    load a module and use actions exported by it.
-		    Particularly, the sl module exports an action
-		    <command>sl_send_reply</command> which makes 
-		    <application>ser</application> act as a stateless
-		    user agent and reply all incoming requests with 404.
-		</para>
-		<programlisting format="linespecific">
-# first of all, load the module!
-loadmodule "/usr/lib/ser/modules/sl.so
-route{
-    # reply all requests with 404
-    sl_send_reply("404", "I am so sorry -- user not found");
-}
-</programlisting>
-	    </example>
-	    <note>
-		<para>Note that unlike with core commands, all actions
-		    exported by modules must have parameters enclosed
-		    in quotation marks in current version of 
-		    <application moreinfo="none">ser</application>.
-		    In the following example, the built-in action
-		    <command moreinfo="none">forward</command> for
-		    stateless forwarding takes
-		    IP address and port numbers as parameters without
-		    quotation marks whereas a module action 
-		    <command moreinfo="none">t_relay</command> for
-		    stateful forwarding takes parameters enclosed in
-		    quotation marks.
-		    <example>
-			<title>Parameters in built-in and exported
-			actions</title>
-			<programlisting format="linespecific">
-# built-in action doesn't enclose IP addresses and port numbers
-# in quotation marks
-forward(192.168.99.100, 5060);
-# module-exported functions enclose all parameters in quotation
-# marks
-t_relay_to("192.168.99.100", "5060");
-			</programlisting>
-		    </example>
-		</para>
-	    </note>
-	    <para>
-		Many modules also allow users to change the way how they
-		work using predefined parameters. For example, the
-		authentication module needs to know location of MySQL
-		database which contains users' security credentials.
-		How module parameters
-		are set using the <command moreinfo="none">modparam</command>
-		directive is shown in <xref linkend="moduleparameters">. 
-		<command moreinfo="none">modparam</command>
-		always contains identification of module, parameter
-		name and parameter value. Description of parameters
-		available in modules is available in module documentation.
-	    </para>
-	    <para>
-		Yet another thing to notice in this example is module
-		dependency. Modules may depend on each other. For example,
-		the authentication modules leverages the mysql module
-		for accessing mysql databases and sl module for generating
-		authentication challenges. We recommend that modules are
-		loaded in dependency order to avoid ambiguous server
-		behaviour.
-	    </para>	    
-	    <para>
-		<example id="moduleparameters">
-		    <title>Module Parameters</title>
-		    <programlisting format="linespecific">
-# ------------------ module loading ----------------------------------
-
-# load first modules on which 'auth' module depends;
-# sl is used for sending challenges, mysql for storage
-# of user credentials
-loadmodule "modules/sl/sl.so"
-loadmodule "modules/mysql/mysql.so"
-loadmodule "modules/auth/auth.so"
-
-# ------------------ module parameters -------------------------------
-# tell the auth module the access data for SQL database:
-# username, password, hostname and database name
-modparam("auth", "db_url","sql://ser:secret@dbhost/ser")
-
-
-# -------------------------  request routing logic -------------------
-
-# authenticate all requests prior to forwarding them
 
-route{
+&general;    
 
-        if (!proxy_authorize("foo.bar" /* realm */,
-                        "subscriber" /* table name */ )) {
-                proxy_challenge("foo.bar", "0");
-                break;
-        };
-        forward(192.168.0.10,5060);
-}
+&intro;
 
-		    </programlisting>
-		</example>
-	    </para>
-	</section>
-
-	<section>
-	    <title>Writing Scripts</title>
-	    <para>
-		This section demonstrates simple examples
-		how to configure server's behaviour using the
-		<application moreinfo="none">ser</application>
-		request routing language. All scripts follow the 
-		<application moreinfo="none">ser</application> language 
-		syntax, which dictates the following block ordering:
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    <emphasis>global configuration parameters</emphasis> --
-			    these value affect behaviour of the server such as port
-			    number at which it listens, number of spawned children
-			    processes, and log-level. See <xref linkend="coreoptions">
-			    for a list of available options.
-			</para>
-		    </listitem>
-
-		    <listitem>
-			<para>
-			    <emphasis>module loading</emphasis> -- these statements
-			    link external modules, such as transaction management
-			    (tm) or stateless UA server (sl)  dynamically. See
-			    <xref linkend="modulereference"> for a list of modules
-			    included in <application moreinfo="none">ser</application>
-			    distribution.
-			</para>
-			<note>
-				<para>
-					If modules depend on each other, than the depending
-					modules must be loaded after modules on which they
-					depend. We recommend to load first modules
-					<command>tm</command> and <command>sl</command>
-					because many other modules (authentication, user
-					location, accounting, etc.) depend on these.
-				</para>
-			</note>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>module-specific parameters</emphasis> -- determine
-			    how modules behave; for example, it is possible to configure
-			    database to be used by authentication module.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    one or more <emphasis>route blocks</emphasis> containing the
-			    request processing logic, which includes built-in actions
-			    as well as actions exported by modules. See <xref linkend="builtinref">
-			    for a list of built-in actions.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    optionally, if modules supporting reply
-			    processing (currently only TM) are loaded,
-			    one or more <emphasis>reply_route blocks</emphasis> containing
-			    logic triggered by received replies. Restrictions on use of
-			    actions within <command moreinfo="none">reply_route</command>
-			    blocks apply -- see <xref linkend="builtinref"> for more
-			    information.
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </para>
-
-	    <para>
-		For more complex examples, see the etc directory in
-		<application>ser</application> source distribution.
-		It contains the 
-		<filename moreinfo="none">iptel.cfg</filename> script which is
-		in production use at iptel.org's public SIP site and exploits most of 
-		<application>ser</application> features.
-	    </para>
-
-	    <section id="defaultscript">
-		<title>Default Configuration Script</title>		
-		<para>
-		    The configuration script, <filename moreinfo="none">ser.cfg</filename>,
-		    is a part of every <application moreinfo="none">ser</application>
-		    distribution and defines default behaviour. It allows users
-		    to register with the server and have requests proxied to each
-		    other.
-		</para>
-		<para>
-		    After performing
-		    routine checks, the script looks whether incoming request is for
-		    served domain. If so and the request is "REGISTER", <application moreinfo="none">ser</application>
-		    acts as SIP registrar and updates database of user's contacts.
-		    Optionally, it verifies user's identity first to avoid
-		    unauthorized contact manipulation.
-		</para>
-		<para>
-		    Non-REGISTER request for served domains are then processed using
-		    user location database. If a contact is found for requested URI,
-		    script execution proceeds to stateful forwarding, a negative 404
-		    reply is generated otherwise. Requests outside served domain
-		    are always statefully forwarded.
-		</para>
-		<para>
-		    Note that this simple script features several limitations:
-		    <itemizedlist>
-			<listitem>			    
-			    <para>
-				By default, authentication is turned off to avoid
-				dependency on mysql. Unless it it turned on, anyone
-				can register using any name and "steal" someone else's
-				calls.
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				Even it authentication is turned on, there is no relationship
-				between authentication username and address of record. That
-				means that for example a user authenticating himself correctly
-				with "john.doe" id may register contacts for "gw.bush".
-				Site policy may wish to mandate authentication id to be equal
-				to username claimed in To header field. <action moreinfo="none">check_to</action>
-				action from auth module can be used to enforce such a policy.
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				There is no dialing plan implemented. All users are supposed to
-				be reachable via user location database. See <xref linkend="numberingplans">
-				for more information.
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				The script assumes users will be using server's name as a part of
-				their address of record. If users wish to use another name (domain
-				name for example), this must be set using the <varname>alias</varname>
-				options. See <xref linkend="domainmatching"> for more information.
-			    </para>
-			</listitem>
-			<listitem>
-			    <para>
-				If authentication is turned on by uncommenting related configuration
-				options, clear-text user passwords will by assumed in back-end database.
-			    </para>
-			</listitem>
-		    </itemizedlist>
-		</para>
-		<example>
-		    <title>Default Configuration Script</title>
-		    <programlisting format="linespecific">
-&defscr;			
-		    </programlisting>
-		</example>
-	    </section>
-
-	    <section id="statefulua">
-		<title>Stateful User Agent Server</title>
-		<para>
-		    This examples shows how to make ser act as a stateful user
-		    agent (UA). Ability to act as as a stateful UA is essential
-		    to many applications which terminate a SIP path. These
-		    applications wish to focus on their added value. They
-		    do not wish to be involved in all SIP gory details, such
-		    as request and reply retransmission, reply formatting, etc.
-		    For example, we use the UA functionality to shield 
-		    SMS gateway and instant message store from SIP transactional
-		    processing.
-		    The simple example bellow issues a log report on receipt
-		    of a new transaction. 
-		    If we did not use a stateful UA, every single request retransmission
-		    would cause the application to be re-executed which would result in
-		    duplicated SMS messages, instant message in message store or 
-		    log reports.
-		</para>
-		<para>
-		    The most important actions are <command moreinfo="none">
-			t_newtran</command> and <command moreinfo="none">
-			t_reply</command>. <command moreinfo="none">
-			
-		    t_newtran</command> shields subsequent code from retransmissions.
-		    It returns success and continues when a new request arrived.
-		    It exits current route block immediately on receipt of
-		    a retransmissions. It only returns a negative value when
-		    a serious error, such as lack of memory, occurs.
-		</para>
-		<para>
-		    <command moreinfo="none">t_reply</command> generates
-		    a reply for a request. It generates the reply statefully,
-		    i.e., it is kept for future retransmissions in memory.
-		</para>
-		<note>
-			<para>
-				Applications that do not need stateful processing
-				may act as stateless UA Server too. They just use
-				the <command>sl_send_reply</command> action to
-				send replies to requests without keeping any
-				state. The benefit is memory cannot run out,
-				the drawback is that each retransmission needs to
-				be processed as a new request. An example of use
-				of a stateless server is shown in
-		    	<xref linkend="redirectserver"> and
-		    	<xref linkend="executingscript">.
-			</para>
-		</note>
-		<example>
-		    <title>Stateful UA Server</title>
-		    <programlisting format="linespecific">
-			<!-- ../../examples/uas.cfg -->
-			&statefuluaexample;
-		    </programlisting>
-		</example>
-	    </section> <!-- Stateful UAS -->
-
-	    <section id="redirectserver">
-		<title>Redirect Server</title>
-		<para>
-		    The redirect example shows how to redirect a request
-		    to multiple destination using 3xx reply. Redirecting
-		    requests as opposed to proxying them is essential to
-		    various scalability scenarios. Once a message is
-		    redirected, <application moreinfo="none">ser</application>
-		    discards all related state and is no more involved
-		    in subsequent SIP transactions (unless the redirection
-		    addresses point to the same server again).
-		</para>
-		<para>
-		    The key <application>ser</application> actions in this example 
-		    are <command moreinfo="none">append_branch</command> and 
-		    <command moreinfo="none">sl_send_reply</command> (sl module).
-		</para>
-		<para>
-		    <command moreinfo="none">append_branch</command> adds
-		    a new item to the destination set. The destinations set always
-		    includes the current URI and may be enhanced up to
-		    <constant>MAX_BRANCHES</constant> items.
-		    <command moreinfo="none">sl_send_reply</command> command, 
-		    if passed SIP reply code 3xx, takes all values in current 
-		    destination set and adds them to Contact header field in 
-		    the reply being  sent.
-		</para>
-		<example id="redirectexample">
-		    <title>Redirect Server</title>
-		    <programlisting format="linespecific">
-			<!-- ../../examples/redirect.cfg -->
-			&redirectexample;
-		    </programlisting>
-		</example>
-	    </section> <!-- redirect server-->
-	    
-	    <section id="executingscript">
-		<title>Executing External Script</title>
-		<para>
-		    Like in the previous example, we show how to
-		    make ser act as a redirect server. The difference is 
-		    that we do not use redirection addresses hardwired in
-		    <application moreinfo="none">ser</application> script but
-		    get them from external shell commands. We also use
-		    ser's ability to execute shell commands to log
-		    source IP address of incoming SIP requests.
-		</para>
-		<para>
-		    The new commands introduced in this example are
-		    <command moreinfo="none">exec_msg</command> and
-		    <command moreinfo="none">exec_uri</command>.
-		    <command moreinfo="none">exec_msg</command> takes
-		    current requests, starts an external command, and
-		    passes the requests to the command's standard input.
-		    It also passes request's source IP address in
-		    environment variable named <constant>SRC_IP</constant>.
-		</para>
-		<para>
-		    <command moreinfo="none">exec_uri</command> serves
-		    for URI rewriting by external applications.  The
-		    <command moreinfo="none">exec_uri</command> action
-		    passes current URI to the called external program as
-		    command-line parameter, and rewrites current destination
-		    set with the program's output. An example use would
-		    be an implementation of a Least-Cost-Router, software which
-		    returns URI of the cheapest PSTN provider for a given
-		    destination based on some pricing tables. <xref linkend="execscript">
-		    is much easier: it prints fixed URIs on its output using
-		    shell script <command moreinfo="none">echo</command> command.
-		</para>
-		<note>
-			<para>
-				This script works statelessly -- it uses this action for
-				stateless replying, <command>sl_send_reply</command>.
-				No transaction is kept in memory and each request retransmission
-				is processed as a brand-new request. That may be a particular
-				concern if the server logic (<command>exec</command> actions
-				in this example) is too expensive. See 
-		    	<xref linkend="statefulua"> for instructions on how
-				to make server logic stateful, so that retransmissions
-				are absorbed and do not cause re-execution of the logic.
-			
-			</para>
-		</note>
-		<example id="execscript">
-		    <title>Executing External Script</title>
-		    <programlisting format="linespecific">
-			<!-- ../../examples/exec.cfg -->
-			&execexample;
-		    </programlisting>
-		</example>
-	    </section> <!-- exec example -->
-	    
-	    <section id="replyprocessingsection">
-		<title>On-Reply Processing (Forward on Unavailable)</title>
-		<para>
-		    Many services depend on status of messages relayed
-		    downstream: <emphasis>forward on busy</emphasis> and 
-		    <emphasis>forward on no reply</emphasis> to name the
-		    most well-known ones. To support implementation of
-		    such services, <application moreinfo="none">ser</application>
-		    allows to return to request processing when request
-		    forwarding failed. When a request is reprocessed,
-		    new request branches may be initiated or the transaction
-		    can be completed at discretion of script writer.
-		</para>
-		<para>
-		    The primitives used are <command moreinfo="none">t_on_negative(r)</command>
-		    and <command moreinfo="none">reply_route[r]{}.</command> If
-		    <command>t_on_negative</command> is called before
-		    a request is statefuly forwarded and a forwarding failure occurs, 
-		    <application moreinfo="none">ser</application>
-		    will return to request processing in a <command moreinfo="none">reply_route</command>
-		    block. Failures include receipt of a SIP error
-		    (status code >= 300 ) from upstream or not receiving
-		    any final reply within final response period.
-		</para>
-		<para>
-		    The length of the timer is governed by parameters of the
-		    tm module. <varname>fr_timer</varname> is the length of
-		    timer set for non-INVITE transactions and INVITE transactions
-		    for which no provisional response is received. If a timer
-		    hits, it indicates that a downstream server is unresponsive.
-		    <varname>fr_inv_timer</varname> governs time to wait for 
-		    a final reply for an INVITE. It is typically longer than
-		    <varname>fr_timer</varname> because final reply may take
-		    long time until callee (finds a mobile phone in a pocket and)
-		    answers the call.
-		</para>
-		<para>
-		    In <xref linkend="replyprocessing">, <command moreinfo="none">reply_route[1]</command>
-		    is set to be entered on error using the <command moreinfo="none">t_on_negative(1)</command>
-		    action. Within this reply block, <application moreinfo="none">ser</application>
-		    is instructed to initiate a new branch and try to reach called party
-		    at another destination (sip:[email protected]). To deal with the case when neither the alternate
-		    destination succeeds, <application moreinfo="none">t_on_negative</application>
-		    is set again. If the case really occurs, <command moreinfo="none">reply_route[2]</command>
-		    is entered and a last resort destination (sip:[email protected]) is tried.
-		</para>
-		<example id="replyprocessing">
-		    <title>On-Reply Processing</title>
-		    <programlisting format="linespecific">
-			<!-- ../../examples/onr.cfg -->
-			&replyexample;
-		    </programlisting>
-
-		</example>
-	    </section> <!-- reply processing -->
-	</section> <!-- examples -->
-    </chapter>
-
-
-    <chapter>
-	<title>Server Operation</title>
-	<section id="operationalpractices">
-	    <title>Recommended Operational Practices</title>
-
-	    <para>
-		Operation of a SIP server is not always easy task.
-		Server administrators are challenged by broken or
-		misconfigured user agents, network and host failures,
-		hostile attacks and other stress-makers. All such
-		situations may lead to an operational failure. It is sometimes
-		very difficult to figure out the root reason of
-		a failure, particularly in a distributed environment
-		with many SIP components involved.		
-		In this section,
-		we share some of our practices and refer to tools
-		which have proven to
-		make life of administrators easier
-	    </para>
-
-	<qandaset>
-	    <qandaentry>
-		<question>
-		    <para>
-			Keeping track of messages is good
-		    </para>
-		</question>
-		<answer>
-			<para>
-			    Frequently, operational errors are discovered or reported
-			    with a delay.
-			    Users frustrated by an error
-			    frequently approach administrators
-			    and scream "even though my SIP requests were absolutely ok
-			    yesterday, they were mistakenly denied by your server".
-			    If administrators do not record all SIP traffic at
-			    their site, they will be no more able to identify
-			    the problem reason.
-			    We thus recommend that site
-			    operators record all messages passing their site and keep them
-			    stored for some period of time.
-			They may use utilities such as 
-			<application>ngrep 
-			</application> or 
-			<application>tcpdump
-			</application>.
-			There is also a utility <application moreinfo="none">
-			    scripts/harv_ser.sh</application> in <application moreinfo="none">
-			ser</application> distribution for post-processing
-			of captured messages. It summarizes messages captured
-			by reply status and user-agent header field.
-		    </para>
-		</answer>
-	    </qandaentry>
-	    <qandaentry>
-		<question>
-		    <para>
-			Real-time Traffic Watching
-		    </para>
-		</question>
-		<answer>
-			<para>
-		    Looking at SIP messages in real-time may help to gain
-		    understanding of problems. Though there are commercial
-		    tools available, using a simple, text-oriented tool
-		    such as <application>ngrep</application> makes the job very well thanks to SIP's textual nature.
-			</para>
-		    <example id="usingngrep">
-			<title>Using <application>ngrep</application>
-			</title>
-			<para>In this example, all messages at port 5060
-			which include the string "bkraegelin" are captured
-			and displayed</para>
-			<programlisting format="linespecific">
-[jiri@fox s]$ ngrep bkraegelin@ port 5060
-interface: eth0 (195.37.77.96/255.255.255.240)
-filter: ip and ( port 5060 )
-match: bkraegelin@
-#
-U +0.000000 153.96.14.162:50240 -> 195.37.77.101:5060
-REGISTER sip:iptel.org SIP/2.0.
-Via: SIP/2.0/UDP 153.96.14.162:5060.
-From: sip:[email protected].
-To: sip:[email protected].
-Call-ID: [email protected].
-Date: Thu, 26 Sep 2002 22:03:55 GMT.
-CSeq: 101 REGISTER.
-Expires: 10.
-Content-Length: 0.
-.
-
-#
-U +0.000406 195.37.77.101:5060 -> 153.96.14.162:5060
-SIP/2.0 401 Unauthorized.
-Via: SIP/2.0/UDP 153.96.14.162:5060.
-From: sip:[email protected].
-To: sip:[email protected].
-Call-ID: [email protected].
-CSeq: 101 REGISTER.
-WWW-Authenticate: Digest realm="iptel.org", nonce="3d9385170000000043acbf6ba9c9741790e0c57adee73812", algorithm=MD5.
-Server: Sip EXpress router(0.8.8 (i386/linux)).
-Content-Length: 0.
-Warning: 392 127.0.0.1:5060 "Noisy feedback tells: pid=31604 req_src_ip=153.96.14.162 in_uri=sip:iptel.org out_uri=sip:iptel.org via_cnt==1".
-
-			</programlisting>
-		    </example>
-		</answer>
-	    </qandaentry>
-	    <qandaentry>
-		<question>
-		    <para>
-			Tracing Errors in Server Chains
-		    </para>
-		</question>
-		<answer>
-			<para>
-			    A request may pass any number of proxy servers on
-			    its path to its destination. If an error occurs
-			    in the chain, it is difficult for upstream troubleshooters
-			    and/or users complaining to administrators to learn 
-			    more about error circumstances. 
-			    <application moreinfo="none">ser
-			    </application> does its best and displays extensive
-			    diagnostics information in SIP replies. It allows 
-			    troubleshooters and/or users who report to troubleshooters
-			    to gain additional knowledge about request processing
-			    status. 
-			    This extended debugging information is part of the warning 
-			    header field. See <xref linkend="usingngrep"> for an illustration
-			    of a reply that includes such a warning header field. The header
-			    field contains the following pieces of information:
-			<itemizedlist>
-			    <listitem>
-				<para>
-				Server's IP Address -- good to identify
-				from which server in a chain the reply
-				came.
-				    </para>
-			    </listitem>
-			    <listitem>
-				    <para>
-					Incoming and outgoing URIs -- good to
-					learn for which URI the reply was
-					generated, as it may be rewritten
-					many times in the path. Particularly
-					useful for debugging of numbering plans.
-				    </para>
-			    </listitem>
-			    <listitem>
-				<para>
-					Number of Via header fields in replied
-					request -- that helps in assessment of
-					request path length. Upstream clients would
-					not know otherwise, how far away in terms
-					of SIP hops their requests were replied.
-				</para>
-			    </listitem>
-				<listitem>
-				    <para>
-					Server's process id. That is useful for
-					debugging to discover situations when
-					mutliple servers listen at the same
-					address.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					IP address of previous SIP hop as seen by
-					the SIP server.
-				    </para>
-				</listitem>
-			</itemizedlist>
-		    </para>
-			<para>
-			    If server administrator is not comfortable with
-			    disclosing all this information, he can turn them
-			    off using the <varname>sip_warning</varname> configuration
-			    option.
-			</para>
-		    <para>
-			A nice utility for debugging server chains is
-			<application moreinfo="none">sipsak</application>,
-			Swiss Army Knife, traceroute-like tool for SIP
-			developed at iptel.org. It allows you to send
-			OPTIONS request with low, increasing Max-Forwards 
-			header-fields and follow how it propagates in
-			SIP network. See its webpage at
-			<ulink url="http://sipsak.berlios.de/">
-			    http://sipsak.berlios.de/
-			</ulink>.
-		    </para>
-		    <example>
-			<title>Use of SIPSak for Learning SIP Path</title>
-			<programlisting format="linespecific">
-[jiri@bat sipsak]$ ./sipsak -T -s sip:[email protected]
-warning: IP extract from warning activated to be more informational
-0: 127.0.0.1 (0.456 ms) SIP/2.0 483 Too Many Hops
-1: ?? (31.657 ms) SIP/2.0 200 OK
-	without Contact header
-
-			</programlisting>
-			<para>
-			    Note that in this example, the second hop
-			    server does not issue any warning header fields
-			    in replies and it is thus impossible to display 
-			    its IP address in <application moreinfo="none">
-			    SIPsak</application>'s output.
-			</para>
-		    </example>
-		</answer>
-	    </qandaentry>
-	    <qandaentry>
-		<question>
-		    <para>
-			Watching Server Health
-		    </para>
-		</question>
-		<answer>
-		    <para>
-			Watching Server's operation status in real-time may
-			also be a great aid for trouble-shooting. 
-			<application>ser</application> has an excellent 
-			facility, a FIFO server, which allows UNIX
-			tools to access server's internals. (It is 
-			similar to how Linux tool access Linux kernel
-			via the proc file system.) The FIFO server
-			accepts commands via a FIFO (named pipe) and
-			returns data asked for. Administrators do not
-			need to learn details of the FIFO communication
-			and can serve themselves using a front-end
-			utility <application moreinfo="none">serctl</application>.
-			Of particular interest for 
-			monitoring server's operation are 
-			<application moreinfo="none">serctl</application>
-			commands
-			<command moreinfo="none">ps</command> and
-			<command moreinfo="none">moni</command>.
-			The former displays running 
-			<application moreinfo="none">ser</application>
-			processes, whereas the latter shows statistics.
-		    </para>
-		    <example>
-			<title>serctl ps command</title>
-			<para>
-			    This example shows 10 processes running at a host.
-			    The process 0, "attendant" watches child processes
-			    and terminates all of them if a failure occurs in
-			    any of them. Processes 1-4 listen at local
-			    interface and processes 5-8 listen at Ethernet
-			    interface at port number 5060. Process number
-			    9 runs FIFO server, and process number 10
-			    processes all server timeouts.
-			</para>
-			<programlisting format="linespecific">
-[jiri@fox jiri]$ serctl ps
-0	31590	attendant
-1	31592	receiver child=0 sock=0 @ 127.0.0.1::5060
-2	31595	receiver child=1 sock=0 @ 127.0.0.1::5060
-3	31596	receiver child=2 sock=0 @ 127.0.0.1::5060
-4	31597	receiver child=3 sock=0 @ 127.0.0.1::5060
-5	31604	receiver child=0 sock=1 @ 195.37.77.101::5060
-6	31605	receiver child=1 sock=1 @ 195.37.77.101::5060
-7	31606	receiver child=2 sock=1 @ 195.37.77.101::5060
-8	31610	receiver child=3 sock=1 @ 195.37.77.101::5060
-9	31611	fifo server
-10	31627	timer
-			  
-			</programlisting>
-		    </example>
-		</answer>
-	    </qandaentry>
-	    <qandaentry>
-		<question>
-		    <para>
-			Is Server Alive
-		    </para>
-		</question>
-		<answer>
-		    <para>
-			It is essential for solid operation to know
-			continuously that server is alive. We've been
-			using two tools for this purpose. 
-			<application moreinfo="none">sipsak</application>
-			does a great job of "pinging" a server, which
-			may be used for alerting on unresponsive servers.
-		    </para>
-		    <para>
-			<application moreinfo="none">monit</application> is
-			a server watching utility which alerts when
-			a server dies.
-		    </para>
-		</answer>
-	    </qandaentry>
-	    <qandaentry>
-		<question>
-		    <para>
-			Dealing with DNS
-		    </para>
-		</question>
-		<answer>
-		    <para>
-			SIP standard leverages DNS. Administrators of
-			<application moreinfo="none">ser</application> should
-			be aware of impact of DNS on server's operation.
-			Server's attempt to resolve an unresolvable address
-			may block a server process in terms of seconds. To be
-			safer that the server doesn't stop responding
-			due to being blocked by DNS resolving, we recommend
-			the following practices:
-			<itemizedlist>
-			    <listitem>
-				<para>
-				    Start a sufficient number of children processes.
-				    If one is blocked, the other children will
-				    keep serving.
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    Use DNS caching. For example, in Linux,
-				    there is an <application moreinfo="none">
-				    nscd</application> daemon available for
-				    this purpose.
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    Process transactions statefully if memory
-				    allows. That helps to absorb retransmissions
-				    without having to resolve DNS for each of
-				    them.
-				</para>
-			    </listitem>
-			</itemizedlist>
-		    </para>
-		</answer>
-	    </qandaentry>
-		<qandaentry>
-			<question>
-				<para>
-					Logging
-				</para>
-			</question>
-			<answer>
-			<anchor id="logging">
-			<para>
-			    <application>ser</application> by default logs
-			    to <application>syslog</application> facility.
-			    It is very useful to watch log messages for
-			    abnormal behaviour. Log messages, subject to
-			    <application>syslog</application> configuration
-			    may be stored at different files, or even at remote
-			    systems. A typical location of the log file is
-			    <filename>/var/log/messages</filename>.
-			</para>
-			<note>
-			    <para>
-				One can also use other <application>syslogd</application>
-				implementation. <application>metalog</application>
-				(<ulink url="http://http://metalog.sourceforge.net//">
-				    http://metalog.sourceforge.net/
-				</ulink>)
-				features regular expression matching that enables
-				to filter and group log messages.
-			    </para>
-			</note>
-			<para>
-			    For the purpose of debugging configuration scripts, one may
-			    want to redirect log messages to console not to pollute
-			    syslog files. To do so configure <application moreinfo="none">ser</application>
-			    in the following way:
-			    <itemizedlist>
-				<listitem>
-				    <para>
-					Attach ser to console by setting <varname>fork=no</varname>.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Set explicitely at which address 
-					<application moreinfo="none">ser</application>
-					should be listening, e.g., <varname>listen=192.168.2.16</varname>.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Redirect log messages to standard error by setting
-					<varname>log_stderror=yes</varname>
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Set appropriately high log level. (Be sure that you redirected logging
-					to standard output. Flooding system logs with many detailed messages
-					would make the logs difficult to read and use.) You can set the global
-					logging threshold value with the option <varname>debug=nr</varname>,
-					where the higher <varname>nr</varname> the more detailed output.
-					If you wish to set log level only for some script events, include
-					the desired log level as the first parameter of the
-					<command moreinfo="none">log</command> action in your script.
-					The messages will be then printed if <command moreinfo="none">log</command>'s
-					level is lower than the global threshold, i.e., the lower the more
-					noisy output you get.
-					<example>
-					    <title>Logging Script</title>
-					    <programlisting format="linespecific">
-&logging;
-					    </programlisting>
-					    <para>
-						The following SIP message causes then logging output as shown
-						bellow.
-					    </para>
-					    <programlisting format="linespecific">
-REGISTER sip:192.168.2.16 SIP/2.0
-Via: SIP/2.0/UDP 192.168.2.33:5060
-From: sip:[email protected]
-To: sip:[email protected]
-Call-ID: [email protected]
-Date: Thu, 27 Feb 2003 15:10:52 GMT
-CSeq: 101 REGISTER
-User-Agent: CSCO/4
-Contact: sip:[email protected]:5060
-Content-Length: 0
-Expires: 600                                 
-					    </programlisting>
-					    <programlisting format="linespecific">
-[jiri@cat sip_router]$ ./ser -f examples/logging.cfg 
-Listening on 
-              192.168.2.16 [192.168.2.16]::5060
-Aliases: cat.iptel.org:5060 cat:5060 
-WARNING: no fork mode 
- 0(0) INFO: udp_init: SO_RCVBUF is initially 65535
- 0(0) INFO: udp_init: SO_RCVBUF is finally 131070
- 0(17379) REGISTER received
- 0(17379) request for other domain received					
-					    </programlisting>
-					</example>
-				    </para>
-				</listitem>
-			    </itemizedlist>
-			</para>
-			</answer>
-		</qandaentry>
-	    <qandaentry>
-		<question>
-		    <para>
-			Labeling Outbound Requests
-		    </para>
-		</question>
-		<answer>
-		    <para>
-		    Without knowing, which pieces of script code a relayed
-		    request visited, trouble-shooting would be difficult.
-		    Scripts typically apply different processing to
-		    different routes such as to IP phones and PSTN
-		    gateways. We thus recommend to label outgoing
-		    requests with a label describing the type of processing
-		    applied to the request.
-			</para>
-		    <para>
-			Attaching "routing-history" hints to relayed
-			requests is as easy as using the 
-			<command moreinfo="none">append_hf</command>
-			action exported by textops module. The following
-			example shows how different labels are attached
-			to requests to which different routing logic
-			was applied.
-			<example>
-			    <title>"Routing-history" labels</title>
-			    <programlisting format="linespecific">
-# is the request for our domain?
-# if so, process it using UsrLoc and label it so.
-if (uri=~[@:\.]domain.foo") {
-   if (!lookup("location")) {
-    sl_send_reply("404", "Not Found");
-    break;
-   };
-   # user found -- forward to him and label the request
-   append_hf("P-hint: USRLOC\r\n");
-} else {
-# it is an outbound request to some other domain --
-# indicate it in the routing-history label
-   append_hf("P-hint: OUTBOUND\r\n");
-};
-t_relay();
-			    </programlisting>
-			    <para>
-				This is how such a labeled requests looks
-				like. The last header field includes
-				a label indicating the script processed
-				the request as outbound.
-			    </para>
-			    <programlisting format="linespecific">
-#
-U 2002/09/26 02:03:09.807288 195.37.77.101:5060 -> 203.122.14.122:5060
-SUBSCRIBE sip:[email protected] SIP/2.0.
-Max-Forwards: 10.
-Via: SIP/2.0/UDP 195.37.77.101;branch=53.b44e9693.0.
-Via: SIP/2.0/UDP 203.122.14.115:16819.
-From: sip:[email protected];tag=5c7cecb3-cfa2-491d-a0eb-72195d4054c4.
-To: sip:[email protected].
-Call-ID: [email protected].
-CSeq: 2 SUBSCRIBE.
-Contact: sip:203.122.14.115:16819.
-User-Agent: Windows RTC/1.0.
-Proxy-Authorization: Digest username="rajeshacl", realm="iptel.org", algorithm="MD5", uri="sip:[email protected]", nonce="3d924fe900000000fd6227db9e565b73c465225d94b2a938", response="a855233f61d409a791f077cbe184d3e3".
-Expires: 1800.
-Content-Length: 0.
-P-hint: OUTBOUND.			    </programlisting>
-			</example>
-		</para>
-		</answer>
-	    </qandaentry>
-	</qandaset>
-	</section> <!-- operational practises -->
-
-	<section>
-	    <title>HOWTOs</title>
-	    <para>
-		This section is a "cookbook" for dealing with common tasks,
-		such as user management or controlling access
-		to PSTN gateways.
-	    </para>
-	    <section>
-		<title>User Management</title>
-
-			<para>
-			    There are two tasks related to management of SIP users:
-			    maintaining user accounts and maintaining user contacts.
-			    Both these jobs can be done using the 
-			    <application moreinfo="none">serctl</application>
-			    command-line tool. Also, the complimentary web
-			    interface, <application moreinfo="none">serweb</application>,
-			    can be used for this purpose as well.
-			</para>
-			<para>
-			    If user authentication is turned on, which is a highly
-			    advisable practice, user account must be created before
-			    a user can log in. To create a new user account, call the
-			    <command moreinfo="none">serctl add</command> utility
-			    with username, password and email as parameters. It
-			    is important that the environment <varname>SIP_DOMAIN</varname>
-			    is set to your realm and matches realm values used in
-			    your script. The realm value is used for calculation
-			    of credentials stored in subscriber database, which are
-			    bound permanently to this value.
-			    <screen format="linespecific">
-[jiri@cat gen_ha1]$ export SIP_DOMAIN=foo.bar
-[jiri@cat gen_ha1]$ serctl add newuser secret [email protected]
-MySql Password: 
-new user added
-			    </screen>
-			</para>
-			<para><application moreinfo="none">serctl</application> can
-			    also change user's password or remove existing accounts
-			    from system permanently.
-			    <screen format="linespecific">
-[jiri@cat gen_ha1]$ serctl passwd newuser newpassword
-MySql Password: 
-password change succeeded
-[jiri@cat gen_ha1]$ serctl rm newuser                
-MySql Password: 
-user removed
-			    </screen>
-			</para>
-			<para>
-			    User contacts are typically automatically uploaded by SIP phones
-			    to server during registration process and administrators do not
-			    need to worry about them. However, users
-			    may wish to append permanent contacts to PSTN gateways
-			    or to locations in other administrative domains. 
-			    To manipulate the contacts in such cases, use
-			    <application moreinfo="none">serctl ul</application>
-			    tool. Note that this is the only correct way
-			    to update contacts -- direct changes to back-end
-			    MySql database do not affect server's memory. Also note,
-			    that if persistence is turned off (usrloc "db_mode"
-			    parameter set to "0"), all contacts are gone on server
-			    reboot. Make sure that persistence is enabled if you
-			    add permanent contacts.
-			</para>
-			<para>
-			    To add a new permanent contact for a user, call 
-			    <application moreinfo="none">serctl ul add &lt;username&gt
-			    &lt;contact&gt;</application>. To delete 
-			    all user's contacts, call 
-			    <application>serctl ul rm &lt;username&gt;</application>.
-			    <application moreinfo="none">serctl ul show &lt;username&gt;</application>
-			    prints all current user's contacts.
-			    <screen format="linespecific">
-[jiri@cat gen_ha1]$ serctl ul add newuser sip:[email protected]
-sip:[email protected]
-200 Added to table
-('newuser','sip:[email protected]') to 'location'
-[jiri@cat gen_ha1]$ serctl ul show newuser
-&lt;sip:[email protected]&gt;;q=1.00;expires=1073741812
-[jiri@cat gen_ha1]$ serctl ul rm newuser  
-200 user (location, newuser) deleted
-[jiri@cat gen_ha1]$ serctl ul show newuser
-404 Username newuser in table location not found
-			    </screen>
-			</para>
-	    </section> <!-- user management -->
-	    <section>
-		<title>User Aliases</title>
-
-			<para>
-			    Frequently, it is desirable for a user to have multiple
-			    addresses in a domain. For example, a user with username "john.doe" wants to be
-			    reachable at a shorter address "john" or at a nummerical address
-			    "12335", so that PSTN callers with digits-only key-pad can reach
-			    him too.
-			</para>
-			<para>
-			    With <application moreinfo="none">ser</application>, you can maintain
-			    a special user-location table and translate existing aliases to canonical
-			    usernames using the <command moreinfo="none">lookup</command>
-			    action from usrloc module. The following script fragment demonstrates
-			    use of <command moreinfo="none">lookup</command> for this purpose.
-			    <example>
-				<title>Configuration of Use of Aliases</title>
-				<programlisting format="linespecific">
-if (!uri==myself) { # request not for our domain...
-  route(1); # go somewhere else, where outbound requests are processed
-  break;
-};
-# the request is for our domain -- process registrations first
-if (method=="REGISTER") { route(3); break; };
-
-# look now, if there is an alias in the "aliases" table; don't care
-# about return value: whether there is some or not, move ahead then
-lookup("aliases");
-
-# there may be aliases which translate to other domain and for which
-# local processing is not appropriate; check again, if after the
-# alias translation, the request is still for us
-if (!uri==myself) { route(1); break; };
-
-# continue with processing for our domain...
-...
-  
-				</programlisting>
-			    </example>
-			</para>
-			<para>
-			    The table with aliases is updated using the
-			    <application moreinfo="none">serctl</application>
-			    tool. <application moreinfo="none">
-			    serctl alias add &lt;alias&gt; &lt;uri&gt;</application>
-			    adds a new alias, 
-			    <application moreinfo="none">serctl alias show &lt;user&gt;</application>
-			    prints an existing alias, and
-			    <application moreinfo="none">serctl alias rm &lt;user&gt;</application>
-			    removes it.
-			    <screen format="linespecific">
-[jiri@cat sip_router]$ serctl alias add 1234 sip:[email protected]
-sip:[email protected]
-200 Added to table
-('1234','sip:[email protected]') to 'aliases'
-[jiri@cat sip_router]$ serctl alias add john sip:[email protected]
-sip:[email protected]
-200 Added to table
-('john','sip:[email protected]') to 'aliases'
-[jiri@cat sip_router]$ serctl alias show john                    
-&lt;sip:[email protected]&gt;;q=1.00;expires=1073741811
-[jiri@cat sip_router]$ serctl alias rm john  
-200 user (aliases, john) deleted				
-			    </screen>
-			</para>
-			<para>
-			    Note that persitence needs to be turned on in usrloc
-			    module. All changes to aliases will be otherwise lost
-			    on server reboot. To enable persistence, set the
-			    db_mode usrloc parameter to a non-zero value.
-			    <programlisting format="linespecific">
-# ....load module ...
-loadmodule "modules/usrloc/usrloc.so"
-# ... turn on persistence -- all changes to user tables are immediately
-# flushed to mysql
-modparam("usrloc", "db_mode",   1)
-# the SQL address:
-modparam("usrloc", "db_url","sql://ser:secret@dbhost/ser")
-			    </programlisting>
-			</para>
-	    </section> <!-- user aliases -->
-	    <section id=acl>
-		<title>Access Control (PSTN Gateway)</title>
-			<para>
-			    It is sometimes important to exercise some sort of
-			    access control. A typical use case is when 
-			    <application moreinfo="none">ser</application> is used
-			    to guard a PSTN gateway. If a gateway was not well guarded,
-			    unauthorized users would be able to use it to terminate calls in PSTN,
-			    and cause high charges to its operator.
-			</para>
-			<para>
-			    There are few issues you need to understand when
-			    configuring <application moreinfo="none">ser</application>
-			    for this purpose. First, if a gateway is built or configured to
-			    accept calls from anywhere, callers may easily bypass your
-			    access control server and communicate with the gateway
-			    directly. You then need to enforce at transport layer
-			    that signaling is only accepted if coming via
-			    <application moreinfo="none">ser</application> and
-			    deny SIP packets coming from other hosts and port numbers.
-			    Your network must be configured not to allow forged
-			    IP addresses. Also, you need to turn on record-routing
-			    to assure that all session requests will travel via 
-			    <application moreinfo="none">ser</application>.			    
-			    Otherwise, caller's devices would send subsequent SIP requests 
-			    directly to your gateway, which would fail because of transport 
-			    filtering.
-			</para>
-			<para>
-			    Authorization (i.e., the process of determining who may call where)
-			    is facilitated in <application moreinfo="none">ser</application>
-			    using <emphasis>group membership</emphasis> concept. Scripts make 
-			    decisions on whether a caller is authorized to make a call to
-			    a specific destination based on user's membership in a group.
-			    For example a policy may be set up to allow calls to international
-			    destinations only to users, who are members of an "int" group.			    
-			    Before user's group membership is checked, his identity
-			    must be verified first. Without cryptographic verification of user's
-			    identity, it would be impossible to assert that a caller really
-			    is who he claims to be.
-			</para>
-			<para>
-			    The following script demonstrates, how to configure <application moreinfo="none">ser</application>
-			    as an access control server for a PSTN gateway. The script verifies user
-			    identity using digest authentication, checks user's privileges,
-			    and forces all requests to visit the server.
-			    <example>
-				<title>Script for Gateway Access Control</title>
-				<programlisting format="linespecific">
-&gatewayacl;
-				</programlisting>
-			    </example>
-			</para>
-			<para>
-			    Use the <application moreinfo="none">serctl</application> tool to
-			    maintain group membership. 
-			    <application moreinfo="none">serctl acl grant &lt;username&gt; &lt;group&gt;</application>
-			    makes a user member of a group, 
-			    <application>serctl acl show &lt;username&gt;</application> shows groups
-			    of which a user is member, and
-			    <application>serctl acl revoke &lt;username&gt; [&lt;group&gt;]</application>
-			    revokes user's membership in one or all groups.
-			    <screen format="linespecific">
-[jiri@cat sip_router]$ serctl acl grant john int
-MySql Password: 
-+------+-----+---------------------+
-| user | grp | last_modified       |
-+------+-----+---------------------+
-| john | int | 2002-12-08 02:09:20 |
-+------+-----+---------------------+
-			    </screen>
-			</para>
-	    </section> <!-- access control -->
-	    <section>
-		<title>Accounting</title>
-			<para>
-			    In some scenarios, like termination of calls in PSTN, SIP administrators
-			    may wish to keep track of placed calls. <application moreinfo="none">ser</application>
-			    can be configured to report on completed transactions. Reports are sent
-			    by default to <application moreinfo="none">syslog</application> facility.
-			    Experimental support for RADIUS and mysql accounting exists as well.
-			</para>
-			<para>
-			    Note that <application moreinfo="none">ser</application> is no way 
-			    call-stateful. It reports on completed transactions, i.e., after 
-			    a successful call set up is reported, it drops any call-related 
-			    state. When a call is terminated, transactional state for BYE request
-			    is created and forgotten again after the transaction completes.
-			    This is a feature and not a bug -- keeping only transactional
-			    state allows for significantly higher scalability. It is then
-			    up to the accounting application to correlate call initiation
-			    and termination events.
-			</para>
-			<para>
-			    To enable call accounting, tm and acc modules need to be loaded,
-			    requests need to be processed statefuly and labeled for
-			    accounting. That means, if you want a transaction to be reported,
-				the initial request must have taken the path 
-				"<command>setflag(X)</command>, <command>t_relay</command>"
-				in <application>ser</application> script. X must have the
-				value configured in <varname>acc_flag</varname>
-				configuration option.
-			</para>
-			<para>
-				Also note, that by default only transactions that initiate
-				a SIP dialog (typically INVITE) visit a proxy server.
-				Subsequent transactions are exhanged directly between
-				end-devices, do not visit proxy server and cannot be
-				reported. To be able to report on subsequent transactions,
-				you need to force them visit proxy server by turning 
-				record-routing on. 
-			</para>
-			<para>
-				
-			    <example>
-				<title>Configuration with Enabled Accounting</title>
-				<programlisting format="linespecific">
-&accountingexample;
-				</programlisting>
-			    </example>
-			</para>
-	    </section> <!-- accounting -->
-	    <section>
-		<title>Reliability</title>
-
-			<para>
-			    It is essential to guarantee continuous
-			    service operation even under erroneous conditions, 
-			    such as host or network failure. The major issue in such
-			    situations is transfer of operation to a backup
-			    infrastructure and making clients use it.
-			</para>
-			<para>
-			    The SIP standard's use of DNS SRV records has been
-			    explicitly constructed to handle with server failures.
-			    There may be multiple servers responsible for a domain
-			    and referred to by DNS. If it is impossible to communicate
-			    with a primary server, a client can proceed to another one.
-			    Backup servers may be located in a different geographic
-			    area to minimize risk caused by areal operational
-			    disasters: lack of power, flooding, earthquake, etc.
-			    <note>
-				<sidebar>
-				    <para>Unless there are redundant DNS
-				    servers, fail-over capability cannot be guaranteed.
-				    </para>
-				</sidebar>
-			    </note>
-			    Unfortunately, at the moment of writing this documentation
-			    (end of December 2002) only very few SIP products
-			    actually implement the DNS fail-over mechanism. Unless
-			    networks with SIP devices supporting this mechanism are
-			    built, alternative mechanisms must be used to force 
-			    clients to use backup servers. Such a mechanism is
-			    disconnecting primary server and replacing him with
-			    a backup server locally.
-			    It unfortunately precludes geographic dispersion and
-			    requires network multihoming to avoid dependency on
-			    single IP access. Another method is to update DNS
-			    when failure of the primary server is detected.
-			    The primary drawback of this method is its latency:
-			    it may take long time until all clients learn to use
-			    the new server.
-			</para>
-			<para>
-			    The easier part of the redundancy story is replication of 
-			    <application moreinfo="none">ser</application>
-			    data. <application moreinfo="none">ser</application>
-			    relies on replication capabilities of its back-end database.
-			    This works with one exception: user location database.
-			    User location database is a frequently accessed table,
-			    which is thus cached in server's memory to improve
-			    performance. Back-end replication does not affect
-			    in-memory tables, unless server reboots. To facilitate
-			    replication of user location database, 
-			    server's SIP replication feature must be enabled
-			    in parallel with back-end replication.
-			</para>
-			<para>
-			    The design idea of replication of user location database
-			    is easy: Replicate any successful REGISTER requests to
-			    a peer server. To assure that digest credentials can
-			    be properly verified, both servers need to use the same
-			    digest generation secret and maintain synchronized time.
-			    A known limitation of this method is it does not replicate
-			    user contacts entered in another way, for example using
-			    web interface through FIFO server.
-			    The following script example shows configuration of
-			    a server that replicates all REGISTERs.
-			    <example>
-				<title>Script for Replication of User Contacts</title>
-				<programlisting format="linespecific">
-&replicateexample;				    
-				</programlisting>
-			    </example>
-			</para>
-	    </section> <!-- reliability -->
-	    <section>
-		<title>Stateful versus Stateless Forwarding</title>
-		<para>
-		    <application moreinfo="none">ser</application> allows both stateless
-		    and stateful request processing. This memo explains what are pros and cons of
-		    using each method. The rule of thumb is "stateless for scalability,
-		    stateful for services". If you are unsure which you need, stateful
-		    is a safer choice which supports more usage scenarios.
-		</para>
-			<para>
-			    Stateless forwarding with the
-			    <command moreinfo="none">forward(uri:host, uri:port)</command> action
-			    guarantees high scalability. It withstands high load and
-			    does not run out of memory. A perfect use of stateless forwarding
-			    is load distribution.
-			</para>
-			<para>
-			    Stateful forwarding using the <command moreinfo="none">t_relay()</command>
-			    action is known to scale worse. It can quickly run out of memory and
-			    consumes more CPU time. Nevertheless, there are scenarios which are
-			    not implementable without stateful processing. In particular:
-			    <itemizedlist>
-				<listitem>
-				    <para>
-					<emphasis>Accounting</emphasis> requires stateful processing
-					to be able to collect transaction status and issue a single
-					report when a transaction completes.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					<emphasis>Forking</emphasis> only works with stateful forwarding.
-					Stateless forwarding only forwards to the default URI out of the
-					whole destination set.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					<emphasis>DNS resolution</emphasis>. DNS resolution may be
-					better server with stateful processing. If a request is forwarded
-					to a destination whose address takes long time to resolve,
-					a server process is blocked and unresponsive. Subsequent 
-					request retransmissions from client will cause other processes
-					to block too if requests are processed statelessly. As a result,
-					<application moreinfo="none">ser</application> will quickly
-					run out of available processes. With stateful forwarding,
-					retransmissions are absorbed and do not cause blocking of
-					another process.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					<emphasis>Forwarding Services</emphasis>. All sort of services 
-					with the "forward_on_event" logic, which rely on 
-					<command moreinfo="none">t_on_negative</command> tm
-					action must be processed statefuly.
-				    </para>
-				</listitem>
-			<listitem>
-			    <para>
-				<emphasis>
-				    Fail-over.
-				</emphasis>
-				If you wish to try out another destination, after a primary destination
-				failed you need to use stateful processing. With stateless processing
-				you never know with what status a forwarded request completed downstream
-				because you immediately release all processing information after the 
-				request is sent out. 
-
-				<note>
-				    <para>
-					Positive return value of stateless
-					<command moreinfo="none">forward</command> action only indicates that
-					a request was successfuly sent out, and does not gain any knowledge
-					about whether it was successfuly received or replied. Neither does
-					the return value of
-					the stateful <command moreinfo="none">t_relay</command> action family
-					gain you this knowledge. However, these actions store transactional
-					context with which includes original request and allows you to
-					take an action when a negative reply comes back or a timer strikes.
-					See <xref linkend="replyprocessingsection"> for an example script 
-					which launches another
-					branch if the first try fails.
-				    </para>
-				</note>
-
-			    </para>
-			</listitem>
-			    </itemizedlist>
-			</para>
-	    </section> <!-- stateful vs. stateless -->
-	    <section>
-		<title>Serving Multiple Domains</title>
-			<para>
-			    <application moreinfo="none">ser</application> can be configured to
-			    serve multiple domains. To do so, you need to take the following steps:
-			    <orderedlist>
-				<listitem id="createtable">
-				    <para>
-					Create separate subscriber and location database table
-					for each domain served and name them uniquely.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Configure your script to distinguish between multiple
-					served domains. Use regular expressions for domain
-					matching as described in <xref linkend="redomainmatching">.
-				    </para>
-				</listitem>
-				<listitem>
-				    <para>
-					Update table names in usrloc and auth actions to reflect
-					names you created in <xref linkend="createtable">.
-				    </para>
-				</listitem>
-				
-			    </orderedlist>
-			</para>
-	    </section> <!-- multiple domains -->
-	    <section id="missedcalls">
-		<title>Reporting Missed Calls</title>
-			<para>
-			    <application moreinfo="none">ser</application> can report missed
-			    calls via <application moreinfo="none">syslog</application> facility
-			    or to mysql. Mysql reporting can be utilized by 
-			    <application moreinfo="none">ser</application>'s 
-			    complementary web-interface, <application moreinfo="none">serweb</application>.
-			    (See more in <xref linkend="serweb">).
-			</para>
-			<para>
-			    Reporting on missed calls is enabled by acc module.
-			    There are two cases, on which you want to report. The first
-			    case is when a callee is off-line. The other case is when
-			    a user is on-line, but call establishment fails. There
-			    may be many failure reasons (call cancellation, inactive phone,
-			    busy phone, server timer, etc.), all of them leading to
-			    a negative (>=300) reply sent to caller. The acc module
-			    can be configured to issue a missed-call report whenever
-			    a transaction completes with a negative status. Two following
-			    script fragment deals with both cases.
-			</para>
-			<para>
-			    First, it reports
-			    on calls missed due to off-line callee status
-			    using the <command moreinfo="none">acc_request</command>
-			    action. The action is wrapped in transactional
-			    processing (<command moreinfo="none">t_newtran</command>)
-			    to guarantee that reports are not
-			    duplicated on receipt of retransmissions.
-			    </para>
-			<para>
-			    Secondly, transaction to on-line users are marked
-			    to be reported on failure. That is what the 
-			    <command moreinfo="none">setflag(3)</command> action
-			    is responsible for, along with the configuration option
-			    "missed_flag". This option configures <application moreinfo="none">ser</application>
-			    to report on all transactions, which were marked
-			    with flag 3.			   
-			    <programlisting format="linespecific">
-loadmodule("modules/tm/tm.so");
-loadmodule("modules/acc/acc.so");
-....
-# if a call is labeled using setflag(3) and is missed, it will
-# be reported
-...
-modparam("acc", "missed_flag", 3 );
-if (!lookup("location")) {
-     # call invitations to off-line users are reported using the
-     # acc_request action; to avoid duplicate reports on request
-     # retransmissions, request is processed statefuly (t_newtran,
-     # t_reply)
-     if ((method=="INVITE" || method=="ACK") && t_newtran() ) {
-          t_reply("404", "Not Found");
-	  acc_request("404 Not Found");
-          break;
-     };
-     # all other requests to off-line users are simply replied
-     # statelessly and no reports are issued
-    sl_send_reply("404", "Not Found");
-    break;
-} else {
-     # user on-line; report on failed transactions; mark the
-     # transaction for reporting using the same number as 
-     # configured above; if the call is really missed, a report
-     # will be issued
-     setflag(3);
-     # forward to user's current destination
-     t_relay();
-     break;
-};
-			    </programlisting>
-			    
-			</para>
-	    </section> <!-- missed calls -->
-	    <section>
-		<title>NAT Traversal</title>
-		<para>
-		    NATs are worst things that ever happened to SIP. These devices
-		    are very popular because they help to conserve IP address space
-		    and save money charged for IP addresses. Unfortunately, they
-		    translate addresses in a way which is not compatible with SIP.
-		    SIP advertises receiver addresses in its payload. The advertised
-		    addresses are invalid out of NATted networks. As a result,
-		    SIP communication does not work accross NATs without extra
-		    effort.
-		</para>
-		<para>
-		    There are few methods that may be deployed to traverse NATs.
-		    How proper their use is depends on the deployment scenario.
-		    Unfortunatelly, all the methods have some limitations and
-		    there is no straight-forward solution addressing all
-		    scenarios. Note that none of these methods takes explicit
-		    support in <application moreinfo="none">ser</application>.
-		</para>
-		<para>
-		    The first issue is whether SIP users are in control of 
-		    their NATs. If not (NATs are either operated by ISP or
-		    they are sealed to prevent users setting them up), the
-		    only method is use of a STUN-enabled phone. STUN is 
-		    a very simple protocol used to fool NAT in such a way,
-		    they permit SIP sessions. Currently, we are aware of
-		    one softphone (kphone) and one hardphone (snom) with
-		    STUN support, other vendors are working on STUN support
-		    too. Unfortunately, STUN gives no NAT traversal
-		    guarantee -- there are types of NATs, so called
-		    symmetric NATs, over which STUN fails to work.
-		    <note>
-			<para>
-			    There is actually yet another method to address
-			    SIP-unaware, user-uncontrolled NATs. It is based
-			    on a proxy server, which relays all signaling and
-			    media and mangles packets to make them more
-			    NAT-friendly. The very serious problem with this
-			    method is it does not scale.
-			</para>
-		    </note>
-		</para>
-		<para>
-		    If users are in control of their own NAT, as typically residential
-		    users are, they can still use STUN. However, they may use other
-		    alternatives too. One of them is to replace their NAT with
-		    a SIP-aware NAT. Such NATs have built-in SIP awareness,
-		    that patches problems caused by address translations. Prices
-		    of such devices are getting low and there are available
-		    implementations (Intertex, Cisco/PIX). No special support
-		    in phones is needed.
-		</para>
-		<para>
-		    Other emerging option is UPnP. UPnP is a protocol that allows
-		    phones to negotiate with NAT boxes. You need UPnP support in
-		    both, NAT and phones. As UPnP NATs are quite affordable,
-		    costs are not an obstacle. Currently, we are aware of one
-		    SIP phone (SNOM) with UPnP support.
-		</para>
-		<para>
-		    Geeks not wishing to upgrade their firewall to a SIP-aware or
-		    UPnP-enabled one may try to configure static address translation.
-		    That takes phones with configuration ability to use fixed port
-		    numbers and advertise outside address in signaling. Cisco phones
-		    have this capability, for example. The NAT devices need to
-		    be configured to translate outside port ranges to the 
-		    ranges configured in phones.		    
-		</para>
-	    </section> <!-- NAT traversal -->
-	    <section>
-		<title>Authentication Policy: Prevention of Unauthorized Domain 
-		    Name Use in From and More</title>
-		<para>
-		    Malicous users can claim a name of domain, to which they do 
-		    not administratively belong, in From header field. This
-		    behaviour cannot be generally prevented. The reason is
-		    that requests with such a faked header field do not need
-		    to visit servers of the domain in question. However, if they
-		    do so, it is desirable to assure that users claiming
-		    membership in a domain are actually associated with it.
-		    Otherwise the faked requests would be relayed and appear
-		    as coming from the domain, which would increase
-		    credibility of the faked address and decrease credibility of
-		    the proxy server.
-		</para>
-		<para>
-		    Preventing unathorized domain name use in relayed requests 
-		    is not difficult.
-		    One needs to authenticate each request with name of the
-		    served domain in From header field. To do so, one can
-		    search for such a header field using <command moreinfo="none">search</command>
-		    action (textops module) and force authentication if the
-		    search succeeds.
-		    <note>
-			<para>
-			    A straight-forward solution might be to authenticate
-			    ALL requests. However, that only works in closed
-			    networks in which all users have an account in the
-			    server domain. In open networks, it is desirable to permit
-			    incoming calls from callers from other domains without
-			    any authentication. For example, a company may wish
-			    to accept calls from unknown callers who are
-			    new prospective customers.
-			    
-			</para>
-		    </note>
-		    <programlisting format="linespecific">
-# does the user claim our domain "foo.bar" in From?
-if (search("^(f|From):.*foo.bar")) {
-        # if so, verify credential
-	if (!proxy_authorize("foo.bar", "subscriber")) { 
-              # don't proceed if credentials broken; challenge
-	      proxy_challenge("foo.bar", "0");
-	      break;
-        };
-};
-		    </programlisting>
-		</para>
-		<para>
-		    In general, the authentication policy may be very rich. You may not
-		    forget each request deserves its own security and you need to 
-		    decide whether it shall be authenticated or not. As mentioned
-		    above, in closed networks, you may want to authenticate absolutely 
-		    every request. That however prohibits traffic from users from
-		    other domains. A pseudo-example of a reasonable policy is attached:
-		    it looks whether a request is registration, it claims to originate
-		    from our domain in From header field, or is a local request to
-		    another domain.
-		    <programlisting format="linespecific">
-# (example provided by Michael Graff on [serusers] mailing list
-if (to me):
-    if register
-          www_authorize or fail if not a valid register
-          done
-    if claiming to be "From" one of the domains I accept registrations for
-          proxy_authorize
-          done
-    if not to me (I'm relaying for a local phone to an external address)
-          proxy_authorize
-          done
-		    </programlisting>
-		</para>
-		<para>
-		    You also may want to apply additional restriction to how
-		    digest username relates to usernames claimed in From and
-		    To header fields. For example, the <command moreinfo="none">check_to</command>
-		    action enforces the digest id to be equal to username
-		    in To header fields. That is good in preventing someone
-		    with valid credentials to register as someone else
-		    (e.g., sending a REGISTER with valid credentials of
-		    "joe" and To belonging to "alice"). Similarly,
-		    <command moreinfo="none">check_from</command> is used
-		    to enforce username in  from to equal to digest id.
-		    <note>
-			<para>
-			    There may be a need for a more complex relationship
-			    between From/To username and digest id. For example,
-			    providers with an established user/password database
-			    may wish to keep using it, whereas permitting users
-			    to claim some telephone numbers in From. To address
-			    such needs generally, there needs to be a 1:N mapping
-			    between digest id and all usernames that are acceptable
-			    for it. This is being addressed in a newly contributed
-			    module "domain", which also addresses more generally
-			    issues of domain matching for multidomain scenarios.
-			</para>
-		    </note>
-		</para>
-		<para>
-		    Other operational aspect affecting the authentication policy
-		    is guarding PSTN gateways (see <xref linkend="acl">). There
-		    may be destinations that are given away for free whereas
-		    other destinations may require access control using
-		    group membership, to which  authentication is a prerequisity.
-		</para>
-
-	    </section> <!-- authentication policy, faked froms -->
-	    <section>
-		<title>Connecting to PBX Voicemail Using a Cisco Gateway</title>
-		<para>
-		    In some networks, administrators may wish to utilize their
-		    PBX voicemail systems behind PSTN gateways. There is a practical problem
-		    in many network settings: it is not clear for whom a call to
-		    voicemail is. If voicemail is identified by a single number,
-		    which is then put in INVITE's URI, there is no easy way to
-		    learn for whom a message should be recorded. PBX voicemail
-		    utilize that PSTN protocols signal the number of originally
-		    called party. If you wish to make the PBX voicemail work,
-		    you need to convey the number in SIP and translate it in
-		    PSTN gateways to its PSTN counterpart.
-		</para>
-		<para>
-		    There may be many different ways to achieve this scenario. Here
-		    we describe the proprietary mechanism Cisco gateways use and how to 
-		    configure <application moreinfo="none">ser</application> to
-		    make the gateways happy. Cisco gateways expect the number
-		    of originally called party to be located in proprietary
-		    <varname>CC-Diversion</varname> header field. When a SIP 
-		    INVITE sent via a PSTN gateway to PBX voicemail has number
-		    of originally called party in the header field, the voicemail
-		    system knows for whom the incoming message is. That is at least
-		    true for AS5300/2600 with Cisco IOS 12.2.(2)XB connected to
-		    Nortel pbxs via PRI. (On the other hand, 12.2.(7b) is known
-		    not to work in this scenario.)
-		</para>
-		<para>
-		    <application moreinfo="none">ser</application> needs then to
-		    be configured to append the <varname>CC-Diversion</varname>
-		    header field name for INVITEs sent to PBX voicemail.
-		    The following script shows that: when initial forwarding
-		    fails (nobody replies, busy is received, etc.), a new branch
-		    is initiated to the pbx's phone number. 
-		    <command moreinfo="none">append_urihf</command> is used to
-		    append the <varname>CC-Diversion</varname> header field. It
-		    takes two parameters: prefix, which includes header name,
-		    and suffix which takes header field separator. 
-		    <command moreinfo="none">append_urihf</command> inserts
-		    original URI between those two.
-		    <example>
-			<title>Forwarding to PBX/Voicemail via Cisco Gateways</title>
-			<programlisting format="linespecific">
-&ccdiversion;
-			</programlisting>
-		    </example>
-		    
-		</para>
-	    </section>
-	</section> <!-- howtos -->
-
-	<section>
-	    <title>Troubleshooting</title>
-	    <para>
-		This section gathers practices how to deal with errors
-		known to occur frequently. To understand how to watch
-		SIP messages, server logs, and in genereal how to
-		troubleshoot, read also <xref linkend="operationalpractices">. 
-	    </para>
-	    <qandaset>
-		<qandaentry>
-		    <question>
-			<para>
-			SIP requests are replied by <application>ser</application> with
-			"483 Too Many Hops" or "513 Message Too Large"
-		        </para>
-		    </question>
-
-		    <answer>
-			<para>
-			    In both cases, the reason is probably an error in
-			    request routing script which caused an infinite loop.
-			    You can easily verify whether this happens by
-			    watching SIP traffic on loopback interface. A typical
-			    reason for misrouting is a failure to match local
-			    domain correctly. If a server fails to recognize
-			    a request for itself, it will try to forward it
-			    to current URI in believe it would forward them
-			    to a foreign domain. Alas, it forwards the request
-			    to itself again. This continues to happen until
-			    value of max_forwards header field reaches zero
-			    or the request grows too big. Solutions is easy:
-			    make sure that domain matching is correctly
-			    configured. See <xref linkend="domainmatching">
-			    for more information how to get it right.
-			</para>
-		    </answer>		    
-		</qandaentry>
-		<qandaentry>
-			
-		    <question>
-			        
-			<para>
-			
-			    Windows Messenger authentication fails.
-			</para>
-		    </question>
-		    <answer>
-			<anchor id="msmbug">
-			<para>
-			    The most likely reason for this problem is a bug
-			    in Windows Messenger. WM only authenticates if
-			    server name in request URI equals authentication
-			    realm. After a challenge is sent by SIP server,
-			    WM does not resubmit the challenged request at all
-			    and pops up authentication window again.
-			    If you want to authenticate WM, you need to
-			    set up your realm value to equal server name.
-			    If your server has no name, IP address can be used
-			    as realm too. The realm value is configured in
-				scripts as the first parameter of all
-				<command>{www|proxy}_{authorize|challenge}</command>
-				actions.
-			</para>
-		    </answer>
-		</qandaentry>
-		<qandaentry>
-		    <question>
-			<para>
-			    On a multihomed host, forwarded messages carry other 
-			    interface in Via than used for sending, or messages 
-			    are not sent and an error log is issued "invalid 
-			    sendtoparameters one possible reason is the server 
-			    is bound to localhost".
-			</para>
-		    </question>
-		    <answer>
-			<anchor id="mhomed">
-			<para>
-			    Set the configuration option <varname>mhome</varname>
-			    to "1". <application moreinfo="none">ser</application>
-			    will then attempt to calculate the correct interface.
-			    It's not done by default as it degrades performance
-			    on single-homed hosts or multi-homed hosts that are
-			    not set-up as routers.
-			</para>
-		    </answer>
-		</qandaentry>
-		<qandaentry>
-		    <question>
-			<para>
-			    I receive "ERROR: t_newtran: transaction already in process" in my logs.
-			</para>
-		    </question>
-		    <answer>
-			<para>
-			    That looks like an erroneous use of tm module in script.
-			    tm can handle only one transaction per request. If you
-			    attempt to instantiate a transaction multiple times,
-			    <application moreinfo="none">ser</application> will complain.
-			    Anytime any of <command moreinfo="none">t_newtran</command>,
-			    <command moreinfo="none">t_relay</command> or 
-			    <command moreinfo="none">t_relay_to</command> actions is
-			    encountered, tm attempts to instantiate a transaction.
-			    Doing so twice fails. Make sure that any of this
-			    commands is called only once during script execution.
-			</para>
-		    </answer>
-		</qandaentry>
-		<qandaentry>
-		    <question>
-			<para>
-			    I try to add an alias but 
-			    <command moreinfo="none">serctl</command>
-			    complains that table does not exist.
-			</para>
-		    </question>
-		    <answer>
-			<para>
-			    You need to run <application moreinfo="none">ser</application>
-			    and use the command
-			    <command moreinfo="none">lookup("aliases")</command>
-			    in its routing script. That's because the table 
-			    of aliases is
-			    stored in cache memory for high speed. The cache
-			    memory is only set up when the 
-			    <application moreinfo="none">ser</application>
-			    is running and configured to use it. If that is
-			    not the case, 
-			    <application moreinfo="none">serctl</application>
-			    is not able to manipulate the aliases table.
-			</para>
-		    </answer>
-		</qandaentry>
-	    </qandaset>
-	</section> <!-- troubleshooting -->
-    </chapter> <!-- operation -->
-
-
-    <chapter>
-	<title>Application Writing</title>
-	<para>
-	    <application moreinfo="none">ser</application> offers several
-	    ways to couple its functionality with applications. The coupling
-	    is bidirectional: <application moreinfo="none">ser</application>
-	    can utilize external applications and external applications can
-	    utilize <application moreinfo="none">ser</application>. 
-	    An example of the former direction would be an external program
-	    determining a least-cost route for a called destination  using 
-	    a pricing table. An example of the latter case
-	    is a web application for server provisioning.
-	    Such an application may want to send instant 
-	    messages, query all current user's locations and monitor server
-	    health. An existing web interface to <application moreinfo="none">ser</application>,
-	    <application moreinfo="none">serweb</application>, actually
-	    does all of it. 
-	</para>
-	<para>
-	    The easiest, language-independent way of using external logic 
-	    from <application moreinfo="none">ser</application> is provided
-	    by exec module. exec module allows <application moreinfo="none">ser</application>
-	    to start external programs on receipt of a request. The
-	    programs can execute arbitrary logic and/or affect routing of SIP
-	    requests. A great benefit of this programming method is it
-	    is language-independent. Programmers may use programming languages
-	    that are effective or with which they are best familiar.
-	    <xref linkend="usingexec"> gives additional examples illustrating 
-	    use of the exec module.
-	</para>
-	<para>
-	    Another method for extending <application moreinfo="none">ser</application>
-	    capabilities is to write new modules in C. This method takes
-	    deeper understanding of <application moreinfo="none">ser</application>
-	    internals but gains the highest flexibility. Modules can implement
-	    arbitrary brand-new commands upon which <application moreinfo="none">ser</application>
-	    scripts can rely on. Guidelines on module programming can be
-	    found in <application moreinfo="none">ser</application>
-	    programmer's handbook available from iptel.org website.
-	</para>
-	<para>
-	    To address needs of applications wishing to leverage
-	    <application moreinfo="none">ser</application>,
-	    <application moreinfo="none">ser</application> exports
-	    parts of its functionality via its built-in
-	    "Application FIFO server". This is a simple textual
-	    interface that allows any external applications
-	    to communicate with the server. It can be used to
-	    send instant messages, manipulate user contacts,
-	    watch server health, etc. Programs written in any
-	    language (PHP, shell scripts, Perl, C, etc.) can
-	    utilize this feature. How to use it is shown in
-	    <xref linkend="fifoserver">.
-	</para>
-
-
-	<section id="usingexec">
-	    <title>Using exec Module</title>
-	    <para>
-		
-		The easiest way is to couple <application moreinfo="none">ser</application>
-		with external applications via the <emphasis>exec</emphasis>
-		module. This module allows execution of logic and URI manipulation 
-		by external applications on request receipt. While very
-		simple, many useful services can be
-		implemented this way. External applications can be written in
-		any programming language and do not be aware of SIP at all.
-		<application moreinfo="none">ser</application> interacts with
-		the application via standard input/output and environment 
-		variables.
-		
-
-	    </para>
-	
-
-	    <para>
-		For example, an external shell script
-		may send an email whenever a request for a user arrives.
-	    </para>
-
-	    <example>
-		<title>Using exec: Step 1</title>
-		<programlisting format="linespecific">
-# send email if a request for user "jiri" arrives
-if (uri=~"^sip:jiri@") {
-     exec_msg("echo 'body: call arrived'|mail -s 'call for you' jiri");
-}
-		</programlisting>
-	    </example> <!-- step 1 -->
-	    <para>
-		In this example, the <command moreinfo="none">exec_msg</command> 
-		action starts an external shell. It passes a received SIP request
-		to shell's input. In the shell, <command>mail</command> command
-		is called to send a notification by e-mail.
-		The script however features several simplifications:
-		<orderedlist inheritnum="ignore" continuation="restarts">
-		    <listitem>
-			<para>
-			    The email notification does not tell who was calling.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    The logic is not general: it only supports one well-known user (jiri).
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    The logic is stateless. It will be executed on
-			    every retransmission.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    It is a script fragment not explaining the 
-			    context. This particular example may be for
-			    example used to report on missed calls.
-			</para>
-		    </listitem>
-		</orderedlist>
-		All of these simplifications are addressed step-by-step
-		in the following examples.
-	    </para>
-	    <example> <!-- step 2: who called me -->
-		<title>Using exec: Step 2, Who Called Me</title>
-		<para>
-		    This example shows how to display caller's address
-		    in email notification. The trick is easy: process
-		    request received on shell programm's input
-		    and grep From header field.
-		</para>
-		<programlisting format="linespecific">
-&execstep2;
-		</programlisting>
-		<para>
-			The following two figures show an example SIP request and
-			email notification generated on its receipt.
-			
-		    <screen format="linespecific">
-
-<![CDATA[
-INVITE sip:[email protected] SIP/2.0
-Via: SIP/2.0/UDP 195.37.77.100:5040
-Max-Forwards: 10
-From: "alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
-To: <sip:[email protected]>
-Call-ID: [email protected]
-CSeq: 2 INVITE
-Contact: <sip:123.20.128.35:9315>
-Content-Type: application/sdp
-Content-Length: 451
-
---- SDP payload snipped ---
-]]>
-
-		    </screen>
-		
-		    email received:
-		
-			<screen format="linespecific">
-<![CDATA[
-Date: Thu, 12 Dec 2002 14:25:02 +0100
-From: root <[email protected]>
-To: [email protected]
-Subject: request for you
-
-From: "alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
-request received
-]]>
-		    </screen>
-		</para>
-		<para>
-		    There is another way to learn values of request
-		    header fields, simpler than use of <command moreinfo="none">grep</command>. 
-		    <application moreinfo="none">ser</application>
-		    parses header fields and passes their values in 
-		    environment variables. Their names correspond
-		    to header field names prefixed with "SIP_HF_".
-		<programlisting format="linespecific">
-# send email if a request for "jiri" arrives
-if (uri=~"^sip:jiri@") {
-     exec_msg("echo request received from $SIP_HF_FROM | mail -s 'request for you' jiri");
-};
-		</programlisting>
-		    Moreover, several other values are passed in environment
-		    variables. <varname>SIP_TID</varname> is a token uniquely identifying 
-		    transaction, to which the request belongs. <varname>SIP_DID</varname>
-		    includes to-tag, and is empty in requests creating a dialog.
-		    <varname>SIP_SRCIP</varname> includes IP address, from which the
-		    request was sent. <varname>SIP_RURI</varname> and <varname>SIP_ORURI</varname>
-		    include current request-uri and original request-uri respectively,
-		    <varname>SIP_USER</varname> and <varname>SIP_OUSER</varname> username
-		    parts of these. The following listing shows environment variables
-		    passed to a shell script on receipt of the previous message:
-		    <programlisting format="linespecific">
-<![CDATA[
-SIP_HF_MAX_FORWARDS=10
-SIP_HF_VIA=SIP/2.0/UDP 195.37.77.100:5040
-SIP_HF_CSEQ=2 INVITE
-SIP_HF_FROM="alice" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
-SIP_ORUI=sip:[email protected]
-SIP_HF_CONTENT_LENGTH=451
-SIP_TID=3b6b8295db0835815847b1f35f3b29b8
-SIP_DID=
-SIP_RURI=iptel.org
-SIP_HF_TO=<sip:[email protected]>
-SIP_OUSER=jiri
-SIP_HF_CALLID=d10815e0-bf17-4afa-8412-d9130a793d96@213.20.128.35
-SIP_SRCIP=195.37.77.100
-SIP_HF_CONTENT_TYPE=application/sdp
-SIP_HF_CONTACT=<sip:123.20.128.35:9315>
-]]>
-		    </programlisting>
-				    
-		</para>
-	    </example> <!-- step 2, who called me -->
-
-
-	    <example>  <!-- step 3,  make the script work for anyone -->
-		<title>Using exec: step 3, Make The Script Work For Anyone</title>
-		<para>
-		    A drawback of the previous example is it works only
-		    for one well-known user: request URI is matched against
-		    his SIP address and notification is sent to his hard-wired email
-		    address. In real scenarios, one would like
-		    to enable such a service for all users without enumerating
-		    their addresses in the script. The missing piece
-		    is translation of user's SIP name to his email address.
-		    This information is maintained in subscriber profiles,
-		    stored in MySQL by <application moreinfo="none">ser</application>.
-		    To translate the username to email address, the executed script
-		    needs to query the MySQL database. That is what this example
-		    shows. First, an SQL query is constructed which looks up
-		    email address of user, for whom a request arrived. If the
-		    query does not return a valid email address, the script
-		    returns with an error status and <application moreinfo="none">ser</application>
-		    script replies with "user does not exist". Otherwise
-		    an email notification is sent.
-		
-		    <programlisting format="linespecific">
-&execstep3;
-		    </programlisting>
-		</para>
-	    </example> <!-- step 3 make the script work for anyone -->
-	    <example> <!-- step 4, stateful processing -->
-		<title>Adding Stateful Processing</title>
-		<para>
-		    The previously improved example still features a shortcoming.
-		    When a message retransmission arrives due to a nework
-		    mistake such as lost reply, the email notification is
-		    executed again and again. That happens because the script
-		    is stateless, i.e., no track of current transactions is
-		    kept. The script does not know whether a request is
-		    a new or a retransmitted one. Transaction management may
-		    be introduced by use of tm module as described in
-		    <xref linkend="statefulua">. In the script,
-		    <command moreinfo="none">t_newtran</command> is first
-		    called to absorb requests retransmission -- if they
-		    occur, script does not continue. Then, as in the previous
-		    example, an exec module action is called. Eventually,
-		    a reply is sent statefully.
-		    <note>
-			<para>
-			    Note carefuly: it is important that the stateful
-			    reply processing (<command moreinfo="none">t_reply</command>)
-			    is used as opposed to using stateless replies
-			    (<command moreinfo="none">sl_send_reply</command>).
-			    Otherwise, the outgoing reply would not affect
-			    transactional context and would not be resent on
-			    receipt of a request retransmission.
-			</para>
-		    </note>
-		    <programlisting format="linespecific">
-&execstep4;
-		    </programlisting>
-		    
-		</para>
-	    </example> <!-- step 4,  stateful processing -->
-	    <example> <!-- step 5, full exec use -->
-		<title>Full Example of exec Use</title>
-		<para>
-		    The last example iteration shows how to integrate the
-		    email notification on missed calls with the default
-		    <application moreinfo="none">ser</application> script
-		    (see <xref linkend="defaultscript">). It generates an
-		    email for every call invitation to an off-line user.
-		    <programlisting format="linespecific">
-&execstep5;
-		    </programlisting>
-		</para>
-		    
-		<para>
-		    Production "missed calls" services may want to 
-		    report on calls missed for other reasons than
-		    being off-line too. Particularly, users may wish to be
-		    reported calls missed due to call cancellation,
-		    busy status or a downstream failure. Such missed
-		    calls can be easily reported to syslog or mysql
-		    using the acc module (see <xref linkend="missedcalls">).
-		    The other, more general way, is to return to request
-		    processing on receipt of a negative reply.
-		    (see <xref linkend="replyprocessingsection">). Before
-		    a request is forwarded, it is labeled to be
-		    re-processed in a <command moreinfo="none">reply_route</command>
-		    on receipt of a negative reply -- this is what
-		    <command moreinfo="none">t_on_negative</command> action
-		    is used for. It does not matter what caused the transaction
-		    to fail -- it may be unresponsive downstream server,
-		    server responding with 6xx, or server sending a 487
-		    reply, because an INVITE was cancelled. When any such
-		    circumstances occur (i.e., transaction does not complete
-		    with a 2xx status code), <command moreinfo="none">reply_route</command>
-		    is entered.
-		</para>
-		<para>
-		    The following <application moreinfo="none">ser</application>
-		    script reports missed calls in all possible cases.
-		    It reports them when a user is off-line as well as when
-		    a user is on-line, but INVITE transaction does not complete
-		    successfully.
-		    <programlisting format="linespecific">
-&execstep5b;
-		    </programlisting>
-		</para>
-		
-	    </example> <!-- step 5, full exec use -->
-
-	</section> <!-- using exec -->
-
-	<section id="fifoserver">
-	    <title>Application FIFO Server</title>
-
-	    <para>
-	    Application FIFO server is a very powerful method to program
-	    SIP services. The most valuable benefit
-	    is it works with SIP-unaware applications
-	    written in any programming language. Textual nature of the
-	    FIFO interface allows for easy integration with a lot of
-	    existing programs. Today, <application moreinfo="none">ser</application>'s
-	    complementary web-interface, <application moreinfo="none">serweb</application>,
-	    written in PHP, leverages the FIFO interface when displaying
-	    and changing user location records stored in server's memory.
-	    It uses this interface to send instant messages too, without
-	    any knowledge of underlying <acronym>SIP</acronym> stack.
-	    Another application relying on the FIFO interface is 
-	    <application moreinfo="none">serctl</application>, <application moreinfo="none">ser</application>
-	    management utility. The command-line utility can browse
-	    server's in-memory user-location database, display 
-	    running processes and operational statistics.
-	    </para>
-	    <para>
-		The way the FIFO server works is similar to how 
-		<filename moreinfo="none">/proc</filename> filesystem works
-		on some operating systems. It provides a human-readable way
-		to access <application moreinfo="none">ser</application>'s
-		internals. Applications dump their requests into the FIFO
-		server and receive a status report when request processing
-		completes. <application moreinfo="none">ser</application>
-		exports a lot of its functionality located in both the
-		core and external modules through the FIFO server. 
-		</para>
-	    <para>
-		FIFO requests are formed easily. They begin with a command
-		enclosed in colons and followed by name of file or pipe (relative
-		to <filename moreinfo="none">/tmp/</filename> path), to which
-		a reply should be printed. The first request line may be
-		followed by additional lines with command-specific 
-		parameters. For example, the <command moreinfo="none">t_uac_dlg</command>
-		FIFO command for initiating a transaction allows 
-		to pass additional header fields and message body to
-		a newly created transaction. Each request is terminated by
-		an empty line. Whole requests must be sent by applications
-		atomically in a single batch to avoid mixing with
-		requests from other applications. Requests are sent to
-		pipe at which <application moreinfo="none">ser</application>
-		listens (filename configured by the <varname>fifo</varname> config
-		file option).
-	    </para>
-	    <para>
-		An easy way to use the FIFO interface is via the
-		<application moreinfo="none">serctl</application>
-		command-line tool. When called along with "fifo",
-		FIFO command name, and optional parameters, the tool
-		generates a FIFO request and prints request result.
-		The following example shows use of this tool with
-		the <command moreinfo="none">uptime</command> and
-		<command moreinfo="none">which</command> commands.
-		<command moreinfo="none">uptime</command> returns
-		server's running time, <command moreinfo="none">which</command>
-		returns list of available FIFO commands. Note that only
-		the built-in FIFO command set is displayed as no modules
-		were loaded in this example.
-		<example>
-		    <title>Use of <application moreinfo="none">serctl</application> 
-		    to Access FIFO Server</title>
-		    <programlisting format="linespecific">
-[jiri@cat test]$ serctl fifo uptime
-Now: Fri Dec  6 17:56:10 2002
-Up Since: Fri Dec  6 17:56:07 2002
-Up time: 3 [sec]
-
-[jiri@cat test]$ serctl fifo which
-ps
-which
-version
-uptime
-print
-		    </programlisting>
-		</example>
-		The request which the <application moreinfo="none">serctl</application>
-		command-line tool sent to FIFO server looked like this:
-		<example>
-		    <title><command moreinfo="none">uptime</command> FIFO Request</title>
-		    <programlisting format="linespecific">
-:uptime:ser_receiver_1114
-		    </programlisting>
-		</example>
-		This request contains no parameters and consists only of
-		command name enclosed in colons and name of file, to which
-		a reply should be printed. FIFO replies consist of a status
-		line followed by optional parameters. The status line consists,
-		similarly to <acronym>SIP</acronym> reply status, of 
-		a three-digit status code and a reason phrase. Status codes
-		with leading digit 2 (200..299) are considered positive,
-		any other values indicate an error. For example, FIFO server
-		returns "500" if execution of a non-existing FIFO command is 
-		requested.
-		<example>
-		    <title>FIFO Errors</title>
-		    <programlisting format="linespecific">
-[jiri@cat sip_router]$ serctl fifo foobar
-500 command 'foobar' not available
-		    </programlisting>
-		</example>
-
-		<example>
-		    <title>Showing User Contacts Using serctl</title>
-		    <para>
-			Another example of use of FIFO is accessing server's
-			in-memory user location database. That's a very powerful
-			feature: web applications and other tools can use it
-			to gain users access to the database. They can add new
-			contacts (like permanent gateway destinations), remove
-			and review their whereabouts. The example here utilizes
-			FIFO command <command>ul_show_contact</command> to
-			retrieve current whereabouts of user "jiri".
-			<programlisting>
-<![CDATA[
-[jiri@fox ser]$ serctl fifo ul_show_contact location jiri
-<sip:195.37.78.160:14519>;q=0.00;expires=1012
-]]>
-			</programlisting>
-		    </para>
-		</example>
-	    </para>
-	    <para>
-		The user location example demonstrates an essential feature
-		of the FIFO server: extensibility. It is able to export new 
-		commands implemented in new modules.
-		Currently, usrloc module exports FIFO
-		commands for maintaining in-memory user location
-		database and tm module exports FIFO commands for
-		management of SIP transactions. See the 
-		example in 
-		<filename moreinfo="none">examples/web_im/send_im.php</filename>
-		for how to initiate a SIP transaction
-		(instant message)
-		from a PHP script via the FIFO server. This example
-		uses FIFO command 
-		<command moreinfo="none">t_uac_dlg</command>. The command
-		is followed by parameters: header fields and 
-		message body. The same FIFO command can be used from
-		other environments to send instant messages too. The
-		following example shows how to send instant messages
-		from a shell script.
-		<example>
-		    <title>Sending IM From Shell Script</title>
-		    <programlisting format="linespecific">
-#!/bin/sh
-#
-# call this script to send an instant message; script parameters
-# will be displayed in message body
-#
-# paremeters mean: message type, request-URI, outbound server is
-# left blank ("."), required header fields From and To follow,
-# then optional header fields terminated by dot and optional
-# dot-terminated body
-
-cat &gt; /tmp/ser_fifo &lt;&lt;EOF
-:t_uac_dlg:hh
-NOTIFY
-sip:[email protected]
-.
-From: sip:[email protected]
-To: sip:[email protected]
-foo: bar_special_header
-x: y
-p_header: p_value
-Contact: &lt;sip:[email protected]:9&gt;
-Content-Type: text/plain; charset=UTF-8
-.
-Hello world!!!! $@
-.
-EOF
-		    </programlisting>
-		</example>
-		</para>
-	    <example>
-		<title>Manipulation of User Contacts</title>
-		<para>
-		    The following example shows use of FIFO server to change 
-		    user's contacts. This may be very practical, if for example
-		    a user wishes to set up his cell phone number as his temporary
-		    contact. The cell phone, which is behind a PSTN gateway, cannot
-		    register automatically using SIP. The user needs to set 
-		    forwarding manually through some convenient web interface.
-		    The web interface needs to have the ability to upload new user's
-		    contacts to <application moreinfo="none">ser</application>.
-		    This is what the <command moreinfo="none">ul_add</command> FIFO
-		    command is good far. Paremeterized by user's name, table name,
-		    expiration time and wight, it allows external applications to
-		    introduce new contacts to server's in-memory user location table.
-		</para>
-		<para>
-		    The example is borrowed from <application moreinfo="none">serweb</application>,
-		    <application moreinfo="none">ser</application>'s web 
-		    PHP-written interface.
-		    It consists of a short "stub" function which carries out
-		    all mechanics of FIFO communication and of forming the FIFO
-		    request.
-		</para>
-		<programlisting format="linespecific">
-<![CDATA[
-
-/* construct and send a FIFO command; the command parameters $sip_address, 
-   $expires are PHP variables originating from an HTML form
- */
-	$fifo_cmd=":ul_add:".$config->reply_fifo_filename."\n".
-		$config->ul_table."\n".			//table
-		$user_id."\n".		//username
-		$sip_address."\n".				//contact
-		$expires."\n".					//expires
-		$config->ul_priority."\n\n";		//priority
-		$message=write2fifo($fifo_cmd, $errors, $status);
-
-/* .......... snip .................. */
-
-/* this is the stub function for communicating with FIFO server.
-   it dumps a request to FIFO server, opens a reply FIFO and
-   reads server's reply from it
-*/
-function write2fifo($fifo_cmd, &$errors, &$status){
-	global $config;
-
-	/* open fifo now */
-	$fifo_handle=fopen( $config->fifo_server, "w" );
-	if (!$fifo_handle) {
-		$errors[]="sorry -- cannot open fifo"; return;
-	}
-	
-	/* create fifo for replies */
-	@system("mkfifo -m 666 ".$config->reply_fifo_path );
-
-	/* add command separator */
-	$fifo_cmd=$fifo_cmd."\n";
-	
-	/* write fifo command */
-	if (fwrite( $fifo_handle, $fifo_cmd)==-1) {
-	    @unlink($config->reply_fifo_path);
-	    @fclose($fifo_handle);
-		$errors[]="sorry -- fifo writing error"; return;
-	}
-	@fclose($fifo_handle);
-	
-	/* read output now */
-	@$fp = fopen( $config->reply_fifo_path, "r");
-	if (!$fp) {
-	    @unlink($config->reply_fifo_path);
-		$errors[]="sorry -- fifo reading error"; return;
-	}
-
-	$status=fgetS($fp,256);
-	if (!$status) {
-	    @unlink($config->reply_fifo_path);
-		$errors[]="sorry -- fifo reading error"; return;
-	}
-	
-	$rd=fread($fp,8192);
-	@unlink($config->reply_fifo_path);
-	
-	return $rd;
-}
-]]>		   
-		</programlisting>
-	    </example>
-	    <para>
-		See
-		<xref linkend="fiforeference"> for a complete listing
-		of FIFO commands available with current 
-		<application moreinfo="none">ser</application>
-		distribution.
-	    </para>
-	    <section>
-		<title>Advanced Example: Click-To-Dial</title>
-		<para>
-		    A very useful SIP application is phonebook with
-		    "click-to-dial" feature. It allows users to keep their 
-		    phonebooks on the web and dial by clicking on an entry. 
-		    The great advantage is that you can use the phonebook 
-		    alone with any phone you have. If you temporarily use 
-		    another phone, upgrade it permanently with another make, 
-		    or use multiple phones in parallel, your phonebook will 
-		    stay with you on the web. You just need to click an entry 
-		    to initiate a call. Other scenario using "click-to-dial"
-		    feature includes "click to be connected with our
-		    sales representative".
-		</para>
-		<para>
-		    There are basically two ways how to build such a feature:
-		    distributed and centralized. We prefer the distributed
-		    approach since it is very robust and leight-weighted.
-		    The "click-to-dial" application just needs to instruct
-		    the calling user to call a destination and that's it.
-		    (That's done using "REFER" method.)
-		    Then, the calling user takes over whereas the initating
-		    application disappears from signaling and
-		    is no longer involved in subsequent communication. Which
-		    is good because such a simple design scales well. 
-		</para>
-		<para>
-		    The other design alternative is use of a B2BUA 
-		    <footnote>
-			<para>
-			    See <filename moreinfo="none">
-				draft-ietf-sipping-3pcc-02.txt 
-			    </filename>  for more details.
-			</para>
-		    </footnote>
-		    which acts as a "middleman" involved in signaling during the
-		    whole session. It is complex: ringing needs to be achieved
-		    using a media server, it introduces session state,
-		    mangling of SIP payloads, complexity when QoS reservation
-		    is used and possibly other threats which result from 
-		    e2e-unfriendly design. The only benefit
-		    is it works even for poor phones which do not support
-		    REFER -- which should not matter because you do not wish
-		    to buy such.
-		</para>
-		<para>
-		    So how does "distributed click-to-dial" application
-		    work? It is simple. The core piece is sending a REFER
-		    request to the calling party. REFER method is typically
-		    used for call transfer and it means "set up a call 
-		    to someone else". 
-		    </para>
-		<para>
-		    There is an issue -- most phones
-		    don't accept unsolicited REFER. If a malicious
-		    user made your phone to call thirty destinations without
-		    your agreement, you would certainly not appreciate it.
-		    The workaround is that first of all the click-to-dial
-		    application gives you a "wrapper call". If you accept it, 
-		    the application will send a REFER which will be considered
-		    by the phone as a part of approved communication and
-		    granted. Be aware that without cryptography, 
-		    security is still weak. Anyone who saw an INVITE can 
-		    generate an acceptable REFER.
-		    <example>
-			<title>Call-Flow for Click-To-Dial Using REFER</title>
-
-			<programlisting format="linespecific">
+&operation;
 
-        CTD                  Caller               Callee
-            #1 INVITE
-            ----------------->
-                             ...
-                             caller answers
-            #2 200
-            <-----------------
-            #3 ACK
-            ----------------->
-            #4 REFER
-            ----------------->
-            #5 202
-            <-----------------
-            #6 BYE
-            ----------------->
-            #7 200
-            <-----------------
-                                  #8 INVITE
-                                  ------------------>
-                                  #9 180 ringing
-                                  <------------------
+&apps;
 
+&otherapps;
 
-#1 click-to-dial (CTD) is started and the "wrapper call" is initiated
-INVITE caller
-From: controller
-To: caller
-SDP: on hold
-
-#2 calling user answes
-200 OK
-From: controller
-To: caller
-
-#3 CTD acknowledges
-ACK caller
-From controller
-To: caller
-
-#4 CTD initiates a transfer
-REFER caller
-From: controller
-To: caller
-Refer-To: callee
-Refered-By: controller
-
-#5 caller confirms delivery of REFER
-202 Accepted
-From: controller
-To: caller
-
-#6 CTD terminates the wrapper call -- it is no longer needed
-BYE caller
-From: controller
-To: caller
-
-#7 BYE is confirmed
-200 Ok
-From: controller
-To: caller
-
-#8 caller initates transaction solicited through REFER
-INVITE callee
-From: caller
-To: callee
-Referred-By: controller
-
-#9 that's it -- it is now up to callee to answer the INVITE
-180 ringing
-From: caller
-To: callee
-			</programlisting>
-
-		    </example>
-		</para>
-		<para>
-		    Implementation of this scenario is quite
-		    straight-forward: you initiate INVITE, BYE and
-		    REFER transaction.
-
-
-
-		    The largest amount of code
-		    is spent with getting dialog processing right.
-		    The subsequent BYE and REFER transactions need to
-		    be build using information learned from the reply
-		    to INVITE: Contact header field, To-tag and Route
-		    set. That's what the function 
-		    <function moreinfo="none">filter_fl</function>
-		    is used for. The "main" part just initiates
-		    each of the transactions, waits for its completion
-		    and proceeds to the next one until BYE is over.
-		    Source code of the example written in Bourne shell
-		    is available in source distrubtion, in 
-		    <filename moreinfo="none">examples/ctd.sh</filename>.
-		    A PHP implementation exists as well.
-		</para>
-		<example>
-		    <title>Running the CTD Example</title>
-		    <programlisting format="linespecific">
-[jiri@cat examples]$ ./ctd.sh 
-destination unspecified -- taking default value sip:[email protected]
-caller unspecified -- taking default value sip:[email protected]
-invitation succeeded
-refer succeeded
-bye succeeded
-		    </programlisting>
-		</example>
-	    </section> <!-- click-to-dial -->
-<!-- for some reason, this does not work :-(
-
-		<example>
-		    <title>Initiating a SIP Transaction from PHP via FIFO</title>
-
-
-		    <programlisting format="linespecific">
-			<textobject>
-			    <textdata fileref="../../examples/web_im/send_im.php" format="linespecific">
-			</textobject>
-			    
-		    </programlisting>
-
-		    
-		</example>
--->
-
-	</section> <!-- FIFO server -->
-    </chapter>
-
-    <chapter id="complementaryapps">
-	<title>Complementary Applications</title>
-	<section id="serctl">
-	    <title><application>serctl</application> command-line tool</title>
-	    <para>
-		<application>serctl</application> is a command-line utility which allows to
-		perform most of management tasks needed to operate
-		<application moreinfo="none">ser</application>: adding users, changing their passwords,
-		watching server status, etc. Usage of utility is
-		as follows:
-
-		<example>
-		    <title><application>serctl</application> usage</title>
-		    <programlisting format="linespecific">
-
-usage: 
-           * subscribers *
- serctl add &lt;username&gt; &lt;password&gt; &lt;email&gt; .. add a new subscriber (*)
- serctl passwd &lt;username&gt; &lt;passwd&gt; ......... change user's password (*)
- serctl rm &lt;username&gt; ...................... delete a user (*)
- serctl mail &lt;username&gt; .................... send an email to a user
- serctl alias show [&lt;alias&gt;] ............... show aliases
- serctl alias rm &lt;alias&gt; ................... remove an alias
- serctl alias add &lt;alias&gt; &lt;uri&gt; ............ add an aliases 
-
-           * access control lists *
- serctl acl show [&lt;username&gt;] .............. show user membership
- serctl acl grant &lt;username&gt; &lt;group&gt; ....... grant user membership (*)
- serctl acl revoke &lt;username&gt; [&lt;group&gt;] .... grant user membership(s) (*)
-
-           * usrloc *
- serctl ul show [&lt;username&gt;]................ show in-RAM online users
- serctl ul rm &lt;username&gt; ................... delete user's UsrLoc entries
- serctl ul add &lt;username&gt; &lt;uri&gt; ............ introduce a permanent UrLoc entry
- serctl showdb [&lt;username&gt;] ................ show online users flushed in DB
-
-           * server health *
- serctl monitor ............................ show internal status
- serctl ps ................................. show runnig processes 
- serctl fifo ............................... send raw commands to FIFO
-
-   Commands labeled with (*) will prompt for a MySQL password.
-   If the variable PW is set, the password will not be prompted.
-
- </programlisting>
-		</example>
-	    </para>
-	    <note>
-		<para>
-
-		Prior to using the utility, you have to first 
-		set the environment variable <constant>SIP_DOMAIN</constant>
-		to locally appropriate value (e.g., "foo.com"). It is
-		needed for calculation of user credentials, which depend
-		    on SIP digest realm. 
-		    (see also <link linkend="msmbug">MSM Authentication Issue</link>)
-	        </para>
-	    </note>
-
-	    <example>
-		<title>Example Output of Server Watching Command 
-		    <command moreinfo="none">sc monitor</command>
-		</title>
-		<programlisting format="linespecific">
-
-[cycle #: 2; if constant make sure server lives and fifo is on]
-Server: Sip EXpress router(0.8.8 (i386/linux))
-Now: Thu Sep 26 23:16:48 2002
-Up Since: Thu Sep 26 12:35:27 2002
-Up time: 38481 [sec]
-
-Transaction Statistics
-Current: 0 (0 waiting) Total: 606 (0 local)       
-Replied localy: 34      
-Completion status 6xx: 0, 5xx: 1, 4xx: 86, 3xx: 0,2xx: 519      
-
-Stateless Server Statistics
-200: 6218 202: 0 2xx: 0      
-300: 0 301: 0 302: 0 3xx: 0      
-400: 0 401: 7412 403: 2 404: 1258 407: 116 408: 0 483: 0 4xx: 25      500: 0 5xx: 0      
-6xx: 0      
-xxx: 0      
-failures: 0      
-
-UsrLoc Stats
-Domain Registered Expired
-'aliases' 9 0
-'location' 29 17
-
-		</programlisting>
-
-	    </example>
-	</section>
-
-	<section id="serweb">
-	    <title>Web User Provisioning -- <application>serweb</application></title>
-	    <para>
-		To make provisioning of user accounts convenient, 
-		a web front-end to <application moreinfo="none">ser</application>,
-		<application moreinfo="none">serweb</application> has been
-		developed. <application moreinfo="none">serweb</application>,
-		a PHP-written web application,
-		allows users to apply for new <application moreinfo="none">ser</application>
-		accounts, and maintain these.
-		Users can manipulate their contacts, keep a phone-book
-		with SIP addresses, change password, send instant SIP messages,
-		and more. Administrators can manipulate any accounts and
-		grant or revoke user privileges.
-	    </para>
-	    <para>
-		<application moreinfo="none">serweb</application> is freely
-		available from berlios site at
-		<ulink url="http://developer.berlios.de/cvs/?group_id=500">
-		http://developer.berlios.de/cvs/?group_id=500</ulink>. Installation
-		takes unpacking tarball to a safe destination at web server
-		(better not in the HTML tree) and configuring 
-		<filename moreinfo="none">config.php</filename> accordingly
-		to local conditions.
-	    </para>
-	    <para>
-		Running <application moreinfo="none">serweb</application> can
-		be seen at iptel.org's SIP site. Just create and use a SIP
-		account at <ulink url="http://www.iptel.org/user/">http://www.iptel.org/user/</ulink>
-	    </para>
-	</section> <!-- serweb -->
-
-
-    <section>
-	<title>Voicemail</title>
-&voicemail;
-    </section> <!-- voicemail -->
-
-    </chapter> <!-- other apps -->
+&reference;
     
-    <chapter>
-	<title>Reference</title>
-	<section id="coreoptions">
-	    <title>Core Options</title>
-	    <para>Core options are located in beginning of configuration file and
-	    affect behaviour of the server.</para>
-	    <itemizedlist>
-		<listitem>
-		    <para>
-			<varname>debug</varname> - Set log level, this is number between 0 and 9. Default 
-			is 0.
-			
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>fork</varname> - If set to yes, the server will spawn children. If set to no, the main
-			process will be processing all messages. Default is yes.
-			<note>
-			    <para>
-				Disabling child spawning is useful mainly for
-				debugging. When <varname>fork</varname> is turned off,
-				some features are unavailable: 
-				there is no attendant process, no pid file is generated,
-				and server listens only at one address. Make sure you
-				are debugging the same interface at which 
-				<application moreinfo="none">ser</application> listens.
-				The easiest way to do so is to set the interface using
-				<varname>listen</varname> option explicitly.
-				</para>
-			</note>
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>log_stderror</varname> - If set to yes, the server will print its debugging 
-			information to standard error output. If set to no, <command moreinfo="none">syslog</command> 
-			will be used. Default is no (printing to syslog).
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>listen</varname> - list of all IP addresses or hostnames SER should listen on.
-			<note>
-				<para>
-					This parameter may repeat several times, then SER will
-					listen on all addresses. For example, the following
-					command-line options (equivalent to "listen" config
-					option) may be used: 
-					<command>
-						ser -l foo  -l bar -p 5061 -l x -l y 
-					</command>
-					will listen on foo:5060, bar:5061 & x:5061 & y:5061
-
-				</para>
-			</note>
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>alias</varname> - Add IP addresses or hostnames to list of name aliases.
-			All requests with hostname matching an alias will satisfy the condition 
-			"uri==myself".
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>dns</varname> - Uses dns to check if it is necessary to add a "received=" field to a via.
-			Default is no.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>rev_dns</varname> - Same as dns but use reverse DNS. Default is no.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>port</varname> - Listens on the specified port (default 5060). It applies to the last 
-			address specified in listen and to all the following that do not have a corresponding "port" option.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>maxbuffer</varname> - Maximum receive buffer size which will not be exceeded by 
-			the auto-probing procedure even if the OS allows. Default value is MAX_RECV_BUFFER_SIZE,
-			which is 256k.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>children</varname> - Specifies how many children should be created when fork is set to yes.
-			Default value is CHILD_NO, which is 8. Running multiple children allows a server to 
-			server multiple requests in parallel when request processing block (e.g., on DNS
-			lookup). Note that <application>ser</application> typically spawns additional
-			processes, such as timer process or FIFO server. If FIFO server is turned on,
-			you can watch running processes using the <application moreinfo="none">serctl</application>
-			utility.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>check_via</varname> - Turn on or off Via host checking when forwarding replies.
-			Default is no.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>syn_branch</varname> - Shall the server use stateful synonym branches? It is faster but not 
-			reboot-safe. Default is yes.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>memlog</varname> - Debugging level for final memory statistics report. Default is L_DBG --
-			memory statistics are dumped only if <varname>debug</varname> is set high.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>sip_warning</varname> - Should replies include extensive warnings? By default yes,
-			it is good for trouble-shooting.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>fifo</varname> - FIFO special file pathname, for example "/tmp/ser_fifo". Default is
-			no filename -- no FIFO server is started then. We recommend to set it so that
-			accompanying applications such as <application moreinfo="none">serweb</application> or
-			<application moreinfo="none">serctl</application> can communicate with
-			<application moreinfo="none">ser</application>.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>fifo_mode</varname> - Permissions of the FIFO special file.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>server_signature</varname> - Should locally-generated messages include server's signature?
-			By default yes, it is good for trouble-shooting.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>reply_to_via</varname> - A hint to reply modules
-			whether they should send reply
-			to IP advertised in Via.
-			Turned off by default, which means that replies are
-			sent to IP address from which requests came from. 
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>user | uid</varname> - uid to be used by the server. 
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>group | gid</varname> - gid to be used by the server.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>mhomed</varname> -- enable calculation of 
-			outbound interface; useful on multihomed servers,
-			ser <link linkend="mhomed"></link>.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>loadmodule</varname> - Specifies a module to be loaded (for example "/usr/lib/ser/modules/tm.so")
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<varname>modparam</varname> - Module parameter configuration. The commands takes three parameters:
-			<itemizedlist>
-			    <listitem>
-				<para>
-				    <emphasis>module</emphasis> - Module in which the parameter resides.
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    <emphasis>parameter</emphasis> - Name of the parameter to be configured.
-				</para>
-			    </listitem>
-			    <listitem>
-				<para>
-				    <emphasis>value</emphasis> - New value of the parameter.
-				</para>
-			    </listitem>
-			</itemizedlist>
-		    </para>
-		</listitem>
-	    </itemizedlist>
-	</section>
-	<section id="builtinref">
-	    <title>Core Commands</title>
-
-
-	    <itemizedlist id="routeblocks">
-		<title>Route Blocks and Process Control</title>
-		<!--<para>
-		    Route block and process control keywords determine
-		    the order in which SIP requests are processed.
-		</para>-->
-		<listitem>
-		    <para>
-			<command>route[number]{...}</command> - This marks a "route block" in configuration files.
-			route blocks are basic building blocks of <application>ser</application> scripts. 
-			Each route block contains a sequence of 
-			<application>SER</application> actions enclosed in braces. Multiple route blocks
-			can be included in a configuration file.
-			When script execution begins on request receipt, 
-			route block number 0 is entered. Other route blocks serve as a kind of sub-routines and 
-			may be entered by calling the action <command>route(n)</command>, 
-			where n is number of the block. The action <command>break</command>
-			exits currently executed route block. It stops script execution for
-			route block number 0 or returns to calling route block otherwise.
-		    </para>
-		    <example>
-			<title>route</title>
-			<programlisting format="linespecific">
-route[0] {
-        # call routing block number 2
-	route(2);
-}
-
-route[2] {
-    forward("host.foo.bar", 5060);
-}
-</programlisting>
-		    </example>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>reply_route</command> is used to restart request processing
-			when a negative reply for a previously relayed request is received. It is only
-			used along with tm module, which stores the original requests and
-			can return to their processing later. To activate processing
-			of a <command>reply_route</command> block, call the TM action
-			<command>t_on_negative(route_number)</command> before calling
-			<command moreinfo="none">t_relay</command>. When a negative reply
-			comes back, the desired <command moreinfo="none">reply_route</command>
-			will be entered and processing of the original request may
-			continue. 
-			</para>
-		    <para>
-			The set of actions applicable from within
-			<command moreinfo="none">reply_route</command> blocks is limited.
-			Permitted actions are URI-manipulation actions, logging and
-			sending stateful replies using <command moreinfo="none">t_reply</command>.
-			Use of other actions may lead to
-			unpredictable results. (We plan to add syntactical checks in the future
-			so that improper action use will be detected during server start-up.)
-		    </para>
-		    <example>
-			<title>reply_route</title>
-			<programlisting format="linespecific">
-reply_route[1] {
-    # for some reason, the original forwarding attempt
-    # failed, try at another URI
-    append_branch("sip:[email protected]");
-    # if this new attempt fails too, try another reply_route
-    t_on_negative("2");
-}
-</programlisting>
-		    </example>
-		</listitem>
-
-		<listitem>
-		    <para>
-		    	The action <command>break</command> exits currently executed route block. 
-			It stops script execution for route block number 0 or returns to calling 
-			route block otherwise.
-			<note>
-			    <para>
-				We recommend to use <command moreinfo="none">break</command>
-				after any request forwarding or replying. This practice
-				helps to avoid erroneous scripts that 
-				continue execution and mistakenly send another reply or
-				forward a request to another place, resulting in
-				protocol confusion.
-			    </para>
-			</note>
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> break;
-		    </para>
-		</listitem>
-
-		<listitem>
-		    <para>
-			<command>route(n)</command> - call routing block route[n]{...};
-			when the routing block n finishes processing, control is passed
-			back to current block and processing continues.
-		    </para>
-		</listitem>
-
-		<listitem>
-		    <para>
-			<command>if (condition) statement</command> - Conditional statement.
-		    </para>
-		    <example>
-			<title>Use of <command>if</command></title>
-			<programlisting format="linespecific">
-if (method=="REGISTER) {
-    log("register received\n");
-};
-</programlisting>
-		    </example>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>if - else</command> - If-Else Conditional statement.
-		    </para>
-		    <example>
-			<title>Use of <command>if-else</command></title>
-			<programlisting format="linespecific">
-if (method=="REGISTER) {
-    log("register received\n");
-} else {
-    log("non-register received\n");
-};
-</programlisting>
-		    </example>
-		</listitem>
-
-	    </itemizedlist>
-	    <itemizedlist>
-		<title>Flag Manipulation</title>
-		<listitem>
-		    <para>
-			<command>setflag</command> - Set flag in the message.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> setflag(1);
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>resetflag</command> - Reset flag in the message.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> resetflag(1);
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>isflagset</command> - Test whether a particular flag is set.
-		    </para>
-		    <example>
-			<title>isflagset</title>
-			<programlisting format="linespecific">
-if (isflagset(1)) {
-    ....
-};
-</programlisting>
-		    </example>
-		</listitem>
-	    </itemizedlist>
-	    <itemizedlist>
-		<title>Manipulation of URI and Destination Set</title>
-		<listitem>
-		    <para>
-			<command>rewritehost | sethost | seth</command> - Rewrite host part of the Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> sethost("foo.bar.com");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>rewritehostport | sethostport | sethp</command> - Rewrite host and port part of the Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> sethostport("foo.bar.com:5060");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>rewriteuser | setuser | setu</command> - Rewrite or set username part of the Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> setuser("joe");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>rewriteuserpass | setuserpass | setup</command> - Rewrite or set username and password part
-			of the Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> setuserpass("joe:mypass");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>rewriteport | setport | setp</command> - Rewrite or set port of the Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> setport("5060");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>rewriteuri | seturi</command> - Rewrite or set the whole Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> seturi("sip:[email protected]:5060");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>revert_uri</command> - Revert changes made to the Request URI and use original Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> revert_uri();
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>prefix</command> - Add prefix to username in Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> prefix("123");
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>strip</command> - Remove first n characters of username in Request URI.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> strip(3);
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>append_branch</command> - Append a new destination to destination set of the message.
-		    </para>
-		    <para>
-			<example>
-			    <title>Use of <command>append_branch</command></title>
-			    <programlisting format="linespecific">
-# redirect to these two destinations: [email protected] and [email protected]
-# 1) rewrite the current URI
-rewriteuri("sip:[email protected]");
-# 2) append another entry to the destination ser
-append_branch("sip:[email protected]");
-# redirect now
-sl_send_reply("300", "redirection");
-			    </programlisting>
-			</example>
-		    </para>
-		</listitem>
-	    </itemizedlist>
-	    <itemizedlist>
-		<title>Message Forwarding</title>
-		<listitem>
-		    <para>
-			<command>forward(uri, port)</command> - Forward the request to given 
-			destination statelessly.  The uri and port parameters may take special 
-			values 'uri:host'
-			and 'uri:port' respectively, in which case SER forwards to destination
-			set in current URI. All other elements in a destination set are
-			ignored by stateless forwarding.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> forward("foo.bar.com"); # port defaults to 5060
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<command>send</command> - Send the message as is to a third party 
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> send("foo.bar.com");
-		    </para>
-		</listitem>
-	    </itemizedlist>
-	    <itemizedlist>
-		<title>Logging</title>
-		
-
-		<listitem>
-		    
-		    <para>
-			<command>log([level], message)</command> - Log a message.
-		    </para>
-		    <para>
-			<emphasis>Example:</emphasis> log(1, "This is a message with high log-level set to 1\n");
-		    </para>
-		    <para>
-			Logging is very useful for troubleshooting or attracting administrator's
-			attention to unusual situations. <application moreinfo="none">ser</application>
-			reports log messages to <application moreinfo="none">syslog</application>
-			facility unless it is configured to print them to <filename moreinfo="none">stderr</filename>
-			with the <varname>log_stderr</varname> configuration option. Log messages
-			are only issued if their log level exceeds threshold set with the
-			<varname>debug</varname> configuration option. If log level is omitted,
-			messages are issued at log level 4.
-		</para>
-		</listitem>
-
-	    </itemizedlist>
-
-
-
-
-	    <itemizedlist>
-		<title>Miscellaneous</title>
-		<listitem>
-		    <para>
-			<command>len_gt</command> - If length of the message is greater than value given as parameter, the
-			command will return 1 (indicating true). Otherwise -1 (indicating false) will be returned. It may 
-			take 'max_len' as parameter, in which case message size is limited
-			to internal buffer size BUF_SIZE (3040 by default).
-		    </para>
-		    <example>
-			<title>Use of <command>len_gt</command></title>
-			<programlisting format="linespecific">
-# deny all requests larger in size than 1 kilobyte
-if (len_gt(1024)) {
-    sl_send_reply("513", "Too big");
-    break;
-};
-			</programlisting>
-		    </example>
-		</listitem>
-	    </itemizedlist>
-	</section>
-	<section>
-	    <title>Command Line Parameters</title>
-	    <note>
-		<para>
-		    Command-Line parameters may be overridden by configuration
-		    file options which take precedence over them.
-		</para>
-	    </note>
-	    <itemizedlist>
-		<listitem>
-		    <para>
-			<emphasis>-h</emphasis> - Displays a short usage description, including all available options.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-c</emphasis> - Performs loop checks and computes branches.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-r</emphasis> - Uses dns to check if it is necessary to add a "received=" field to a via.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-R</emphasis> - Same as -r but uses reverse dns.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-v</emphasis> - Turns on via host checking when forwarding replies.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-d</emphasis> - Turns on debugging, multiple -d increase debugging level.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-D</emphasis> - Runs ser in the foreground (it doesn't fork into daemon mode).
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-E</emphasis> - Sends all the log messages to stderr.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-V</emphasis> - Displays the version number.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-f config-file</emphasis> - Reads the configuration from "config-file" (default ./ser.cfg).
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-l address</emphasis> - Listens on the specified address. Multiple -l mean listening 
-			on multiple addresses. The default behaviour is to listen on all the ipv4 interfaces.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-p port</emphasis> - Listens on the specified port (default 5060). It applies to the last 
-			address specified with -l and to all the following that do not have a corresponding -p.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-n processes-no</emphasis> - Specifies the number of children processes forked per 
-			interface (default 8).
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-b max_rcv_buf_size</emphasis> - Maximum receive buffer size which will not be exceeded by 
-			the auto-probing procedure even if the OS allows.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-m shared_mem_size</emphasis> - Size of the shared memory which will be allocated (in Megabytes).
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-w working-dir</emphasis> - Specifies the working directory. In the very improbable event 
-			that will crash, the core file will be generated here.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-t chroot-dir</emphasis> - Forces ser to chroot after reading the config file.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-u uid</emphasis> - Changes the user id under which ser runs.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-g gid</emphasis> - Changes the group id under which ser runs.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-P pid-file</emphasis> - Creates a file containing the pid of the main ser process.
-		    </para>
-		</listitem>
-		<listitem>
-		    <para>
-			<emphasis>-i fifo-path</emphasis> - Creates a fifo, useful for monitoring ser status.
-		    </para>
-		</listitem>
-	    </itemizedlist>
-	</section>
-
-
-
-
-	<section id="modulereference">
-	    <title>Modules</title>
-	    <para>
-		Module description is currently located in READMEs of
-		respective module directories. <filename moreinfo="none">README-MODULES</filename>
-		lists all available modules, including their maturity status.
-		In the current <application moreinfo="none">ser</application>
-		distribution, there are the following modules:
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    <emphasis>
-				acc
-			    </emphasis>
-			    -- call accounting using <application moreinfo="none">syslog</application> facility.
-			    Depends on tm.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				auth
-			    </emphasis>
-			    -- digest authentication. Depends on sl and mysql.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				exec
-			    </emphasis>
-			    -- execution of shell programs.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				jabber
-			    </emphasis> -- gateway between SIMPLE and Jabber instant messaging. Depends
-			    on tm and mysql.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				maxfwd
-			    </emphasis>
-			    -- checking max-forwards header field.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>msilo</emphasis>
-
-			-- message silo. Store for undelivered instant messages. Depends on tm and mysql.
-			    </para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				mysql
-			    </emphasis>
-			    -- mysql database back-end.
-			    </para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				registrar, usrloc
-			    </emphasis>
-			    -- User Location database. Works in in-memory mode or with mysql persistence
-			    support. Depends on sl, and on mysql if configured for use with mysql.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				rr
-			    </emphasis>
-			    -- Record Routing (strict and loose)
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				sl
-			    </emphasis>
-			    -- stateless User Agent server.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				sms
-			    </emphasis>
-			    -- SIMPLE/SMS gateway. Depends on tm. Takes special hardware.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    <emphasis>
-				textops
-			    </emphasis>
-			    -- textual request operations.
-			</para>
-		    </listitem>
-		    <listitem>			
-			<para>
-			    <emphasis>
-				tm
-			    </emphasis>
-			    -- transaction manager (stateful processing).
-			</para>
-		    </listitem>
-		</itemizedlist>
-	    </para>
-	    <para>
-		The most frequently used actions exported by modules are summarized
-		in <xref linkend="moduleactions">. For a full explanation of 
-		module actions, see documentation in respective module directories
-		in source distribution of <application moreinfo="none">ser</application>.
-	    </para>
-	    <table id="moduleactions">
-		<title>Frequently Used Module Actions</title>
-		<tgroup cols="4">
-		    <thead>
-			<row>			    
-			    <entry>
-				Command
-			    </entry>
-			    <entry>
-				Modules
-			    </entry>
-			    <entry>
-				Parameters
-			    </entry>
-			    <entry>
-				Comments
-			    </entry>
-			</row>
-		    </thead>
-
-		    <tbody>
-
-			<row>
-			    <entry>
-				append_hf
-			    </entry>
-			    <entry>
-				textops
-				</entry>
-			    <entry>
-				header field
-				</entry>
-			    <entry>
-				append a header field to the end of request's header
-				</entry>
-			    </row>
-			<row>
-			    <entry>
-				check_from
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				none
-			    </entry>
-			    <entry>
-				check if username in from header field matches authentication id
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				check_to
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				none
-			    </entry>
-			    <entry>
-				check if username in To header field matched authentication id
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				exec_dset
-			    </entry>
-			    <entry>
-				exec
-			    </entry>
-			    <entry>
-				command name
-			    </entry>
-			    <entry>
-				execute an external command and replace destination set with
-				its output
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				exec_msg
-			    </entry>
-			    <entry>
-				exec
-			    </entry>
-			    <entry>
-				command name
-			    </entry>
-			    <entry>
-				execute an external command and pass received SIP request
-				to its input
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				is_in_group
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				group name
-			    </entry>
-			    <entry>
-				check if a user, as identified by digest credentials, 
-				is a member of a group`
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				is_user
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				user id
-			    </entry>
-			    <entry>
-				returns true if request credentials belong to a user
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				is_user_in
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				user, group
-			    </entry>
-			    <entry>
-				check if user is member of a group; user can be gained
-				from request URI ("Request-URI"), To header field ("To"),
-				From header field ("From") or digest credentials
-				("Credentials")
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				lookup
-			    </entry>
-			    <entry>
-				usrloc
-			    </entry>
-			    <entry>
-				table name
-			    </entry>
-			    <entry>
-				attempt to translate request URI using user location database;
-				returns false if no contact for user found;
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				loose_route
-			    </entry>
-			    <entry>
-				rr
-			    </entry>
-			    <entry>
-				none
-			    </entry>
-			    <entry>
-				process loose routes in requests
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				mf_process_maxfwd_header
-			    </entry>
-			    <entry>
-				maxfwd
-			    </entry>
-			    <entry>
-				default max_forwards value
-			    </entry>
-			    <entry>
-				return true, if request's max_forwards value has not
-				reached zero yet; if none is included in the request,
-				set it to value in parameter
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				proxy_authorize
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				realm, subscriber table
-			    </entry>
-			    <entry>
-				returns true if requests contains proper credentials, false
-				otherwise
-			    </entry>
-			</row>
-
-
-
-
-
-
-			<row>
-			    <entry>
-				proxy_challenge
-			    </entry>
-			    <entry>
-				auth
-			    </entry>
-			    <entry>
-				realm, qop
-			    </entry>
-			    <entry>
-				challenge user to submit digest credentials; qop may be turned
-				off for backwards compatibility with elderly implementations
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				record_route
-			    </entry>
-			    <entry>
-				rr
-			    </entry>
-			    <entry>
-				loose routing (1=on, 0=off)
-			    </entry>
-			    <entry>
-				record-route a request
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				replace
-			    </entry>
-			    <entry>
-				textops
-			    </entry>
-			    <entry>
-				RegExp, Substitute
-			    </entry>
-			    <entry>
-				find the first occurence of a string matching the regular 
-				expression in header or body and replace it with a substitute
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				replace_all
-			    </entry>
-			    <entry>
-				textops
-			    </entry>
-			    <entry>
-				RegExp, Substitute
-			    </entry>
-			    <entry>
-				find all occurences of a string matching the regular 
-				expression in header or body and replace it with a substitute
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				save
-			    </entry>
-			    <entry>
-				usrloc
-			    </entry>
-			    <entry>
-				table name
-			    </entry>
-			    <entry>
-				for use in registrar: save content of Contact header fields
-				in user location database and reply with 200
-			    </entry>
-			</row>
-			<row>
-			    <entry>
-				search
-			    </entry>
-			    <entry>
-				textops
-			    </entry>
-			    <entry>
-				regular expression
-			    </entry>
-			    <entry>
-				search for a regular expression match in request header of body
-			    </entry>
-			</row>
-
-			<row>
-			    <entry>
-				sl_send_reply
-			    </entry>
-			    <entry>
-				sl
-			    </entry>
-			    <entry>
-				status code, reason phrase
-			    </entry>
-			    <entry>
-				reply a request statelessly
-			    </entry>
-			</row>
-
-			<row>
-			    <entry>
-				t_relay
-			    </entry>
-			    <entry>
-				tm
-			    </entry>
-			    <entry>
-				none
-			    </entry>
-			    <entry>
-				stateful forwarding to locations in current destination set
-			    </entry>
-			</row>
-
-			<row>
-			    <entry>
-				t_on_negative
-			    </entry>
-			    <entry>
-				tm
-			    </entry>
-			    <entry>
-				reply_route number
-			    </entry>
-			    <entry>
-				set reply_route block which shall be entered if stateful
-				forwarding fails
-			    </entry>
-			</row>
-
-			<row>
-			    <entry>
-				t_replicate
-			    </entry>
-			    <entry>
-				tm
-			    </entry>
-			    <entry>
-				host, port number
-			    </entry>
-			    <entry>
-				replicate a request to a destination
-			    </entry>
-			</row>
-
-
-		    </tbody>
-		</tgroup>
-	    </table>
-	</section> <!-- modules -->
-	<section id="fiforeference">
-	    <title>FIFO Commands Reference</title>
-	    <para>
-		This section lists currently supported FIFO commands. Some of them are
-		built-in in <application moreinfo="none">ser</application> core, whereas
-		others are exported by modules. The most important exporters are now
-		tm and usrloc module. tm FIFO commands allow users to initiate transactions
-		without knowledge of underlying SIP stack. usrloc FIFO commands allow
-		users to access in-memory user-location database. Note that that is the
-		only way how to affect content of the data-base in real-time. Changes
-		to MySql database do not affect in-memory table unless <application moreinfo="none">ser</application>
-		is restarted.
-	    </para>
-	    <table>
-		
-		<title>FIFO Commands</title>
-		<tgroup cols="4">
-		    <thead>
-			<row>
-			    <entry>
-				Command
-			    </entry>
-			    <entry>
-				Module
-			    </entry>
-			    <entry>
-				Parameters
-			    </entry>			    
-			    <entry>
-				Comments
-			    </entry>
-			</row>
-		    </thead>
-		    <tbody>
-			<row>
-			    <entry>
-				ps
-			    </entry>
-			    <entry>
-				core
-			    </entry>
-			    <entry>
-				none
-			    </entry>
-			    <entry>
-				prints running <application moreinfo="none">ser</application> processes
-			    </entry>
-			</row>
-			<row>
-			    <entry>which</entry>
-			    <entry>core</entry>
-			    <entry>none</entry>
-			    <entry>prints list of available FIFO commands</entry>
-			</row>
-			<row>
-			    <entry>arg</entry>
-			    <entry>core</entry>
-			    <entry>none</entry>
-			    <entry>prints list of command-line arguments with which 
-				<application moreinfo="none">ser</application> was started</entry>
-			</row>
-			<row>
-			    <entry>pwd</entry>
-			    <entry>core</entry>
-			    <entry>none</entry>
-			    <entry>prints <application moreinfo="none">ser</application>'s working
-			    directory</entry>
-			</row>
-			<row>
-			    <entry>version</entry>
-			    <entry>core</entry>
-			    <entry>none</entry>
-			    <entry>prints version of <application moreinfo="none">ser</application></entry>
-			</row>
-			<row>
-			    <entry>uptime</entry>
-			    <entry>core</entry>
-			    <entry>none</entry>
-			    <entry>prints <application moreinfo="none">ser</application>'s running time</entry>
-			</row>
-			<row>
-			    <entry>sl_stats</entry>
-			    <entry>sl</entry>
-			    <entry>none</entry>
-			    <entry>prints statistics for sl module</entry>
-			</row>
-			<row>
-			    <entry>t_stats</entry>
-			    <entry>tm</entry>
-			    <entry>none</entry>
-			    <entry>print statistics for tm module</entry>
-			</row>
-			<row>
-			    <entry>t_hash</entry>
-			    <entry>tm</entry>
-			    <entry>none</entry>
-			    <entry>print occupation of transaction table (mainly for debugging)</entry>
-			</row>
-			<row>
-			    <entry>t_uac_dlg</entry>
-			    <entry>tm</entry>
-			    <entry>method, request URI, outbound URI (if none, empty line with a single dot),
-					dot-line-terminated header fields, optionaly dot-line terminated message
-					body. 
-				</entry>
-					
-			    <entry>initiate a transaction.
-					From and To header fields must be present in header field list,
-					so does Content-Type if body is present. If CSeq, CallId and From-tag
-					are not present, ephemeral values are generated. Content_length is
-					calculated automatically if body present.
-				</entry>
-			</row>
-			<row>
-			    <entry>ul_stats</entry>
-			    <entry>usrloc</entry>
-			    <entry>none</entry>
-			    <entry>print usrloc statistics</entry>
-			</row>
-			<row>
-			    <entry>ul_rm</entry>
-			    <entry>usrloc</entry>
-			    <entry>table name, user name</entry>
-			    <entry>remove all user's contacts from user-location database</entry>
-			</row>
-			<row>
-			    <entry>ul_rm_contact</entry>
-			    <entry>usrloc</entry>
-			    <entry>table name, user name, contact</entry>
-			    <entry>remove a user's contact from user-location database</entry>
-			</row>
-			<row>
-			    <entry>ul_dump</entry>
-			    <entry>usrloc</entry>
-			    <entry>none</entry>
-			    <entry>print content of in-memory user-location database</entry>
-			</row>
-			<row>
-			    <entry>ul_flush</entry>
-			    <entry>usrloc</entry>
-			    <entry>none</entry>
-			    <entry>flush content of in-memory user-location cache in
-			    persistent database (MySQL)</entry>
-			</row>
-			<row>
-			    <entry>ul_add</entry>
-			    <entry>usrloc</entry>
-			    <entry>table name, user name, contact, expiration, priority (q)</entry>
-			    <entry>insert a contact address in user-location database</entry>
-			</row>
-			<row>
-			    <entry>ul_show_contact</entry>
-			    <entry>usrloc</entry>
-			    <entry>table, user name</entry>
-			    <entry>show user's contact addresses in user-location database</entry>
-			</row>
-		    </tbody>
-		</tgroup>
-	    </table>
-	</section>
-	<section>
-	    <title>Used Database Tables</title>
-	    <para>
-		<application moreinfo="none">ser</application> includes MySQL support
-		to guarantee data persistence across server reboots and storage
-		of users' web environment. The data stored in
-		the database include user profiles, access control lists, user location,
-		etc. Note that users are not supposed to alter the data directly, as it
-		could introduce inconsistency between data on persistence storage and
-		in server's memory.
-		The following list enumerates used tables and explains their purpose.
-
-		<itemizedlist>
-		    <listitem>
-			<para>
-			    subscriber -- table of users. It includes user names and
-			    security credentials, as well as additional user information.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    reserved -- reserved user names. <application moreinfo="none">serweb</application>
-			    does not permit creation of accounts with name on this list.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    phonebook -- user's personal phonebooks. Accessible via
-			    <application moreinfo="none">serweb</application>.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    pending -- table of unconfirmed subscription requests. Used by
-			    <application moreinfo="none">serweb</application>.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    missed_calls -- table of missed calls. Can be fed by acc modules
-			    if mysql support is turned on. Displayed by <application moreinfo="none">serweb</application>.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    location -- user contacts. Typically updated through
-			    <application moreinfo="none">ser</application>'r registrar
-			    functionality.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    grp -- group membership. Used by auth module to determine
-			    whether a user belongs to a group.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    event -- allows users to subscribe to additional services.
-			    Currently unused.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    aliases -- keeps track of alternative user names.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    active_sessions -- keeps track of currently active web sessions.
-			    For use by <application moreinfo="none">serweb</application>.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    acc -- keeps track of accounted calls.  Can be fed by acc module
-			    if mysql support is turned on. Displayed by <application moreinfo="none">serweb</application>.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    config -- maintains attribute-value pairs for keeping various information.
-			    Currently not used.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    silo -- message store for instant messages which could not have been
-			    delivered.
-			</para>
-		    </listitem>
-		    <listitem>
-			<para>
-			    version -- keeps version number of each table definition.
-			</para>
-		    </listitem>
-		</itemizedlist>
-		
-	    </para>
-	</section>
-    </chapter> <!-- reference -->
     
     <!-- TODO
 

+ 1 - 1
doc/seruser/voicemail.sgml

@@ -1,4 +1,4 @@
-<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ ]>
+<!-- <!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ ]> -->
 <section>
 <title>Introduction</title>
 <para>

+ 2 - 2
etc/ser.cfg

@@ -10,11 +10,11 @@ debug=3          # debug level (cmd line: -dddddddddd)
 fork=yes
 log_stderror=no	# (cmd line: -E)
 
-/* Uncomment these lines to enter debugging mode 
+/* Uncomment these lines to enter debugging mode */
 debug=7
 fork=no
 log_stderror=yes
-*/
+/**/
 
 check_via=no	# (cmd. line: -v)
 dns=no           # (cmd. line: -r)