|
@@ -1,6940 +0,0 @@
|
|
|
-<!-- $Id$ -->
|
|
|
-<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN">
|
|
|
-
|
|
|
-<book label="serdev" id="serdev" lang="EN">
|
|
|
-<?dbhtml filename="index.html">
|
|
|
- <title>SIP Express Router v0.8.8 - Developer's Guide</title>
|
|
|
- <bookinfo>
|
|
|
- <authorgroup>
|
|
|
- <author>
|
|
|
- <firstname>Jan</firstname>
|
|
|
- <surname>Janak</surname>
|
|
|
- <email>[email protected]</email>
|
|
|
- </author>
|
|
|
- <author>
|
|
|
- <firstname>Jiri</firstname>
|
|
|
- <surname>Kuthan</surname>
|
|
|
- <email>[email protected]</email>
|
|
|
- </author>
|
|
|
- <author>
|
|
|
- <firstname>Bogdan</firstname>
|
|
|
- <surname>Iancu</surname>
|
|
|
- <email>[email protected]</email>
|
|
|
- </author>
|
|
|
- </authorgroup>
|
|
|
- <copyright>
|
|
|
- <year>2001</year>
|
|
|
- <year>2002</year>
|
|
|
- <holder>FhG Fokus</holder>
|
|
|
- </copyright>
|
|
|
- <legalnotice>
|
|
|
- <para>
|
|
|
- This documentation is free software; you can redistribute
|
|
|
- it and/or modify it under the terms of the GNU General Public
|
|
|
- License as published by the Free Software Foundation; either
|
|
|
- version 2 of the License, or (at your option) any later
|
|
|
- version.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- This program is distributed in the hope that it will be
|
|
|
- useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
|
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
- See the GNU General Public License for more details.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- You should have received a copy of the GNU General Public
|
|
|
- License along with this program; if not, write to the Free
|
|
|
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
- MA 02111-1307 USA
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- For more details see the file COPYING in the source
|
|
|
- distribution of SER.
|
|
|
- </para>
|
|
|
- </legalnotice>
|
|
|
-
|
|
|
- <abstract>
|
|
|
- <para>
|
|
|
- The document describes the SIP Express Router internals and algorithms. It describes
|
|
|
- overall server architecture, request processing, configuration, memory management,
|
|
|
- interprocess locking, module interface and selected modules in detail.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- The document is intended mainly for module developers wishing to implement
|
|
|
- a new module for the server. Other people like developers of SIP related
|
|
|
- software or students might be interested too.
|
|
|
- </para>
|
|
|
- </abstract>
|
|
|
-
|
|
|
- </bookinfo>
|
|
|
-
|
|
|
- <toc></toc>
|
|
|
-
|
|
|
- <chapter id="server-startup">
|
|
|
- <title>The Server Startup</title>
|
|
|
- <para>
|
|
|
- The <function moreinfo="none">main</function> function in file <filename moreinfo="none">main.c</filename>
|
|
|
- is the first function called upon server startup. It's purpose is to initialize the server and
|
|
|
- enter main loop. The server initialization will be described in the following sections.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- Particular initialization steps are described in order in which they appear in <function>main</function> function.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="signal-installation">
|
|
|
- <title>Installation Of New Signal Handlers</title>
|
|
|
- <para>
|
|
|
- The first step in the initialization process is the installation of new signal handlers. We need
|
|
|
- our own signal handlers to be able to do graceful shutdown, print server statistics and so on. There is
|
|
|
- only one signal handler function which is function <function moreinfo="none">sig_usr</function> in
|
|
|
- file <filename moreinfo="none">main.c</filename>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The following signals are handled by the function: SIGINT, SIGPIPE, SIGUSR1, SIGCHLD, SIGTERM, SIGHUP and
|
|
|
- SIGUSR2.
|
|
|
- </para>
|
|
|
- </section> <!-- signal-installation -->
|
|
|
-
|
|
|
- <section id="cmd-line-params">
|
|
|
- <title>Processing Command Line Parameters</title>
|
|
|
- <para>
|
|
|
- <acronym>SER</acronym> utilizes the <function moreinfo="none">getopt
|
|
|
- </function>function to parse command line parameters.
|
|
|
- The function is extensively described in the man pages.
|
|
|
- </para>
|
|
|
- </section> <!-- cmd-line-params -->
|
|
|
-
|
|
|
- <section id="parser-init">
|
|
|
- <title>Parser Initialization</title>
|
|
|
- <para>
|
|
|
- <acronym>SER</acronym> contains a fast 32-bit parser. The parser uses pre-calculated hash table that needs to be
|
|
|
- filled in upon startup. The initialization is done here, there are two functions that do the
|
|
|
- job. Function <function moreinfo="none">init_hfname_parser</function> initializes hash table
|
|
|
- in header field name parser and function <function moreinfo="none">init_digest_parser</function>
|
|
|
- initializes hash table in digest authentication parser. The parser's internals will be described
|
|
|
- later.
|
|
|
- </para>
|
|
|
- </section> <!-- parser-init -->
|
|
|
-
|
|
|
-<!--
|
|
|
- <section id="hash-init">
|
|
|
- <title>Hash Table Initialization</title>
|
|
|
- <para>TBD.</para>
|
|
|
- </section>
|
|
|
--->
|
|
|
-
|
|
|
- <section id="malloc-init">
|
|
|
- <title>Malloc Initialization</title>
|
|
|
- <para>
|
|
|
- To make <acronym>SER</acronym> even faster we decided to re-implement memory allocation routines. The new
|
|
|
- <function moreinfo="none">malloc</function>
|
|
|
- better fits our needs and speeds up the server a lot. The memory management subsystem needs
|
|
|
- to be initialized upon server startup. The initialization mainly creates internal data
|
|
|
- structures and allocates memory region to be partitioned.
|
|
|
- </para>
|
|
|
-
|
|
|
- <important>
|
|
|
- <para>
|
|
|
- The memory allocation code must be initialized <emphasis>BEFORE</emphasis> any of its function is called !
|
|
|
- </para>
|
|
|
- </important>
|
|
|
- </section> <!-- malloc-init -->
|
|
|
-
|
|
|
- <section id="timer-init">
|
|
|
- <title>Timer Initialization</title>
|
|
|
- <para>
|
|
|
- Various subsystems of the server must be called periodically regardless of the incoming
|
|
|
- requests. That's what timer is for. Function <function moreinfo="none">init_timer</function>
|
|
|
- initializes the timer subsystem. The function is called from <filename moreinfo="none">main.c</filename>
|
|
|
- and can be found in <filename moreinfo="none">timer.c</filename> The timer subsystem will
|
|
|
- be described later.
|
|
|
- </para>
|
|
|
- <warning>
|
|
|
- <para>
|
|
|
- Timer subsystem must be initialized before config file is parsed !
|
|
|
- </para>
|
|
|
- </warning>
|
|
|
- </section> <!-- timer-init -->
|
|
|
-
|
|
|
- <section id="fifo-init">
|
|
|
- <title><acronym>FIFO</acronym> Initialization</title>
|
|
|
- <para>
|
|
|
- <acronym>SER</acronym> has built-in support for <acronym>FIFO</acronym> control. It means that the
|
|
|
- running server can accept
|
|
|
- commands over a FIFO special file (a named pipe). Function <function moreinfo="none">register_core_fifo</function>
|
|
|
- initializes <acronym>FIFO</acronym> subsystem and registers basic commands, that are processed by the core
|
|
|
- itself. The function can be found in file <filename moreinfo="none">fifo_server.c</filename>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The <acronym>FIFO</acronym> server will be described in another chapter.
|
|
|
- </para>
|
|
|
- </section> <!-- fifo-init -->
|
|
|
-
|
|
|
- <section id="builtin-mod-reg">
|
|
|
- <title>Built-in Module Initialization</title>
|
|
|
- <para>
|
|
|
- Modules can be either loaded dynamically at runtime or compiled in statically. When a module
|
|
|
- is loaded at runtime, it is registered
|
|
|
- <footnote id="regfoot">
|
|
|
- <para>
|
|
|
- Module registration is a process when the core tries to find what functions and
|
|
|
- parameters are offered by the module.
|
|
|
- </para>
|
|
|
- </footnote>
|
|
|
- immediately with the
|
|
|
- core. When the module is compiled in statically, the registration<footnoteref linkend="regfoot">
|
|
|
- must be performed during the server startup. Function
|
|
|
- <function moreinfo="none">register_builtin_modules</function> does the job.
|
|
|
- </para>
|
|
|
- </section> <!-- builtin-mod-reg -->
|
|
|
-
|
|
|
- <section id="ser-config">
|
|
|
- <title>Server Configuration</title>
|
|
|
- <para>
|
|
|
- The server is configured through a configuration file. The configuration file
|
|
|
- is C-Shell like script which defines how incoming requests should be processed.
|
|
|
-
|
|
|
- The file cannot be interpreted directly because that would be very slow. Instead
|
|
|
- of that the file is translated into an internal binary representation. The process
|
|
|
- is called compilation and will be described in the following sections.
|
|
|
- </para>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- The following sections only describe how the internal binary representation is
|
|
|
- being constructed from the config file. The way how the binary representation is used
|
|
|
- upon a request arrival will be described later.
|
|
|
- </para>
|
|
|
- </note>
|
|
|
- <para>The compilation can be divided in several steps:</para>
|
|
|
-
|
|
|
- <section id="lex-analysis">
|
|
|
- <title>Lexical Analysis</title>
|
|
|
- <para>
|
|
|
- Lexical analysis is process of converting the input (the configuration file in this
|
|
|
- case) into a stream of tokens. A token is a set of characters that
|
|
|
- 'belong' together. A program that can turn the input into stream of tokens is
|
|
|
- called scanner. For example, when scanner encounters a number in the config
|
|
|
- file, it will produce token NUMBER.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- There is no need to implement the scanner from scratch, it can be done automatically.
|
|
|
- There is a utility called flex. Flex accepts a configuration file and generates
|
|
|
- scanner according to the configuration file. The configuration file for flex consists
|
|
|
- of several lines - each line describing one token. The tokens are described using
|
|
|
- regular expressions. For more details, see flex manual page or info documentation.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Flex input file for the <acronym>SER</acronym> config file is in file
|
|
|
- <filename moreinfo="none">cfg.lex</filename>. The file is processed by flex when the
|
|
|
- server is being compiled and the result is written in file
|
|
|
- <filename moreinfo="none">lex.yy.c</filename>. The output file contains the scanner
|
|
|
- implemented in the C language.
|
|
|
- </para>
|
|
|
- </section> <!-- lex-analysis -->
|
|
|
-
|
|
|
- <section id="syntax-analysis">
|
|
|
- <title>Syntactical Analysis</title>
|
|
|
- <para>
|
|
|
- The second stage of configuration file processing is called syntactical analysis. Purpose
|
|
|
- of syntactical analysis is to check if the configuration file has been well formed, doesn't
|
|
|
- contain syntactical errors and perform various actions at various stages of the analysis.
|
|
|
- Program performing syntactical analysis is called parser.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Structure of the configuration file is described using grammar. Grammar is a set of rules
|
|
|
- describing valid 'order' or 'combination' of tokens. If the file isn't conformable with it's
|
|
|
- grammar, it is syntactically invalid and cannot be further processed. In that case an error
|
|
|
- will be issued and the server will be aborted.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- There is a utility called yacc. Input of the utility is a file containing the grammar of
|
|
|
- the configuration file, in addition to the grammar, you can describe what action the parser
|
|
|
- should do at various stages of parsing. For example, you can instruct the parser to create a
|
|
|
- structure describing an <acronym>IP</acronym> address every time it finds an <acronym>IP</acronym>
|
|
|
- address in the configuration file and convert the address to its binary representation.
|
|
|
- </para>
|
|
|
- <para>For more information see yacc documentation.</para>
|
|
|
- <para>
|
|
|
- yacc creates the parser when the server is being compiled from the sources.
|
|
|
- Input file for yacc is <filename moreinfo="none">cfg.y</filename>. The file contains grammar
|
|
|
- of the config file along with actions that create the binary representation of the file.
|
|
|
- Yacc will write its result into file <filename moreinfo="none">cfg.tab.c</filename>. The
|
|
|
- file contains function <function moreinfo="none">yyparse</function> which will parse the whole
|
|
|
- configuration file and construct the binary representation. For more information about the
|
|
|
- bison input file syntax see bison documentation.
|
|
|
- </para>
|
|
|
- </section> <!-- syntax-analysis -->
|
|
|
-
|
|
|
- <section id="config-file-struct">
|
|
|
- <title>Config File Structure</title>
|
|
|
- <para>
|
|
|
- The configuration file consist of three sections, each of the sections will be
|
|
|
- described separately.
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>Route Statement</emphasis> - The statement describes how incoming requests
|
|
|
- will be processed.
|
|
|
- When a request is received, commands in one or more <quote>route</quote> sections will be executed
|
|
|
- step by step. The config file must always contain one main <quote>route</quote> statement and
|
|
|
- may contain several additional <quote>route</quote> statements. Request processing always starts
|
|
|
- at the beginning
|
|
|
- of the main <quote>route</quote> statement. Additional <quote>route</quote> statements can be
|
|
|
- called from the main
|
|
|
- one or another additional <quote>route</quote> statements (It it similar to function calling).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>Assign Statement</emphasis> - There are many configuration variables across
|
|
|
- the server and this
|
|
|
- statement makes it possible to change their value. Generally it is a list of assignments,
|
|
|
- each assignment on a separate line.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>Module Statement</emphasis> - Additional functionality of the server is
|
|
|
- available through separate
|
|
|
- modules. Each module is a shared object that can be loaded at runtime. Modules can
|
|
|
- export functions, that can be called from the configuration file and variables, that
|
|
|
- can be configured from the config file. The module statement makes it possible to load
|
|
|
- modules and configure them. There are two commands in the statement -
|
|
|
- <function moreinfo="none">loadmodule</function> and <function moreinfo="none">modparam</function>.
|
|
|
- The first can load a module. The second one can configure module's internal
|
|
|
- variables.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- <para>
|
|
|
- In the following sections we will describe in detail how the three sections are being processed
|
|
|
- upon server startup.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="route-stm">
|
|
|
- <title>Route Statement</title>
|
|
|
- <para>The following grammar snippet describes how the route statement is constructed</para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-route_stm = "route" "{" actions "}"
|
|
|
-{
|
|
|
- $$ = push($3, &rlist[DEFAULT_RT]);
|
|
|
-}
|
|
|
-
|
|
|
-actions = actions action { $$ = append_action($1, $2}; }
|
|
|
- | action { $$ = $1; }
|
|
|
-
|
|
|
-action = cmd SEMICOLON { $$ = $1; }
|
|
|
- | SEMICOLON { $$ = 0; }
|
|
|
-
|
|
|
-cmd = "forward" "(" host ")" { $$ = mk_action(FORWARD_T, STRING_ST, NUMBER_ST, $3, 0)
|
|
|
- | ...
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- A config file can contain one or more "route" statements. "route" statement without
|
|
|
- number will be executed first and is called the main route statement. There can be
|
|
|
- additional route statements identified by number, these additional route statements
|
|
|
- can be called from the main route statement or another additional route statements.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each route statement consists of a set of actions. Actions in the route statement are
|
|
|
- executed step by step in the same order in which they appear in the config file. Actions in the
|
|
|
- route statement are delimited by semicolon.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each action consists of one and only one command (cmd in the grammar). There are many types
|
|
|
- of commands defined. We don't list all of them here because the list would be too long and all the
|
|
|
- commands are processed in the same way. Therefore we show only one example (forward) and
|
|
|
- interested readers might look in <filename moreinfo="none">cfg.y</filename> file for
|
|
|
- full list of available commands.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each rule in the grammar contains a section enclosed in curly braces. The section is the C code
|
|
|
- snippet that will be executed every time the parser recognizes that rule in the config file.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- For example, when the parser finds <function moreinfo="none">forward</function> command,
|
|
|
- <function moreinfo="none">mk_action</function> function (as specified in the
|
|
|
- grammar snippet above) will be called. The function creates a new structure with
|
|
|
- <structfield>type</structfield> field set to FORWARD_T representing the command. Pointer
|
|
|
- to the structure will be returned as the return value of the rule.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The pointer propagates through <function moreinfo="none">action</function> rule to
|
|
|
- <function moreinfo="none">actions</function> rule. <function moreinfo="none">Actions</function> rule
|
|
|
- will create linked list of all commands. The linked list will be then inserted into
|
|
|
- <structfield>rlist</structfield> table.
|
|
|
- (Function <function moreinfo="none">push</function> in rule <function moreinfo="none">route_stm</function>).
|
|
|
- Each element of the table represents one <quote>route</quote> statement of the config file.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each route statement of the configuration file will be represented by a linked list of all
|
|
|
- actions in the statement. Pointers to all the lists will be stored in rlist array. Additional
|
|
|
- route statements are identified by number. The number also serves as index to the array.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When the core is about to execute route statement with number n, it will look in the array
|
|
|
- at position n. If the element at position n is not null then there is a linked list of
|
|
|
- commands and the commands will be executed step by step.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Reply-Route statement is compiled in the same way. Main differences are:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Reply-Route statement is executed when a <acronym>SIP</acronym> <emphasis>REPLY</emphasis>
|
|
|
- comes (not ,<acronym>SIP</acronym> <emphasis>REQUEST</emphasis>).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Only subset of commands is allowed in the reply-route statement.
|
|
|
- (See file <filename moreinfo="none">cfg.y</filename> for more details).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Reply-route statement has it's own array of linked-lists.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- </section> <!-- route-stm -->
|
|
|
-
|
|
|
- <section id="assign-stm">
|
|
|
- <title>Assign Statement</title>
|
|
|
- <para>
|
|
|
- The server contains many configuration variables. There is a section of the
|
|
|
- config file in which the variables can be assigned new value. The section
|
|
|
- is called The Assign Statement. The following grammar snippet describes how the section
|
|
|
- is constructed (only one example will be shown):
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-assign_stm = "children" '=' NUMBER { children_no=$3; }
|
|
|
- | "children" '=' error { yyerror("number expected"); }
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- The number in the config file is assigned to <varname>children_no</varname> variable.
|
|
|
- The second statement will be executed if the parameter is not number or is in invalid
|
|
|
- format and will issue an error and abort the server.
|
|
|
- </para>
|
|
|
- </section> <!-- assign-stm -->
|
|
|
-
|
|
|
- <section id="module-stm">
|
|
|
- <title>Module Statement</title>
|
|
|
- <para>
|
|
|
- The module statement allows module loading and configuration. There are two commands:
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>loadmodule</emphasis> - Load the specified module in form of a shared object.
|
|
|
- The shared object will be loaded using <function moreinfo="none">dlopen</function>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>modparam</emphasis> - It is possible to configure a module using this
|
|
|
- command. The command accepts 3 parameters:
|
|
|
- <emphasis>module name</emphasis>, <emphasis>variable name</emphasis>
|
|
|
- and <emphasis>variable value</emphasis>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- <para>The following grammar snippet describes the module statement:</para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-module_stm = "loadmodule" STRING
|
|
|
-{
|
|
|
- DBG("loading module %s\n", $2);
|
|
|
- if (load_module($2)!=0) {
|
|
|
- yyerror("failed to load module");
|
|
|
- }
|
|
|
-}
|
|
|
- | "loadmodule" error { yyerror("string expected"); }
|
|
|
- | "modparam" "(" STRING "," STRING "," STRING ")"
|
|
|
- {
|
|
|
- if (set_mod_param($3, $5, STR_PARAM, $7) != 0) {
|
|
|
- yyerror("Can't set module parameter");
|
|
|
- }
|
|
|
- }
|
|
|
- | "modparam" "(" STRING "," STRING "," NUMBER ")"
|
|
|
- {
|
|
|
- if (set_mod_param($3, $5, INT_PARAM, (void*)$7) != 0) {
|
|
|
- yyerror("Can't set module parameter");
|
|
|
- }
|
|
|
- }
|
|
|
- | MODPARAM error { yyerror("Invalid arguments"); }
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- When the parser finds <function moreinfo="none">loadmodule</function> command, it will execute
|
|
|
- statement in curly braces.
|
|
|
- The statement will call <function moreinfo="none">load_module</function> function.
|
|
|
- The function will load the specified filename using <function moreinfo="none">dlopen</function>.
|
|
|
- If <function moreinfo="none">dlopen</function> was successful, the server will look for
|
|
|
- <structname>exports</structname> structure describing the module's interface and register the
|
|
|
- module. For more details see <link linkend="module-interface">module section</link>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If the parser finds <function moreinfo="none">modparam</function> command, it will try to configure
|
|
|
- the specified variable in the
|
|
|
- specified module. The module must be loaded using <function moreinfo="none">loadmodule</function>
|
|
|
- before <function moreinfo="none">modparam</function> for the module can be used !
|
|
|
- Function <function moreinfo="none">set_mod_param</function> will be called and will
|
|
|
- configure the variable in the specified module.
|
|
|
- </para>
|
|
|
- </section> <!-- module-stm -->
|
|
|
- </section> <!-- config-file-struct -->
|
|
|
- </section> <!-- ser-config -->
|
|
|
-
|
|
|
- <section id="iface-config">
|
|
|
- <title>Interface Configuration</title>
|
|
|
- <para>
|
|
|
- The server will try to obtain list of all configured interfaces of the host it is running on. If it
|
|
|
- fails the server tries to convert hostname to <acronym>IP</acronym> address and will use interface with
|
|
|
- the <acronym>IP</acronym> address only.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Function <function moreinfo="none">add_interfaces</function> will add all configured interfaces to the
|
|
|
- array.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Try to convert all interface names to IP addresses, remove duplicates...
|
|
|
- </para>
|
|
|
- </section> <!-- iface-config -->
|
|
|
-
|
|
|
- <section id="daemon">
|
|
|
- <title>Turning into a Daemon</title>
|
|
|
- <para>
|
|
|
- When configured so, <acronym>SER</acronym> becomes a daemon during startup. A process is called daemon
|
|
|
- when it hasn't associated controlling terminal. See function
|
|
|
- <function moreinfo="none">daemonize</function> in file
|
|
|
- <filename moreinfo="none">main.c</filename> for more details.
|
|
|
- The function does the following:
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>chroot</emphasis> is performed if necessary. That ensures that the server will have
|
|
|
- access to a particular directory and its subdirectories only.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Server's working directory is changed if the new working directory was
|
|
|
- specified (usually it is /).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If command line parameter -g was used, the server's group ID is changed
|
|
|
- to that value.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If command line parameter -u was used, the server's user ID is changed
|
|
|
- to that value.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Perform <emphasis>fork</emphasis>, let the parent process exit. This ensures that we
|
|
|
- are not a group leader.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Perform <emphasis>setsid</emphasis> to become a session leader and drop the controlling
|
|
|
- terminal.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Fork again to drop group leadership.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Create a pid file.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Close all opened file descriptors.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- daemon -->
|
|
|
-
|
|
|
- <section id="module-init">
|
|
|
- <title>Module Initialization</title>
|
|
|
- <para>
|
|
|
- The whole config file was parsed, all modules were loaded already and can
|
|
|
- be initialized now. A module can tell the core that it needs to be initialized
|
|
|
- by exporting <function moreinfo="none">mod_init</function> function.
|
|
|
- <function moreinfo="none">mod_init</function> function of all loaded modules
|
|
|
- will be called now.
|
|
|
- </para>
|
|
|
- </section> <!-- module-init -->
|
|
|
-
|
|
|
- <section id="rt-list-fix">
|
|
|
- <title>Routing List Fixing</title>
|
|
|
- <para>
|
|
|
- After the whole routing list was parsed, there might be still places that can be
|
|
|
- further processed to speed-up the server. For example, several commands accept
|
|
|
- regular expression as one of their parameters. The regular expression can be compiled
|
|
|
- too and processing of compiled expression will be much faster.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Another example might be string as parameter of a function. For example if you call
|
|
|
- <function moreinfo="none">append_hf("Server: SIP Express Router\r\n")</function> from the routing
|
|
|
- script, the function will
|
|
|
- append a new header field after the last one. In this case, the function needs to know length
|
|
|
- of the string parameter. It could call <function moreinfo="none">strlen</function> every time it is
|
|
|
- called, but that is not a very good idea because <function moreinfo="none">strlen</function> would
|
|
|
- be called every time a message is processed and that is not necessary.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Instead of that the length of the string parameter could be pre-calculated upon server startup, saved
|
|
|
- and reused later. The processing of the request will be faster because
|
|
|
- <function moreinfo="none">append_hf</function> doesn't need
|
|
|
- to call <function moreinfo="none">strlen</function> every time, I can just reuse the saved value.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- This can be used also for string to int conversions, hostname lookups, expression evaluation and so on.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- This process is called Routing List Fixing and will be done as one of last steps of the server startup.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Every loaded module can export one or more functions. Each such function can have associated a fixup
|
|
|
- function, which should do fixing as described in this section. All such fixups of all loaded modules
|
|
|
- will be called here. That makes it possible for module functions to fix their parameters too if necessary.
|
|
|
- </para>
|
|
|
- </section> <!-- rt-list-fix -->
|
|
|
-
|
|
|
- <section id="stat-init">
|
|
|
- <title>Statistics Initialization</title>
|
|
|
- <para>
|
|
|
- If compiled-in, the core can produce some statistics about itself and traffic processed. The statistics
|
|
|
- subsystem gets initialized here, see function <function moreinfo="none">init_stats</function>.
|
|
|
- </para>
|
|
|
- </section> <!-- stat-init -->
|
|
|
-
|
|
|
- <section id="socket-init">
|
|
|
- <title>Socket Initialization</title>
|
|
|
- <para>
|
|
|
- UDP socket initialization depends on <varname>dont_fork</varname> variable. If this variable is set
|
|
|
- (only one process will
|
|
|
- be processing incoming requests) and there are multiple listen interfaces, only the first one will be used. This
|
|
|
- mode is mainly for debugging.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If the variable is not set, then sockets for all configured interfaces will be created and initialized.
|
|
|
- See function <function moreinfo="none">udp_init</function> in file
|
|
|
- <filename moreinfo="none">udp_server.c</filename> for more details.
|
|
|
- </para>
|
|
|
- </section> <!-- socke-init -->
|
|
|
-
|
|
|
- <section id="forking">
|
|
|
- <title>Forking</title>
|
|
|
- <para>
|
|
|
- The rest of the initialization process depends on value of <varname>dont_fork</varname> variable.
|
|
|
- <varname>dont_fork</varname> is a global variable defined in <filename moreinfo="none">main.c</filename>.
|
|
|
- We will describe both variants separately.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="dont-fork-set">
|
|
|
- <title><varname>dont_fork</varname> variable is set (not zero)</title>
|
|
|
- <para>
|
|
|
- If <varname>dont_fork</varname> variable is set, the server will be operating in special mode.
|
|
|
- There will be only one process processing incoming requests. This is very slow and was intended mainly
|
|
|
- for debugging purposes. The main process will be processing all incoming requests itself.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The server still needs additional children:
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- One child is for the timer subsystem, the child will be processing timers independently of
|
|
|
- the main process.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <acronym>FIFO</acronym> server will spawn another child if enabled. The child will be
|
|
|
- processing all commands coming through the fifo interface.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>If <acronym>SNMP</acronym> support was enabled, another child will be created.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <para>
|
|
|
- The following initialization will be performed in dont fork mode.
|
|
|
- (look into function <function moreinfo="none">main_loop</function> in file
|
|
|
- <filename moreinfo="none">main.c</filename>.
|
|
|
- </para>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>Another child will be forked for the timer subsystem.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Initialize the <acronym>FIFO</acronym> server if enabled, this will fork another child.
|
|
|
- For more info about the <acronym>FIFO</acronym> server,
|
|
|
- see section The <acronym>FIFO</acronym> server.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Call <function moreinfo="none">init_child(0).</function>
|
|
|
- The function performs per-child specific initialization of all loaded modules.
|
|
|
- A module can be initialized though <function moreinfo="none">mod_init</function> function.
|
|
|
- The function is called <emphasis>BEFORE</emphasis> the server forks and thus is common for all
|
|
|
- children.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is anything, that needs to be initialized in every child separately (for example
|
|
|
- if each child needs to open its own file descriptor), it cannot be done in
|
|
|
- <function>mod_init</function>.
|
|
|
- To make such initialization possible, a module can export another initialization function
|
|
|
- called <function moreinfo="none">init_child</function>. The function will be called in
|
|
|
- all children <emphasis>AFTER</emphasis> fork of the server.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- And since we are in <quote>dont fork</quote> mode and there will no children processing
|
|
|
- requests (remember the main process will be processing all requests), the
|
|
|
- <function moreinfo="none">init_child</function> wouldn't be called.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- That would be bad, because <function moreinfo="none">child_init</function> might do some
|
|
|
- initialization that must be done otherwise modules might not work properly.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- To make sure that module initialization is complete we will call
|
|
|
- <function moreinfo="none">init_child</function> here for the main process even if we
|
|
|
- are not going to fork.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- <para>
|
|
|
- That's it. Everything has been initialized properly and as the last step we will call
|
|
|
- <function moreinfo="none">udp_rcv_loop</function> which is the main loop function. The function
|
|
|
- will be described later.
|
|
|
- </para>
|
|
|
- </section> <!-- dont-fork-set -->
|
|
|
-
|
|
|
- <section id="dont-fork-not-set">
|
|
|
- <title><varname>dont_fork</varname> is not set (zero)</title>
|
|
|
- <para>
|
|
|
- <varname>dont_fork</varname> is not set. That means that the server will fork children and the children
|
|
|
- will be processing incoming requests. How many children will be created depends on
|
|
|
- the configuration (<varname>children</varname> variable). The main process will be sleeping and
|
|
|
- handling signals only.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- The main process will then initialize the <acronym>FIFO</acronym> server. The <acronym>FIFO</acronym> server
|
|
|
- needs another child to handle communication over <acronym>FIFO</acronym> and thus another child will be
|
|
|
- created. The <acronym>FIFO</acronym> server will be described in more detail later.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- Then the main process will perform another fork for the timer attendant. The child will
|
|
|
- take care of timer lists and execute specified function when a timer hits.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The main process is now completely initialized, it will sleep in <function moreinfo="none">pause</function>
|
|
|
- function until a signal comes and call <function moreinfo="none">handle_sigs</function> when such
|
|
|
- condition occurs.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- The following initialization will be performed by each child separately:
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each child executes <function moreinfo="none">init_child</function> function. The function
|
|
|
- will sequentially call <function moreinfo="none">child_init</function> functions of all loaded modules.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Because the function is called in each child separately, it can initialize per-child
|
|
|
- specific data. For example if a module needs to communicate with database, it must open
|
|
|
- a database connection. If the connection would be opened in <function moreinfo="none">mod_init</function>
|
|
|
- function, all the children would share the same connection and locking would be necessary
|
|
|
- to avoid conflicts. On the other hand if the connection was opened in
|
|
|
- <function moreinfo="none">child_init</function> function, each child will have its own
|
|
|
- connection and concurrency conflicts will be handled by the database server.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- And last, but not least, each child executes <function moreinfo="none">udp_rcv_loop</function> function
|
|
|
- which contains the main loop logic.
|
|
|
- </para>
|
|
|
-
|
|
|
- </section> <!-- dont-fork-not-set -->
|
|
|
- </section> <!-- forking -->
|
|
|
- </chapter> <!-- server-startup -->
|
|
|
-
|
|
|
- <chapter id="main-loop">
|
|
|
- <title>Main Loop</title>
|
|
|
- <para>
|
|
|
- Upon startup, all children execute <function moreinfo="none">recvfrom</function> function. The process will
|
|
|
- enter the kernel mode. When there is no data to be processed at the moment, the kernel will put the process on
|
|
|
- list of processes waiting for data and the process will be put asleep.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When data to be processed was received, the first process on the list will be removed from the list and woken
|
|
|
- up. After the process finished processing of the data, it will call <function moreinfo="none">recvfrom</function>
|
|
|
- again and will be put by the kernel at the end of the list.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When next data arrives, the first process on the list will be removed, processes the data and will be put on the
|
|
|
- end of the list again. And so on...
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- The main loop logic can be found in function <function moreinfo="none">udp_rcv_loop</function> in file
|
|
|
- <filename moreinfo="none">udp_server.c</filename>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The message is received using <function moreinfo="none">recvfrom</function> function. The received data is
|
|
|
- stored in buffer and zero terminated.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If configured so, basic sanity checks over the received message will be performed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The message is then processed by <function moreinfo="none">receive_msg</function> function and
|
|
|
- <function moreinfo="none">recvfrom</function> is called again.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="recv-message">
|
|
|
- <title><function moreinfo="none">receive_msg</function> Function</title>
|
|
|
- <para>
|
|
|
- The function can be found in <filename moreinfo="none">receive.c</filename> file.
|
|
|
- </para>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- In the server, a request or response is represented by <structname>sip_msg</structname>
|
|
|
- structure. The structure is allocated in this function. The original message is stored in
|
|
|
- <structfield>buf</structfield>
|
|
|
- attribute of the structure and is zero terminated. Then, another copy of the received message will be
|
|
|
- created and the copy will be stored in <structfield>orig</structfield> field. The original copy will be not
|
|
|
- modified during the server operation. All changes will be made to the copy in <structfield>buf</structfield>
|
|
|
- field. The second copy of the message will be removed in the future.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- The message will be parsed (function <function moreinfo="none">parse_msg</function>). We don't
|
|
|
- need the whole message header to be parsed at this stage. Only the first line and first Via
|
|
|
- header need to be parsed. The server needs to know if the message is request or response - hence
|
|
|
- the first line. The server also needs the first Via to be able to add its own Via - hence
|
|
|
- the first Via. Nothing else will be parsed at the moment - this saves time. (Message parser
|
|
|
- as well as <structname>sip_msg</structname> structure will be described later).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- A module may register callbacks. Each callback have associated an event, that
|
|
|
- will trigger the callback. One such callback is <emphasis>pre-script</emphasis> callback. Such
|
|
|
- callback will be called immediately before the routing part of the config file will be executed.
|
|
|
- If there are such callbacks registered, they will be executed now.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- As the next step we will determine type of the message. If the message being processed is a REQUEST
|
|
|
- then basic sanity checks will be performed (make sure that there is the first Via and parsing was
|
|
|
- successful) and the message will be passed to routing engine.
|
|
|
- The routing engine is one of the most complicated parts of the server and will be in detail
|
|
|
- described in chapter <link linkend="routing-engine">The Routing Engine</link>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If the message is a RESPONSE, it will be simply forwarded to its destination.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- After all, <emphasis>post-script</emphasis> callbacks will be executed if any and the
|
|
|
- structure representing the message will be released.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Processing of the message is done now and the process is ready for another
|
|
|
- <acronym>SIP</acronym> message.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- recv-message -->
|
|
|
- </chapter> <!-- main-loop -->
|
|
|
-
|
|
|
- <chapter id="server-shutdown">
|
|
|
- <title>The Server Shutdown</title>
|
|
|
- <para>
|
|
|
- The server shutdown can be triggered by sending a signal to the server. The server will behave differently upon
|
|
|
- receiving various types of signals, here is a brief summary:
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>SIGINT, SIGPIPE, SIGTERM, SIGCHLD</emphasis> will terminate the server.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>SIGUSR1</emphasis> will print statistics and let the server continue.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>SIGHUP, SIGUSR2</emphasis> will be ignored.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <para>
|
|
|
- There is only one common signal handler for all signals - function <function moreinfo="none">sig_usr</function>
|
|
|
- in file <filename moreinfo="none">main.c</filename>.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- In normal mode of operation (<varname>dont_fork</varname> variable is not set), the main server is not processing any
|
|
|
- requests, it calls <function moreinfo="none">pause</function> function and will be waiting for signals only. What
|
|
|
- happens when a signal arrives is shown in the previous paragraph.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When in normal mode (<varname>dont_fork</varname> is not set), the signal handler of the main process will
|
|
|
- only store number of the signal received.
|
|
|
- All the processing logic will be executed by the main process outside the signal handler (function
|
|
|
- <function moreinfo="none">handle_sigs</function>) The function will be called immediately after the signal
|
|
|
- handler finish. The main
|
|
|
- process usually does some cleanup and running such things outside the signal handler is much
|
|
|
- more safe than doing it from the handler itself. Children only print statistics and exit
|
|
|
- or ignore the signal completely, that is quite safe and can be done directly from the signal handler of
|
|
|
- children.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When <varname>dont_fork</varname> is set, all the cleanup will be done directly from the signal handler,
|
|
|
- because there is only one process - the main process. This is not so safe as the previous case, but this mode
|
|
|
- should be used for debugging only and such shortcoming doesn't harm in that case.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Upon receipt of SIGINT, SIGPIPE or SIGTERM <function moreinfo="none">destroy_modules</function> will be called.
|
|
|
- Each module may register so-called <function moreinfo="none">destroy</function> function if it needs to do some
|
|
|
- cleanup when the server is terminating (flush of cache to disk for example).
|
|
|
- <function moreinfo="none">destroy_modules</function> will call destroy function of all loaded modules.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- If you need to terminate the server and all of its children, the best way how to do it is to send SIGTERM
|
|
|
- to the main process, the main process will in turn send the same signal to its children.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- The main process and its children are in the same process group. Therefore the main process can kill all
|
|
|
- its children simply by sending a signal to pid 0, sending to pid 0 will send the signal to all processes
|
|
|
- in the same process group as the sending process. This is how the main process will terminate all children
|
|
|
- when it is going to shut down.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- If one child exited during normal operation, the whole server will be shut down. This is better than let
|
|
|
- the server continue - a dead child might hold a lock and that could block the whole server, such situation
|
|
|
- cannot be avoided easily. Instead of that it is better to shutdown the whole server and let it restart.
|
|
|
- </para>
|
|
|
- </chapter> <!-- server-shutdown -->
|
|
|
-
|
|
|
- <chapter id="internal-data-struct">
|
|
|
- <title>Internal Data Structures</title>
|
|
|
- <para>
|
|
|
- There are some data structures that are important and widely used in the server. We will describe them
|
|
|
- in detail in this section.
|
|
|
- </para>
|
|
|
-
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- There are many more structures and types defined across the server and modules. We will describe
|
|
|
- only the most important and common data structure here. The rest will be described in other sections
|
|
|
- if needed.
|
|
|
- </para>
|
|
|
- </note>
|
|
|
-
|
|
|
- <section id="str">
|
|
|
- <title>Type <type>str</type></title>
|
|
|
- <para>
|
|
|
- One of our main goals was to make <acronym>SER</acronym> really fast. There are many functions across
|
|
|
- the server that need to work with strings. Usually these functions need to know string length. We wanted
|
|
|
- to avoid using of <function moreinfo="none">strlen</function> because the function is relatively slow. It
|
|
|
- must scan the whole string and find the first occurrence of zero character. To avoid this, we created
|
|
|
- <type>str</type> type. The type has 2 fields, field <structfield>s</structfield> is pointer
|
|
|
- to the beginning of the string and field <structfield>len</structfield> is length of the string. We then
|
|
|
- calculate length of the string only once and later reuse saved value.
|
|
|
- </para>
|
|
|
- <important>
|
|
|
- <para>
|
|
|
- <type>str</type> structure is quite important because it is widely used in
|
|
|
- <acronym>SER</acronym> (most functions accept <type>str</type> instead of <type>char*</type>).
|
|
|
- </para>
|
|
|
- </important>
|
|
|
-
|
|
|
-
|
|
|
- <para><emphasis><type>str</type> Type Declaration</emphasis></para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct _str{
|
|
|
- char* s;
|
|
|
- int len;
|
|
|
-};
|
|
|
-
|
|
|
-typedef struct _str str;
|
|
|
-</programlisting>
|
|
|
-
|
|
|
- <para>
|
|
|
- The declaration can be found in header file <filename moreinfo="none">str.h</filename>.
|
|
|
- </para>
|
|
|
-
|
|
|
- <warning>
|
|
|
- <para>
|
|
|
- Because we store string lengths, there is no need to zero terminate them. Some strings in the
|
|
|
- server are still zero terminated, some are not. Be careful when using functions like
|
|
|
- <function moreinfo="none">snprintf</function> that rely on the ending zero. You can print
|
|
|
- variable of type <type>str</type> this way:
|
|
|
- <programlisting format="linespecific">printf("%.*s", mystring->len, mystring->s);</programlisting>
|
|
|
- That ensures that the string will be printed correctly even if there is no zero character at
|
|
|
- the end.
|
|
|
- </para>
|
|
|
- </warning>
|
|
|
- </section> <!-- str -->
|
|
|
-
|
|
|
- <section id="hdr-field">
|
|
|
- <title>Structure <structname>hdr_field</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents a header field of a <acronym>SIP</acronym> message. A header field
|
|
|
- consist of <emphasis>name</emphasis> and <emphasis>body</emphasis> separated by a double colon.
|
|
|
- For example: <quote>Server: SIP Express Router\r\n</quote> is one header field. <quote>Server</quote>
|
|
|
- is header field name and <quote>SIP Express Router\r\n</quote> is header field body.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The structure is defined in file <filename moreinfo="none">hf.h</filename> under
|
|
|
- <filename moreinfo="none">parser</filename> subdirectory.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Structure Declaration</emphasis>
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct hdr_field {
|
|
|
- int type; /* Header field type */
|
|
|
- str name; /* Header field name */
|
|
|
- str body; /* Header field body */
|
|
|
- void* parsed; /* Parsed data structures */
|
|
|
- struct hdr_field* next; /* Next header field in the list */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- <emphasis>Field Description:</emphasis>
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>type</structfield> - Type of the header field, the following header field
|
|
|
- types are defined (and recognized by the parser):
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- HDR_VIA1, HDR_VIA2, HDR_TO, HDR_FROM, HDR_CSEQ, HDR_CALLID, HDR_CONTACT, HDR_MAXFORWARDS,
|
|
|
- HDR_ROUTE, HDR_RECORDROUTE, HDR_CONTENTTYPE, HDR_CONTENTLENGTH, HDR_AUTHORIZATION,
|
|
|
- HDR_EXPIRES, HDR_PROXYAUTH, HDR_WWWAUTH, HDR_SUPPORTED, HDR_REQUIRE, HDR_PROXYREQUIRE,
|
|
|
- HDR_UNSUPPORTED, HDR_ALLOW, HDR_EVENT, HDR_OTHER.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Their meaning is self explanatory. HDR_OTHER marks header field not recognized by the parser.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>name</structfield> - Name of the header field (the part before colon)
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>body</structfield> - body of the header field (the part after colon)
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>parsed</structfield> - Each header field body can be further parsed. The field
|
|
|
- contains pointer to parsed structure if the header field was parsed already. The pointer is
|
|
|
- of type <type>void*</type> because it can point to different types of structure depending on
|
|
|
- the header field type.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>next</structfield> - Pointer to the next header field in linked list.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- hdr-field -->
|
|
|
-
|
|
|
- <section id="sip-uri">
|
|
|
- <title>Structure <structname>sip_uri</structname></title>
|
|
|
- <para>This structure represents parsed <acronym>SIP</acronym> <acronym>URI</acronym>.</para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct sip_uri {
|
|
|
- str user; /* Username */
|
|
|
- str passwd; /* Password */
|
|
|
- str host; /* Host name */
|
|
|
- str port; /* Port number */
|
|
|
- str params; /* Parameters */
|
|
|
- str headers;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para><emphasis>Field Description:</emphasis></para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>user</structfield> - Username if found in the <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>passwd</structfield> - Password if found in the <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>host</structfield> - Hostname of the <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>params</structfield> - Parameters of the <acronym>URI</acronym> if any.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>headers</structfield> - See the <acronym>SIP</acronym> <acronym>RFC</acronym>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- sip-uri -->
|
|
|
-
|
|
|
- <section id="via-body">
|
|
|
- <title>Structure <structname>via_body</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents parsed Via header field. See file <filename moreinfo="none">parse_via.h</filename>
|
|
|
- under <filename moreinfo="none">parser</filename> subdirectory for more details.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct via_body {
|
|
|
- int error;
|
|
|
- str hdr; /* Contains "Via" or "v" */
|
|
|
- str name;
|
|
|
- str version;
|
|
|
- str transport;
|
|
|
- str host;
|
|
|
- int port;
|
|
|
- str port_str;
|
|
|
- str params;
|
|
|
- str comment;
|
|
|
- int bsize; /* body size, not including hdr */
|
|
|
- struct via_param* param_lst; /* list of parameters*/
|
|
|
- struct via_param* last_param; /*last via parameter, internal use*/
|
|
|
-
|
|
|
- /* shortcuts to "important" params*/
|
|
|
- struct via_param* branch;
|
|
|
- struct via_param* received;
|
|
|
-
|
|
|
- struct via_body* next; /* pointer to next via body string if
|
|
|
- compact via or null */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para><emphasis>Field Description:</emphasis></para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>error</structfield> - The field contains error code when the parser was unable
|
|
|
- to parse the header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>hdr</structfield>- Header field name, it can be <quote>Via</quote> or <quote>v</quote>
|
|
|
- in this case.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>name</structfield> - Protocol name (<quote>SIP</quote> in this case).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>version</structfield> - Protocol version (for example <quote>2.0</quote>).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>transport</structfield> - Transport protocol name (<quote>TCP</quote>, <quote>UDP</quote>
|
|
|
- and so on).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>host</structfield> - Hostname or IP address contained in the Via header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>port</structfield> - Port number as integer.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>port_str</structfield> - Port number as string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>params</structfield> - Unparsed parameters (as one string containing all the parameters).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>comment</structfield> - Comment.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>bsize</structfield> - Size of the body (not including hdr).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_lst</structfield> - Linked list of all parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>last_param</structfield> - Last parameter in the list.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>branch</structfield> - Branch parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>received</structfield> - Received parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>next</structfield> - If the Via is in compact form (more Vias in the same header
|
|
|
- field), this field contains pointer to the next Via.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- via-body -->
|
|
|
-
|
|
|
- <section id="ip-addr">
|
|
|
- <title>Structure <structname>ip_addr</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents <acronym>IPv4</acronym> or <acronym>IPv6</acronym> address. It is defined in
|
|
|
- <filename moreinfo="none">ip_addr.h</filename>.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct ip_addr{
|
|
|
- unsigned int af; /* address family: AF_INET6 or AF_INET */
|
|
|
- unsigned int len; /* address len, 16 or 4 */
|
|
|
-
|
|
|
- /* 64 bits aligned address */
|
|
|
- union {
|
|
|
- unsigned int addr32[4];
|
|
|
- unsigned short addr16[8];
|
|
|
- unsigned char addr[16];
|
|
|
- }u;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- </section> <!-- ip-addr -->
|
|
|
-
|
|
|
- <section id="lump">
|
|
|
- <title>Structure <structname>lump</structname></title>
|
|
|
- <para>
|
|
|
- The structure describes modifications that should be made to the message before
|
|
|
- the message will be sent.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The structure will be described in more detail later in chapter
|
|
|
- SIP Message Modifications.
|
|
|
- </para>
|
|
|
- </section> <!-- lump -->
|
|
|
-
|
|
|
- <section id="lump-rpl">
|
|
|
- <title>Structure <structname>lump_rpl</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents text that should be added to reply. List of such data is
|
|
|
- kept in the request and processed when the request is being turned into reply.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The structure will be described in more detail later in chapter
|
|
|
- SIP Message Modifications.
|
|
|
- </para>
|
|
|
- </section> <!-- lump-rpl -->
|
|
|
-
|
|
|
- <section id="msg-start">
|
|
|
- <title>Structure <structname>msg_start</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents the first line of a <acronym>SIP</acronym> request or response.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The structure is defined in file <filename moreinfo="none">parse_fline.h</filename> under
|
|
|
- <filename moreinfo="none">parser</filename> subdirectory.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- <emphasis>Structure Declaration</emphasis>
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct msg_start {
|
|
|
- int type; /* Type of the Message - Request/Response */
|
|
|
- union {
|
|
|
- struct {
|
|
|
- str method; /* Method string */
|
|
|
- str uri; /* Request URI */
|
|
|
- str version; /* SIP version */
|
|
|
- int method_value; /* Parsed method */
|
|
|
- } request;
|
|
|
- struct {
|
|
|
- str version; /* SIP version */
|
|
|
- str status; /* Reply status */
|
|
|
- str reason; /* Reply reason phrase */
|
|
|
- unsigned int statuscode; /* Status code */
|
|
|
- } reply;
|
|
|
- }u;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
-
|
|
|
- <para>
|
|
|
- <emphasis>Description of Request Related Fields:</emphasis>
|
|
|
- </para>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>type</structfield> - Type of the message - REQUEST or RESPONSE.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>method</structfield> - Name of method (same as in the message).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>uri</structfield> - Request <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>version</structfield> - Version string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>method_value</structfield> - Parsed method. Field method which is of
|
|
|
- type <type>str</type> will be converted to integer and stored here. This is good for comparison,
|
|
|
- integer comparison is much faster then string comparison.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <para>
|
|
|
- <emphasis>Description of Response Related Fields:</emphasis>
|
|
|
- </para>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>version</structfield> - Version string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>status</structfield> - Response status code as string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>reason</structfield> - Response reason string as in the message.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>statuscode</structfield> - Response status code converted to integer.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- </section> <!-- msg-start -->
|
|
|
-
|
|
|
- <section id="sip-msg">
|
|
|
- <title>Structure <structname>sip_msg</structname></title>
|
|
|
- <para>
|
|
|
- This is the most important structure in the whole server. This structure represents
|
|
|
- a <acronym>SIP</acronym> message. When a message is received, it is immediately converted
|
|
|
- into this structure and all operations are performed over the structure. After the server
|
|
|
- finished processing, this structure is converted back to character array
|
|
|
- buffer and the buffer is sent out.
|
|
|
- </para>
|
|
|
- <para><emphasis>Structure Declaration:</emphasis></para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct sip_msg {
|
|
|
- unsigned int id; /* message id, unique/process*/
|
|
|
- struct msg_start first_line; /* Message first line */
|
|
|
- struct via_body* via1; /* The first via */
|
|
|
- struct via_body* via2; /* The second via */
|
|
|
- struct hdr_field* headers; /* All the parsed headers*/
|
|
|
- struct hdr_field* last_header; /* Pointer to the last parsed header*/
|
|
|
- int parsed_flag; /* Already parsed header field types */
|
|
|
-
|
|
|
- /* Via, To, CSeq, Call-Id, From, end of header*/
|
|
|
- /* first occurrence of it; subsequent occurrences
|
|
|
- * saved in 'headers'
|
|
|
- */
|
|
|
-
|
|
|
- struct hdr_field* h_via1;
|
|
|
- struct hdr_field* h_via2;
|
|
|
- struct hdr_field* callid;
|
|
|
- struct hdr_field* to;
|
|
|
- struct hdr_field* cseq;
|
|
|
- struct hdr_field* from;
|
|
|
- struct hdr_field* contact;
|
|
|
- struct hdr_field* maxforwards;
|
|
|
- struct hdr_field* route;
|
|
|
- struct hdr_field* record_route;
|
|
|
- struct hdr_field* content_type;
|
|
|
- struct hdr_field* content_length;
|
|
|
- struct hdr_field* authorization;
|
|
|
- struct hdr_field* expires;
|
|
|
- struct hdr_field* proxy_auth;
|
|
|
- struct hdr_field* www_auth;
|
|
|
- struct hdr_field* supported;
|
|
|
- struct hdr_field* require;
|
|
|
- struct hdr_field* proxy_require;
|
|
|
- struct hdr_field* unsupported;
|
|
|
- struct hdr_field* allow;
|
|
|
- struct hdr_field* event;
|
|
|
-
|
|
|
- char* eoh; /* pointer to the end of header (if found) or null */
|
|
|
- char* unparsed; /* here we stopped parsing*/
|
|
|
-
|
|
|
- struct ip_addr src_ip;
|
|
|
- struct ip_addr dst_ip;
|
|
|
-
|
|
|
- char* orig; /* original message copy */
|
|
|
- char* buf; /* scratch pad, holds a modified message,
|
|
|
- * via, etc. point into it
|
|
|
- */
|
|
|
- unsigned int len; /* message len (orig) */
|
|
|
-
|
|
|
- /* modifications */
|
|
|
-
|
|
|
- str new_uri; /* changed first line uri*/
|
|
|
- int parsed_uri_ok; /* 1 if parsed_uri is valid, 0 if not */
|
|
|
- struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/
|
|
|
-
|
|
|
- struct lump* add_rm; /* used for all the forwarded
|
|
|
- * requests */
|
|
|
- struct lump* repl_add_rm; /* used for all the forwarded replies */
|
|
|
- struct lump_rpl *reply_lump; /* only for locally generated replies !!!*/
|
|
|
-
|
|
|
- char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
|
|
|
- int add_to_branch_len;
|
|
|
-
|
|
|
- /* index to TM hash table; stored in core to avoid unnecessary calcs */
|
|
|
- unsigned int hash_index;
|
|
|
-
|
|
|
- /* allows to set various flags on the message; may be used for
|
|
|
- * simple inter-module communication or remembering processing state
|
|
|
- * reached
|
|
|
- */
|
|
|
- flag_t flags;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- <emphasis>Field Description:</emphasis>
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>id</structfield> - Unique ID of the message within a process context.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>first_line</structfield> - Parsed first line of the message.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>via1</structfield> - The first Via - parsed.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>via2</structfield> - The second Via - parsed.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>headers</structfield> - Linked list of all parsed headers.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>last_header</structfield> - Pointer to the last parsed header (parsing is incremental,
|
|
|
- that means that the parser will stop if all requested headers were found and next time it will
|
|
|
- continue at the place where it stopped previously. Therefore this field will not point to the
|
|
|
- last header of the message if the whole message hasn't been parsed yet).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>parsed_flag</structfield> - Already parsed header field types (bitwise OR).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <para>
|
|
|
- The following fields are set to zero if the corresponding header field was not found in the
|
|
|
- message or hasn't been parsed yet. (These fields are called hooks - they always point to the first
|
|
|
- occurrence if there is more than one header field of the same type).
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>h_via1</structfield> - Pointer to the first Via header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>h_via2</structfield> - Pointer to the second Via header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>callid</structfield> - Pointer to the first Call-ID header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>to</structfield> - Pointer to the first To header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>cseq</structfield> - Pointer to the first CSeq header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>from</structfield> - Pointer to the first From header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>contact</structfield> - Pointer to the first Contact header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>maxforwards</structfield> - Pointer to the first Max-Forwards header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>route</structfield> - Pointer to the first Route header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>record_route</structfield> - Pointer to the first Record-Route header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>content_type</structfield> - Pointer to the first Content-Type header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>content_length</structfield> - Pointer to the first Content-Length header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>authorization</structfield> - Pointer to the first Authorization header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>expires</structfield> - Pointer to the first Expires header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>proxy_auth</structfield> - Pointer to the first Proxy-Authorize header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>www_auth</structfield> - Pointer to the first WWW-Authorize header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>supported</structfield> - Pointer to the first Supported header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>require</structfield> - Pointer to the first Require header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>proxy_require</structfield> - Pointer to the first Proxy-Require header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>unsupported</structfield> - Pointer to the first Unsupported header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>allow</structfield> - Pointer to the first Allow header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>event</structfield> - Pointer to the first Event header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <para>
|
|
|
- The following fields are mostly used internally by the server and should be modified through dedicated
|
|
|
- functions only.
|
|
|
- </para>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>eoh</structfield> - Pointer to the End of Header or null if not found yet (the field
|
|
|
- will be set if and only if the whole message was parsed already).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>unparsed</structfield> - Pointer to the first unparsed character in the message.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>src_ip</structfield> - Sender's <acronym>IP</acronym> address.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>dst_ip</structfield> - Destination's <acronym>IP</acronym> address.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>orig</structfield> - Original (unmodified) message copy, this field will hold
|
|
|
- unmodified copy of the message during the whole message lifetime.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>buf</structfield> - Message scratch-pad (modified copy of the message) - All modifications
|
|
|
- made to the message will be done here.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>len</structfield> - Length of the message (unmodified).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>new_uri</structfield> - New Request-URI to be used when forwarding the message.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>parsed_uri_ok</structfield> - 1 if <structfield>parsed_uri</structfield> is
|
|
|
- valid, 0 if not.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>parsed_uri</structfield> - The original parsed Request <acronym>URI</acronym>, sometimes
|
|
|
- it might be necessary to revert changes made to the Request <acronym>URI</acronym> and therefore we
|
|
|
- store the original <acronym>URI</acronym> here.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>add_rm</structfield> - Linked list describing all modifications that will be made to
|
|
|
- <emphasis>REQUEST</emphasis> before it will be forwarded. The list will be processed when the request
|
|
|
- is being converted to character array (i.e. immediately before the request will be send out).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>repl_add_rm</structfield> - Linked list describing all modifications
|
|
|
- that will be made to
|
|
|
- <emphasis>REPLY</emphasis> before it will be forwarded. the list will be processed when the reply
|
|
|
- is being converted to character array (i.e. immediately before the request will be send out).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>reply_lump</structfield> - This is list of data chunks that should be appended to
|
|
|
- locally generated reply, i.e. when the server is generating local reply out of the request. A local
|
|
|
- reply is reply generated by the server. For example, when processing of a request fails for some
|
|
|
- reason, the server might generate an error reply and send it back to sender.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>add_to_branch_s</structfield> - String to be appended to branch parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>add_to_branch_len</structfield> - Length of the string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>hash_index</structfield> - Index to a hash table in TM module.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>flags</structfield> - Allows to set various flags on the message. May be used
|
|
|
- for simple inter-module communication or remembering processing state reached.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- sip_msg -->
|
|
|
- </chapter> <!-- internal-data-struct -->
|
|
|
-
|
|
|
- <chapter id="routing-engine">
|
|
|
- <title>The Routing Engine</title>
|
|
|
- <para>
|
|
|
- In a previous section we discussed how routing part of a config file gets translated into binary
|
|
|
- representation. In this section, we will discuss how the binary representation is used during
|
|
|
- message processing.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Upon a <acronym>SIP</acronym> message receipt, the server performs some basic sanity checks and converts
|
|
|
- the message into <structname>sip_msg</structname> structure. After that the Routing Engine will start
|
|
|
- processing the message.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The routing engine can be found in file <filename moreinfo="none">action.c</filename>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The main function is <function moreinfo="none">run_actions.</function> The
|
|
|
- function accepts two parameters. The first parameter is list of actions to
|
|
|
- be processed (Remember, the config file gets translated into array of linked
|
|
|
- lists. Each linked list in the array represents one "route" part of the config
|
|
|
- file). The second parameter is <structname>sip_msg</structname> structure
|
|
|
- representing the message to be processed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Upon a receipt of a request, the linked list representing the main route
|
|
|
- part will be processed so the first parameter will be <varname>rlist[0]</varname>. (The linked
|
|
|
- list of main route part is always at index 0).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function will then sequentially call
|
|
|
- <function moreinfo="none">do_action</function> function for each element
|
|
|
- of the linked list. Return value of the function is important. If the function
|
|
|
- returns 0, processing of the list will be stopped. By returning 0 a command
|
|
|
- can indicate that processing of the message should be stopped and the message will be dropped.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Modules may export so-called <emphasis>on_break handlers</emphasis>.
|
|
|
- <emphasis>on_break</emphasis> handler is a function, that will be called when
|
|
|
- processing of the linked-list is interrupted (ret == 0). All such handlers
|
|
|
- will be called when processing of the linked-list is finished and ret == 0.
|
|
|
- </para>
|
|
|
- <section id="do-action">
|
|
|
- <title><function moreinfo="none">do_action</function> Function</title>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">do_action</function> function is core of the
|
|
|
- routing engine. There is a big <function moreinfo="none">switch</function>
|
|
|
- statement. Each case of the statements is one command handled by the
|
|
|
- server core itself.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The following commands are handled by the <acronym>SER</acronym> core
|
|
|
- itself:
|
|
|
- <function moreinfo="none">drop</function>,
|
|
|
- <function moreinfo="none">forward</function>,
|
|
|
- <function moreinfo="none">send</function>,
|
|
|
- <function moreinfo="none">log</function>,
|
|
|
- <function moreinfo="none">append_branch</function>,
|
|
|
- <function moreinfo="none">len_gt</function>,
|
|
|
- <function moreinfo="none">setflag</function>,
|
|
|
- <function moreinfo="none">resetflag</function>,
|
|
|
- <function moreinfo="none">isflagset</function>,
|
|
|
- <function moreinfo="none">error</function>,
|
|
|
- <function moreinfo="none">route</function>,
|
|
|
- <function moreinfo="none">exec</function>,
|
|
|
- <function moreinfo="none">revert_uri</function>,
|
|
|
- <function moreinfo="none">set_host</function>,
|
|
|
- <function moreinfo="none">set_hostport</function>,
|
|
|
- <function moreinfo="none">set_user</function>,
|
|
|
- <function moreinfo="none">set_userpass</function>,
|
|
|
- <function moreinfo="none">set_port</function>,
|
|
|
- <function moreinfo="none">set_uri</function>,
|
|
|
- <function moreinfo="none">prefix</function>,
|
|
|
- <function moreinfo="none">strip</function>,
|
|
|
- <function moreinfo="none">if</function>,
|
|
|
- <function moreinfo="none">module</function>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each of the commands is represented by a <emphasis>case</emphasis> statement in the switch.
|
|
|
- (For example, if you are interested in implementation of
|
|
|
- <function>drop</function> command,
|
|
|
- look at <quote>case DROP_T:</quote> statement in the function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The respective commands will be described now.
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">drop</function> - This command is very
|
|
|
- simple, it simply returns 0 which will result in abortion of
|
|
|
- processing of the request. No other commands after
|
|
|
- <function moreinfo="none">drop</function> will be executed.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">forward</function> - The function will
|
|
|
- forward the message further. The message will be either forwarded
|
|
|
- to the Request <acronym>URI</acronym> of the message or to
|
|
|
- <acronym>IP</acronym> or host given as parameter.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- In the first case, host in the Request <acronym>URI</acronym>
|
|
|
- must be converted into corresponding <acronym>IP</acronym> address.
|
|
|
- Function <function moreinfo="none">mk_proxy</function> converts
|
|
|
- hostname to corresponding <acronym>IP</acronym> address.
|
|
|
- The message is then sent out using
|
|
|
- <function moreinfo="none">forward_request</function> function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- In the second case, hostname was converted to <acronym>IP</acronym>
|
|
|
- address in fixup i.e. immediately after the config file was compiled
|
|
|
- into its binary representation. The first parameter is pointer to
|
|
|
- <structname>proxy</structname> structure created in the fixup and
|
|
|
- therefore we only need to call
|
|
|
- <function moreinfo="none">forward_request</function> here to
|
|
|
- forward the message further.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">send</function> - This functions sends
|
|
|
- the message to a third-party host. The message will be sent out
|
|
|
- as is - i.e. without Request <acronym>URI</acronym> and Via
|
|
|
- altering.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Hostname or <acronym>IP</acronym> address of the third-party host
|
|
|
- is specified as a parameter of the function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The message will be sent out using
|
|
|
- <function moreinfo="none">udp_send</function> directly.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">log</function> - The message given as
|
|
|
- a parameter will be logged using system logger. It can be either
|
|
|
- <command moreinfo="none">syslog</command> or <varname>stderr</varname>
|
|
|
- (depends on configuration). The message is logged
|
|
|
- using <function moreinfo="none">LOG</function> which is a macro
|
|
|
- defined in <filename moreinfo="none">dprint.h</filename> header
|
|
|
- file.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">append_branch</function> - Append a new
|
|
|
- <acronym>URI</acronym> for forking.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- More than one destinations may be associated with a single
|
|
|
- <acronym>SIP</acronym> request. If the server was configured so,
|
|
|
- it will use all the destinations and fork the request.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The server keeps an array of all destinations, that should be
|
|
|
- used when forking. The array and related functions can be found
|
|
|
- in file <filename moreinfo="none">dset.c</filename>. There is
|
|
|
- function <function moreinfo="none">append_branch</function> which adds a new destination to the set.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- This command simply calls
|
|
|
- <function moreinfo="none">append_branch</function> function and
|
|
|
- adds a new destination to the destination set.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">len_gt</function> - The command accepts
|
|
|
- one number as a parameter. It then compares the number with length
|
|
|
- of the message. If the message length is greater or equal then
|
|
|
- the number then 1 will be returned otherwise the function returns -1.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">setflag</function> - Sets a flag in the
|
|
|
- message. The command simply
|
|
|
- calls <function moreinfo="none">setflags</function> function that
|
|
|
- will set the flag. Fore more information see file
|
|
|
- <filename moreinfo="none">flag.c</filename>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">resetflag</function> - Same as command
|
|
|
- <function moreinfo="none">setflag</function> - only resetflag
|
|
|
- will be called instead of setflag.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">isflagset</function> - Test if the flag
|
|
|
- is set or not.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">error</function> - Log a message with
|
|
|
- NOTICE log level.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">route</function> - Execute another
|
|
|
- route statement.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- As we have mentioned already, there can be more that one route
|
|
|
- statement in the config file. One of them is main (without
|
|
|
- number), the other are additional. This command makes it possible
|
|
|
- to execute an additional route statement.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The command accepts one parameter which is route statement number.
|
|
|
- First sanity checks over the parameter will be performed. If
|
|
|
- the checks passed, function
|
|
|
- <function moreinfo="none">run_actions</function> will be called.
|
|
|
- The function accepts two parameters. The first one is linked list
|
|
|
- to execute, the second one is <structname>sip_msg</structname>
|
|
|
- structure representing the message to be processed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- As you might remember, each route statement was compiled into
|
|
|
- linked list of commands to be executed and head of the linked
|
|
|
- list was stored in <varname>rlist</varname> array. For example, head of linked list
|
|
|
- representing route statement with number 4 will be stored at
|
|
|
- position 4 in the array (position 0 is reserved for the main
|
|
|
- route statement).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- So the command will simply call
|
|
|
- <function moreinfo="none">run_actions(rlist[a->p1.number], msg)</function>
|
|
|
- and that will execute route statement with number given as parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">exec</function> - Execute a shell command.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The command accepts one parameter of type <type>char*</type>. The string given as
|
|
|
- parameter will be passed to <function moreinfo="none">system</function>
|
|
|
- function which will in turn execute
|
|
|
- <function moreinfo="none">/bin/sh -c <string></function>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">revert_uri</function> - Revert changes made to
|
|
|
- the Request <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a new <acronym>URI</acronym> stored in
|
|
|
- <structfield>new_uri</structfield> of <structname>sip_msg</structname> structure,
|
|
|
- it will be freed. The original Request <acronym>URI</acronym> will be used
|
|
|
- when forwarding the message.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a valid <acronym>URI</acronym> in
|
|
|
- <structfield>parsed_uri</structfield> field of <structname>sip_msg</structname>
|
|
|
- structure (indicated by <structfield>parsed_uri_ok</structfield> field), it
|
|
|
- will be freed too.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">set_host</function> - Change hostname of Request
|
|
|
- <acronym>URI</acronym> to value given as parameter.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">set_hostport</function> - change hostname and port
|
|
|
- of Request <acronym>URI</acronym> to value given as string parameter.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">set_user</function> - Set username part of Request
|
|
|
- <acronym>URI</acronym> to string given as parameter.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">set_userpass</function> - Set username and password
|
|
|
- part of Request <acronym>URI</acronym> to string given as parameter.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">set_port</function> - Set port of Request
|
|
|
- <acronym>URI</acronym> to value given as parameter.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">set_uri</function> - Set a new Request
|
|
|
- <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield> field,
|
|
|
- it will be freed. If there is a valid <acronym>URI</acronym> in
|
|
|
- <structfield>parsed_uri</structfield> field, it will be freed too.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Then <acronym>URI</acronym> given as parameter will be stored in
|
|
|
- <structfield>new_uri</structfield> field. (If <structfield>new_uri</structfield>
|
|
|
- contains a <acronym>URI</acronym> it will be used instead of Request
|
|
|
- <acronym>URI</acronym> when forwarding the message).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">prefix</function> - Set the parameter as username
|
|
|
- prefix.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The string will be put immediately after <quote>sip:</quote> part of the
|
|
|
- Request <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">strip</function> - Remove first n characters of
|
|
|
- username in Request <acronym>URI</acronym>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
|
|
|
- field, it will be modified, otherwise the original Request
|
|
|
- <acronym>URI</acronym> will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">if</function> - if Statement.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- There is an expression associated with the command and one or two linked lists of
|
|
|
- commands. The expression is a regular expression compiled into binary form
|
|
|
- in the fixup when the config file was compiled.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The expression will be evaluated now. If the result is > 0, the first linked
|
|
|
- list will be executed using <function moreinfo="none">run_action</function>
|
|
|
- function. The linked list represents command enclosed in curly braces of
|
|
|
- <function moreinfo="none">if</function> command.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Otherwise, if there is the second list, it will be executed in the same way. The
|
|
|
- second list represents commands of <function moreinfo="none">else</function>
|
|
|
- statement.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">module</function> - Execute a function exported by
|
|
|
- a module.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When a command in a route statement is not recognized by the core itself
|
|
|
- (i.e. it is not one of commands handled by the core itself), list of exported
|
|
|
- functions of all loaded modules will be searched for a function with corresponding
|
|
|
- name and number of parameters.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If the function was found, <function moreinfo="none">module</function> command
|
|
|
- (this one) will be created and pointer to the function will be stored in
|
|
|
- <structfield>p1.data</structfield> field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- So, this command will simply call function whose pointer is in
|
|
|
- <structfield>p1.data</structfield> field and will pass 2 parameters to the
|
|
|
- function. If one or both of the parameters were not used, 0 will be passed
|
|
|
- instead.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Return value of the function will be returned as return value of
|
|
|
- <function moreinfo="none">module</function> command.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- This command makes <acronym>SER</acronym> pretty extensible while the core
|
|
|
- itself is still reasonably small and clean. Additional functionality is put
|
|
|
- in modules and loaded only when needed.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- do-action -->
|
|
|
- </chapter> <!-- routing-engine -->
|
|
|
-
|
|
|
-<!--
|
|
|
- <chapter id="memory-management">
|
|
|
- <title>Memory Management</title>
|
|
|
- <para>
|
|
|
- This section should be written by somebody who really knows how it works. Any volunteers ?
|
|
|
- TBD.
|
|
|
- </para>
|
|
|
- </chapter>
|
|
|
--->
|
|
|
-
|
|
|
- <chapter id="msg-parser">
|
|
|
- <title>The Message Parser</title>
|
|
|
- <para>
|
|
|
- In this section we will discuss internals of the <acronym>SIP</acronym> message header
|
|
|
- parser implemented in the server. Message parsing is very important and one of the most
|
|
|
- time consuming operations of a <acronym>SIP</acronym> server. We have been trying to
|
|
|
- make the parser as fast as possible.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- A header field parser can be either in the server core or in a module. By convention,
|
|
|
- parser that is needed by the core itself or is needed by at least two modules will be
|
|
|
- in the core. Parsers contained in modules will be not described in this section.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- There is a <filename moreinfo="none">parser</filename> subdirectory that contains all
|
|
|
- the parsers and related stuff.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The following parsers can be found under <filename moreinfo="none">parser</filename>
|
|
|
- subdirectory:
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="sip-msg-structure">
|
|
|
- <title>Structure of a <acronym>SIP</acronym> Message</title>
|
|
|
- <para>
|
|
|
- A <acronym>SIP</acronym> message consists of message header and optional message body.
|
|
|
- The header is separated from the body with a empty line (containing CRLF only).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Message header consists of the first line and one or more header fields. The first line
|
|
|
- determines type of the message. Header fields provide additional information that is
|
|
|
- needed by clients and servers to be able to process the message.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Each header field consists of header field name and header field body. Header field name
|
|
|
- is delimited from header field body by a colon (<quote>:</quote>). For example,
|
|
|
- <quote>Server: SIP Express Router</quote> - in this case <quote>Server</quote> is
|
|
|
- header field name and <quote>SIP Express Router</quote> is header field body.
|
|
|
- </para>
|
|
|
- </section> <!-- sip-msg-structure -->
|
|
|
-
|
|
|
-
|
|
|
- <section id="parser-organization">
|
|
|
- <title>The Parser Organization</title>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>First Line Parser - Parses the first line of a <acronym>SIP</acronym> message.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Header Name Parser- Parsers Name part of a header field (part before colon).</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>To Header Parser - Parses body of To header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>From Header Parser - Parses body of From header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>CSeq Header Parser - Parses body of CSeq header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Event Header Parser - Parses body of Event header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Expires Header Parser - Parses body of Expires header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Via Header Parser - Parses body of Via header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Contact Header Parser - Parses body of Contact header field.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Digest Parser - Parses digest response.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
-
|
|
|
- <para>
|
|
|
- The server implements what we call <emphasis>incremental parsing</emphasis>. It means that
|
|
|
- a header field will be not parsed unless it is really needed. There is a minimal set of
|
|
|
- header that will be parsed every time. The set includes:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- The first line - the server must know if the message is request or response
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Via header field - Via will be needed for sure. We must add ourself to Via
|
|
|
- list when forwarding the message.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="fline-parser">
|
|
|
- <title>The First Line Parser</title>
|
|
|
- <para>
|
|
|
- Purpose of the parser is to parse the first line of a <acronym>SIP</acronym>
|
|
|
- message. The first line is represented by <structname>msg_start</structname>
|
|
|
- structure define in file <filename moreinfo="none">parse_fline.h</filename>
|
|
|
- under <filename moreinfo="none">parser</filename> subdirectory.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The main function of the first line parser is
|
|
|
- <function moreinfo="none">parse_first_line</function>, the function will fill in
|
|
|
- <structname>msg_start</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Follow inline comments in the function if you want to add support for a new
|
|
|
- message type.
|
|
|
- </para>
|
|
|
- </section> <!-- fline-parser -->
|
|
|
- <section id="hfname-parser">
|
|
|
- <title>The Header Field Name Parser</title>
|
|
|
- <para>
|
|
|
- The purpose of the header field type parser is to recognize type of a header field.
|
|
|
- The following types of header field will be recognized:
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Via, To, From, CSeq, Call-ID, Contact, Max-Forwards, Route, Record-Route,
|
|
|
- Content-Type, Content-Length, Authorization, Expires, Proxy-Authorization,
|
|
|
- WWW-Authorization, supported, Require, Proxy-Require, Unsupported, Allow, Event.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- All other header field types will be marked as HDR_OTHER.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Main function of header name parser is <function moreinfo="none">parse_hname2</function>. The
|
|
|
- function can be found in file <filename moreinfo="none">parse_hname.c</filename>. The function
|
|
|
- accepts pointers to begin and end of a header field and fills in <structname>hdf_field</structname>
|
|
|
- structure. <structfield>name</structfield> field will point to the header field name,
|
|
|
- <structfield>body</structfield> field will point to the header field body and
|
|
|
- <structfield>type</structfield> field will contain type of the header field if known and HDR_OTHER
|
|
|
- if unknown.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser is 32-bit, it means, that it processes 4 characters of header field name at time. 4
|
|
|
- characters of a header field name are converted to an integer and the integer is then compared. This
|
|
|
- is much faster than comparing byte by byte. Because the server is compiled on at least 32-bit architectures,
|
|
|
- such comparison will be compiled into one instruction instead of 4 instructions.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- We did some performance measurement and 32-bit parsing is about 3 times faster for a typical
|
|
|
- <acronym>SIP</acronym> message than corresponding automaton comparing byte by byte. Performance may vary
|
|
|
- depending on the message size, parsed header fields and header fields type. Test showed that it was always
|
|
|
- as fast as corresponding 1-byte comparing automaton.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Since comparison must be case insensitive in case of header field names, it is necessary to convert it
|
|
|
- to lower case first and then compare. Since converting byte by byte would slow down the parser a lot, we
|
|
|
- have implemented a hash table, that can again convert 4 bytes at once. Since set of keys that need to be
|
|
|
- converted to lowercase is known (the set consists of all possible 4-byte parts of all recognized header
|
|
|
- field names) we can pre-calculate size of the hash table to be synonym-less. That will simplify (and speed
|
|
|
- up) the lookup a lot. The hash table must be initialized upon the server startup (function
|
|
|
- <function moreinfo="none">init_hfname_parser</function>).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The header name parser consists of several files, all of them are under
|
|
|
- <filename moreinfo="none">parser</filename> subdirectory. Main file is
|
|
|
- <filename moreinfo="none">parse_hname2.c</filename> - this files contains the parser itself and functions
|
|
|
- used to initialize and lookup the hash table. File <filename moreinfo="none">keys.h</filename> contains
|
|
|
- automatically generated set of macros. Each macro is a group of 4 bytes converted to integer. The macros
|
|
|
- are used for comparison and the hash table initialization. For example, for Max-Forwards header field
|
|
|
- name, the following macros are defined in the file:
|
|
|
- </para>
|
|
|
- <programlisting>
|
|
|
-#define _max__ 0x2d78616d /* "max-" */
|
|
|
-#define _maX__ 0x2d58616d /* "maX-" */
|
|
|
-#define _mAx__ 0x2d78416d /* "mAx-" */
|
|
|
-#define _mAX__ 0x2d58416d /* "mAX-" */
|
|
|
-#define _Max__ 0x2d78614d /* "Max-" */
|
|
|
-#define _MaX__ 0x2d58614d /* "MaX-" */
|
|
|
-#define _MAx__ 0x2d78414d /* "MAx-" */
|
|
|
-#define _MAX__ 0x2d58414d /* "MAX-" */
|
|
|
-
|
|
|
-#define _forw_ 0x77726f66 /* "forw" */
|
|
|
-#define _forW_ 0x57726f66 /* "forW" */
|
|
|
-#define _foRw_ 0x77526f66 /* "foRw" */
|
|
|
-#define _foRW_ 0x57526f66 /* "foRW" */
|
|
|
-#define _fOrw_ 0x77724f66 /* "fOrw" */
|
|
|
-#define _fOrW_ 0x57724f66 /* "fOrW" */
|
|
|
-#define _fORw_ 0x77524f66 /* "fORw" */
|
|
|
-#define _fORW_ 0x57524f66 /* "fORW" */
|
|
|
-#define _Forw_ 0x77726f46 /* "Forw" */
|
|
|
-#define _ForW_ 0x57726f46 /* "ForW" */
|
|
|
-#define _FoRw_ 0x77526f46 /* "FoRw" */
|
|
|
-#define _FoRW_ 0x57526f46 /* "FoRW" */
|
|
|
-#define _FOrw_ 0x77724f46 /* "FOrw" */
|
|
|
-#define _FOrW_ 0x57724f46 /* "FOrW" */
|
|
|
-#define _FORw_ 0x77524f46 /* "FORw" */
|
|
|
-#define _FORW_ 0x57524f46 /* "FORW" */
|
|
|
-
|
|
|
-#define _ards_ 0x73647261 /* "ards" */
|
|
|
-#define _ardS_ 0x53647261 /* "ardS" */
|
|
|
-#define _arDs_ 0x73447261 /* "arDs" */
|
|
|
-#define _arDS_ 0x53447261 /* "arDS" */
|
|
|
-#define _aRds_ 0x73645261 /* "aRds" */
|
|
|
-#define _aRdS_ 0x53645261 /* "aRdS" */
|
|
|
-#define _aRDs_ 0x73445261 /* "aRDs" */
|
|
|
-#define _aRDS_ 0x53445261 /* "aRDS" */
|
|
|
-#define _Ards_ 0x73647241 /* "Ards" */
|
|
|
-#define _ArdS_ 0x53647241 /* "ArdS" */
|
|
|
-#define _ArDs_ 0x73447241 /* "ArDs" */
|
|
|
-#define _ArDS_ 0x53447241 /* "ArDS" */
|
|
|
-#define _ARds_ 0x73645241 /* "ARds" */
|
|
|
-#define _ARdS_ 0x53645241 /* "ARdS" */
|
|
|
-#define _ARDs_ 0x73445241 /* "ARDs" */
|
|
|
-#define _ARDS_ 0x53445241 /* "ARDS" */
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- As you can see, Max-Forwards name was divided into three 4-byte chunks: Max-, Forw, ards. The file
|
|
|
- contains macros for every possible lower and upper case character combination of the chunks. Because
|
|
|
- the name (and therefore chunks) can contain colon (<quote>:</quote>), minus or space and these
|
|
|
- characters are not allowed in macro name, they must be substituted. Colon is substituted by
|
|
|
- <quote>1</quote>, minus is substituted by underscore (<quote>_</quote>) and space is substituted
|
|
|
- by <quote>2</quote>.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- When initializing the hash table, all these macros will be used as keys to the hash table. One of
|
|
|
- each upper and lower case combinations will be used as value. Which one ?
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- There is a convention that each word of a header field name starts with a upper case character. For
|
|
|
- example, most of user agents will send <quote>Max-Forwards</quote>, messages containing some other
|
|
|
- combination of upper and lower case characters (for example: <quote>max-forwards</quote>,
|
|
|
- <quote>MAX-FORWARDS</quote>, <quote>mAX-fORWARDS</quote>) are very rare (but it is possible).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Considering the previous paragraph, we optimized the parser for the most common case. When all header
|
|
|
- fields have upper and lower case characters according to the convention, there is no need to do hash
|
|
|
- table lookups, which is another speed up.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- For example suppose we are trying to figure out if the header field name is Max-Forwards and the
|
|
|
- header field name is formed according to the convention (i.e. <quote>Max-Forwards</quote>):
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Get the first 4 bytes of the header field name (<quote>Max-</quote>), convert it to an
|
|
|
- integer and compare to <quote>_Max__</quote> macro. Comparison succeeded, continue
|
|
|
- with the next step.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Get next 4 bytes of the header field name (<quote>Forw</quote>), convert it to an
|
|
|
- integer and compare to <quote>_Forw_</quote> macro. Comparison succeeded, continue
|
|
|
- with the next step.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Get next 4 bytes of the header field name (<quote>ards</quote>), convert it to an
|
|
|
- integer and compare to <quote>_ards_</quote> macro. Comparison succeeded, continue
|
|
|
- with the next step.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If the following characters are spaces and tabs followed by a colon (or colon directly
|
|
|
- without spaces and tabs), we found Max-Forwards header field name and can set
|
|
|
- <structfield>type</structfield> field to HDR_MAXFORWARDS. Otherwise (other characters
|
|
|
- than colon, spaces and tabs) it is some other header field and set
|
|
|
- <structfield>type</structfield> field to HDR_OTHER.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- As you can see, there is no need to do hash table lookups if the header field was formed according
|
|
|
- to the convention and the comparison was very fast (only 3 comparisons needed !).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Now lets consider another example, the header field was not formed according to the convention, for
|
|
|
- example <quote>MAX-forwards</quote>:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Get the first 4 bytes of the header field name (<quote>MAX-</quote>), convert it to an
|
|
|
- integer and compare to <quote>_Max__</quote> macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Comparison failed, try to lookup <quote>MAX-</quote> converted to integer in the hash
|
|
|
- table. It was found, result is <quote>Max-</quote> converted to integer.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Try to compare the result from the hash table to <quote>_Max__</quote> macro. Comparison
|
|
|
- succeeded, continue with the next step.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Compare next 4 bytes of the header field name (<quote>forw</quote>), convert it to an
|
|
|
- integer and compare to <quote>_Max__</quote> macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Comparison failed, try to lookup <quote>forw</quote> converted to integer in the hash
|
|
|
- table. It was found, result is <quote>Forw</quote> converted to integer.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Try to compare the result from the hash table to <quote>Forw</quote> macro. Comparison
|
|
|
- succeeded, continue with the next step.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Compare next 4 bytes of the header field name (<quote>ards</quote>), convert it to
|
|
|
- integer and compare to <quote>ards</quote> macro. Comparison succeeded, continue
|
|
|
- with the next step.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If the following characters are spaces and tabs followed by a colon (or colon directly
|
|
|
- without spaces and tabs), we found Max-Forwards header field name and can set
|
|
|
- <structfield>type</structfield> field to HDR_MAXFORWARDS. Otherwise (other characters
|
|
|
- than colon, spaces and tabs) it is some other header field and set
|
|
|
- <structfield>type</structfield> field to HDR_OTHER.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- In this example, we had to do 2 hash table lookups and 2 more comparisons. Even this variant is still
|
|
|
- very fast, because the hash table lookup is synonym-less, lookups are very fast.
|
|
|
- </para>
|
|
|
- </section> <!-- hfname-parser -->
|
|
|
-
|
|
|
- <section id="body-parsers">
|
|
|
- <title>The Header Field Body Parsers</title>
|
|
|
- <section id="to-parser">
|
|
|
- <title>To HF Body Parser</title>
|
|
|
- <para>
|
|
|
- Purpose of this parser is to parse body of To header field. The parser can be found in file
|
|
|
- <filename moreinfo="none">parse_to.c</filename> under <filename moreinfo="none">parser</filename>
|
|
|
- subdirectory.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Main function is <function moreinfo="none">parse_to</function> but there is no need to call the
|
|
|
- function explicitly. Every time the parser finds a To header field, this function will be called
|
|
|
- automatically. Result of the parser is <structname>to_body</structname> structure. Pointer to the
|
|
|
- structure will be stored in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure. Since the pointer is <type>void*</type>, there is a
|
|
|
- convenience macro <function moreinfo="none">get_to</function> in file
|
|
|
- <filename moreinfo="none">parse_to.h</filename> that will do the necessary type-casting and will
|
|
|
- return pointer to <structname>to_body</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser itself is a finite state machine that will parse To body according to the grammar defined
|
|
|
- in <acronym>RFC3261</acronym> and store result in <structname>to_body</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser gets called automatically from function <function moreinfo="none">get_hdr_field</function>
|
|
|
- in file <filename moreinfo="none">msg_parser.c</filename>. The function first creates and initializes
|
|
|
- an instance of <structname>to_body</structname> structure, then calls
|
|
|
- <function moreinfo="none">parse_to</function> function with the structure as a parameter and if
|
|
|
- everything went OK, puts the pointer to the structure in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure representing the parsed To header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The newly created structure will be freed when the message is being destroyed, see function
|
|
|
- <function moreinfo="none">clean_hdr_field</function> in file <filename moreinfo="none">hf.c</filename>
|
|
|
- for more details.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="to-body-struct">
|
|
|
- <title>Structure <structname>to_body</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents parsed To body. The structure is declared in
|
|
|
- <filename moreinfo="none">parse_to.h</filename> file.
|
|
|
- </para>
|
|
|
- <para><emphasis>Structure Declaration:</emphasis></para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct to_param{
|
|
|
- int type; /* Type of parameter */
|
|
|
- str name; /* Name of parameter */
|
|
|
- str value; /* Parameter value */
|
|
|
- struct to_param* next; /* Next parameter in the list */
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-struct to_body{
|
|
|
- int error; /* Error code */
|
|
|
- str body; /* The whole header field body */
|
|
|
- str uri; /* URI */
|
|
|
- str tag_value; /* Value of tag */
|
|
|
- struct to_param *param_lst; /* Linked list of parameters */
|
|
|
- struct to_param *last_param; /* Last parameter in the list */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- Structure <structname>to_param</structname> is a temporary structure representing
|
|
|
- a To <acronym>URI</acronym> parameter. Right now only TAG parameter will be marked
|
|
|
- in <structfield>type</structfield> field. All other parameters will have the same
|
|
|
- type.
|
|
|
- </para>
|
|
|
- <para><emphasis>Field Description:</emphasis></para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>error</structfield> - Error code will be put here when parsing of To
|
|
|
- body fails.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>body</structfield> - The whole header field body.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>uri</structfield> - <acronym>URI</acronym> of the To header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>tag_value</structfield> - Value of tag parameter if present.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_lst</structfield> - Linked list of all parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>last_param</structfield> - Pointer to the last parameter in the linked list.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- to-body-struct -->
|
|
|
-
|
|
|
- </section> <!-- to-parser -->
|
|
|
-
|
|
|
- <section id="from-parser">
|
|
|
- <title>From HF Body Parser</title>
|
|
|
- <para>
|
|
|
- This parser is only a wrapper to the To header field parser. Since bodies of both header fields
|
|
|
- are identical, From parser only calls To parser.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The wrapper can be found in file <filename moreinfo="none">parse_from.c</filename> under
|
|
|
- <filename moreinfo="none">parser</filename> subdirectory. There is only one function called
|
|
|
- <function moreinfo="none">parse_from_header</function>. The function accepts one parameter which
|
|
|
- is pointer to structure representing the From header field to be parsed. The function creates an
|
|
|
- instance of <structname>to_body</structname> structure and initializes it. It then calls
|
|
|
- <function moreinfo="none">parse_to</function> function and if everything went OK, the pointer to
|
|
|
- the newly created structure will be put in <structfield>parsed</structfield> field of the structure
|
|
|
- representing the parsed header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The newly created structure will be freed when the whole message is being destroyed.
|
|
|
- (See To header field parser description for more details).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- From parser <emphasis>must be called explicitly</emphasis> !
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If the main parser finds a From header field, it will not parse the header field body
|
|
|
- automatically. It is up to you to call the
|
|
|
- <function moreinfo="none">parse_from_header</function> when you want to parse a From
|
|
|
- header field body.
|
|
|
- </para>
|
|
|
- </section> <!-- from-parser -->
|
|
|
-
|
|
|
- <section id="cseq-parser">
|
|
|
- <title>CSeq HF Body Parser</title>
|
|
|
- <para>
|
|
|
- Purpose of this parser is to parse body of CSeq header field. The parser can be found in file
|
|
|
- <filename moreinfo="none">parse_cseq.c</filename> under <filename moreinfo="none">parser</filename>
|
|
|
- subdirectory.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Main function is <function moreinfo="none">parse_cseq</function> but there is no need to call the
|
|
|
- function explicitly. Every time the parser finds a CSeq header field, this function will be called
|
|
|
- automatically. Result of the parser is <structname>cseq_body</structname> structure. Pointer to the
|
|
|
- structure will be stored in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure. Since the pointer is <type>void*</type>, there is a
|
|
|
- convenience macro <function moreinfo="none">get_cseq</function> in file
|
|
|
- <filename moreinfo="none">parse_cseq.h</filename> that will do the necessary type-casting and will
|
|
|
- return pointer to <structname>cseq_body</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser will parse CSeq body according to the grammar defined in <acronym>RFC3261</acronym> and
|
|
|
- store result in <structname>cseq_body</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser gets called automatically from function <function moreinfo="none">get_hdr_field</function>
|
|
|
- in file <filename moreinfo="none">msg_parser.c</filename>. The function first creates and initializes
|
|
|
- an instance of <structname>cseq_body</structname> structure, then calls
|
|
|
- <function moreinfo="none">parse_cseq</function> function with the structure as a parameter and if
|
|
|
- everything went OK, puts the pointer to the structure in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure representing the parsed CSeq header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The newly created structure will be freed when the message is being destroyed, see function
|
|
|
- <function moreinfo="none">clean_hdr_field</function> in file <filename moreinfo="none">hf.c</filename>
|
|
|
- for more details.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="cseq-body-struct">
|
|
|
- <title>Structure <structname>cseq_body</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents parsed CSeq body. The structure is declared in
|
|
|
- <filename moreinfo="none">parse_cseq.h</filename> file.
|
|
|
- </para>
|
|
|
- <para><emphasis>Structure Declaration:</emphasis></para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct cseq_body{
|
|
|
- int error; /* Error code */
|
|
|
- str number; /* CSeq number */
|
|
|
- str method; /* Associated method */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para><emphasis>Field Description:</emphasis></para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>error</structfield> - Error code will be put here when parsing of CSeq
|
|
|
- body fails.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>number</structfield> - CSeq number as string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>method</structfield> - CSeq method.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- cseq-body-struct -->
|
|
|
- </section> <!-- cseq-parser -->
|
|
|
-
|
|
|
- <section id="event-parser">
|
|
|
- <title>Event HF Body Parser</title>
|
|
|
- <para>
|
|
|
- Purpose of this parser is to parse body of an Event Header field. The parser can be found in
|
|
|
- file <filename moreinfo="none">parse_event.c</filename> under
|
|
|
- <filename moreinfo="none">parser</filename> subdirectory.
|
|
|
- </para>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- This is <emphasis>NOT</emphasis> fully featured Event body parser ! The parser was written
|
|
|
- for Presence Agent module only and thus can recognize Presence package only. No subpackages
|
|
|
- will be recognized. All other packages will be marked as <quote>OTHER</quote>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser should be replace by a more generic parser if subpackages or parameters should be
|
|
|
- parsed too.
|
|
|
- </para>
|
|
|
- </note>
|
|
|
- <para>
|
|
|
- Main function is <function moreinfo="none">parse_event</function> in file
|
|
|
- <filename moreinfo="none">parse_event.c</filename>. The function will create an instance of
|
|
|
- <structname>event_t</structname> structure and call the parser. If everything went OK, pointer
|
|
|
- to the newly created structure will be stored in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure representing the parsed header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- As usually, the newly created structure will be freed when the whole message is being destroyed.
|
|
|
- See function <function moreinfo="none">clean_hdr_field</function> in file
|
|
|
- <filename moreinfo="none">hf.c</filename>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser will be not called automatically when the main parser finds an Event header field.
|
|
|
- It is up to you to call the parser when you really need the body of the header field to be
|
|
|
- parsed (call <function moreinfo="none">parse_event</function> function).
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="event-struct">
|
|
|
- <title>Structure <structname>event_t</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents parsed Event body. The structure is declared in
|
|
|
- <filename moreinfo="none">parse_event.h</filename> file.
|
|
|
- </para>
|
|
|
- <para><emphasis>Structure Declaration:</emphasis></para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-#define EVENT_OTHER 0
|
|
|
-#define EVENT_PRESENCE 1
|
|
|
-
|
|
|
-typedef struct event {
|
|
|
- str text; /* Original string representation */
|
|
|
- int parsed; /* Parsed variant */
|
|
|
-} event_t;
|
|
|
-</programlisting>
|
|
|
- <para><emphasis>Field Description:</emphasis></para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>text</structfield> - Package name as text.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>parsed</structfield> - Package name as integer. It will be EVENT_PRESENCE
|
|
|
- for presence package and EVENT_OTHER for rest.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- event-struct -->
|
|
|
- </section> <!-- event-parser -->
|
|
|
- <section id="expires-parser">
|
|
|
- <title>Expires HF Body Parser</title>
|
|
|
- <para>
|
|
|
- The parser parses body of Expires header field. The body is very simple, it consists of number only.
|
|
|
- so the parser only removes any leading tabs and spaces and converts the number from string to
|
|
|
- integer. That's it.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser can be found in file <filename moreinfo="none">parse_expires.c</filename> under
|
|
|
- <filename moreinfo="none">parser</filename> subdirectory. Main function is
|
|
|
- <function moreinfo="none">parse_expires</function>. The function is not called automatically
|
|
|
- when an Expires header field was found. It is up to you to call the function if you need the body
|
|
|
- to be parsed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function creates a new instance of <structname>exp_body_t</structname> structure and calls the
|
|
|
- parser. If everything went OK, pointer to the newly created structure will be saved in
|
|
|
- <structfield>parsed</structfield> field of the <structname>hdr_field</structname> structure representing
|
|
|
- the parsed header field.
|
|
|
- </para>
|
|
|
- <section id="exp-body-struct">
|
|
|
- <title>Structure <structname>exp_body_t</structname></title>
|
|
|
- <para>
|
|
|
- The structure represents parsed Expires body. The structure is declared in
|
|
|
- <filename moreinfo="none">parse_expires.h</filename> file.
|
|
|
- </para>
|
|
|
- <para><emphasis>Structure Declaration:</emphasis></para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct exp_body {
|
|
|
- str text; /* Original text representation */
|
|
|
- int val; /* Parsed value */
|
|
|
-} exp_body_t;
|
|
|
-</programlisting>
|
|
|
- <para><emphasis>Field Description:</emphasis></para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>text</structfield> - Expires value as text.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>val</structfield> - Expires value as integer.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- exp-body-struct -->
|
|
|
- </section> <!-- expires-parser -->
|
|
|
-
|
|
|
- <section id="via-parser">
|
|
|
- <title>Via HF Body Parser</title>
|
|
|
- <para>
|
|
|
- Purpose of this parser is to parse body of Via header field. The parser can be found in file
|
|
|
- <filename moreinfo="none">parse_via.c</filename> under <filename moreinfo="none">parser</filename>
|
|
|
- subdirectory.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Main function is <function moreinfo="none">parse_via</function> but there is no need to call the
|
|
|
- function explicitly. Every time the parser finds a Via header field, this function will be called
|
|
|
- automatically. Result of the parser is <structname>via_body</structname> structure. Pointer to the
|
|
|
- structure will be stored in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure representing the parsed header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser itself is a finite state machine that will parse Via body according to the grammar defined
|
|
|
- in <acronym>RFC3261</acronym> and store result in <structname>via_body</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser gets called automatically from function <function moreinfo="none">get_hdr_field</function>
|
|
|
- in file <filename moreinfo="none">msg_parser.c</filename>. The function first creates and initializes
|
|
|
- an instance of <structname>via_body</structname> structure, then calls
|
|
|
- <function moreinfo="none">parse_via</function> function with the structure as a parameter and if
|
|
|
- everything went OK, puts the pointer to the structure in <structfield>parsed</structfield> field of
|
|
|
- <structname>hdr_field</structname> structure representing the parsed Via header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The newly created structure will be freed when the message is being destroyed, see function
|
|
|
- <function moreinfo="none">clean_hdr_field</function> in file <filename moreinfo="none">hf.c</filename>
|
|
|
- for more details.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Structure <structname>via_body</structname> is described in section
|
|
|
- <link linkend="via-body">Structure <structname>via_body</structname></link>.
|
|
|
- </para>
|
|
|
- </section> <!-- via-parser -->
|
|
|
-
|
|
|
- <section id="contact-parser">
|
|
|
- <title>Contact HF Body Parser</title>
|
|
|
- <para>
|
|
|
- The parser is located under <filename moreinfo="none">parser/contact</filename> subdirectory. The
|
|
|
- parser is not called automatically when the main parser finds a Contact header field. It is your
|
|
|
- responsibility to call the parser if you want a Contact header field body to be parsed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Main function is <function moreinfo="none">parse_contact</function> in file
|
|
|
- <filename moreinfo="none">parse_contact.c</filename>. The function accepts one parameter which
|
|
|
- is structure <structname>hdr_field</structname> representing the header field to be parsed. A single
|
|
|
- Contact header field may contain multiple contacts, the parser will parse all of them and will create
|
|
|
- linked list of all such contacts.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function creates and initializes an instance of <structname>contact_body</structname> structure.
|
|
|
- Then function <function moreinfo="none">contact_parser</function> will be called. If everything went
|
|
|
- OK, pointer to the newly created structure will be stored in <structfield>parsed</structfield> field
|
|
|
- of the <structname>hdr_field</structname> structure representing the parsed header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Function <function moreinfo="none">contact_parser</function> will then check if the contact is star, if
|
|
|
- not it will call <function moreinfo="none">parse_contacts</function> function that will parse all
|
|
|
- contacts of the header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Function <function moreinfo="none">parse_contacts</function> can be found in file
|
|
|
- <filename moreinfo="none">contact.c</filename>. It extracts <acronym>URI</acronym> and parses all
|
|
|
- contact parameters.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The Contact parameter parser can be found in file <filename moreinfo="none">cparam.c</filename>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The following structures will be created during parsing:
|
|
|
- </para>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- Mind that none of string in the following structures is zero terminated ! Be very careful
|
|
|
- when processing the strings with functions that require zero termination (printf for example) !
|
|
|
- </para>
|
|
|
- </note>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct contact_body {
|
|
|
- unsigned char star; /* Star contact */
|
|
|
- contact_t* contacts; /* List of contacts */
|
|
|
-} contact_body_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This is the main structure. Pointer to instance of this structure will be stored in
|
|
|
- <structfield>parsed</structfield> field of structure representing the header field to be parsed.
|
|
|
- The structure contains two field:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>star</structfield> field - This field will contain 1 if the Contact
|
|
|
- was star (see <acronym>RFC3261</acronym> for more details).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>contacts</structfield> field - This field contains pointer to linked
|
|
|
- list of all contacts found in the Contact header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct contact {
|
|
|
- str uri; /* contact uri */
|
|
|
- cparam_t* q; /* q parameter hook */
|
|
|
- cparam_t* expires; /* expires parameter hook */
|
|
|
- cparam_t* method; /* method parameter hook */
|
|
|
- cparam_t* params; /* List of all parameters */
|
|
|
- struct contact* next; /* Next contact in the list */
|
|
|
-} contact_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This structure represents one Contact (Mind that there might be several contacts in one Contact
|
|
|
- header field delimited by a comma). Its fields have the following meaning:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>uri</structfield> - This field contains pointer to begin of
|
|
|
- <acronym>URI</acronym> and its length.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>q</structfield> - This is a hook to structure representing q parameter.
|
|
|
- If there is no such parameter, the hook contains 0.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>expires</structfield> - This is a hook to structure representing expires
|
|
|
- parameter. If there is no such parameter, the hook contains 0.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>method</structfield> - This is a hook to structure representing method
|
|
|
- parameter. If there is no such parameter, the hook contains 0.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>params</structfield> - Linked list of all parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>next</structfield> - Pointer to the next contact that was in the same
|
|
|
- header field.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef enum cptype {
|
|
|
- CP_OTHER = 0, /* Unknown parameter */
|
|
|
- CP_Q, /* Q parameter */
|
|
|
- CP_EXPIRES, /* Expires parameter */
|
|
|
- CP_METHOD /* Method parameter */
|
|
|
-} cptype_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This is an enum of recognized types of contact parameters. Q parameter will have type set to
|
|
|
- CP_Q, Expires parameter will have type set to CP_EXPIRES and Method parameter will have type set
|
|
|
- to CP_METHOD. All other parameters will have type set to CP_OTHER.
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/*
|
|
|
- * Structure representing a contact
|
|
|
- */
|
|
|
-typedef struct cparam {
|
|
|
- cptype_t type; /* Type of the parameter */
|
|
|
- str name; /* Parameter name */
|
|
|
- str body; /* Parameter body */
|
|
|
- struct cparam* next; /* Next parameter in the list */
|
|
|
-} cparam_t;
|
|
|
-</programlisting>
|
|
|
-
|
|
|
- <para>
|
|
|
- This structure represents a contact parameter. Field description follows:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>type</structfield> - Type of the parameter, see <structname>cptype</structname>
|
|
|
- enum for more details.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>name</structfield> - Name of the parameter (i.e. the part before
|
|
|
- <quote>=</quote>).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>body</structfield> - Body of the parameter (i.e. the part after
|
|
|
- <quote>=</quote>).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>next</structfield> - Next parameter in the linked list.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- </section> <!-- contact-parser -->
|
|
|
-
|
|
|
- <section id="digest-parser">
|
|
|
- <title>Digest Body Parser</title>
|
|
|
- <para>
|
|
|
- Purpose of this parser is to parse digest response. The parser can be found under
|
|
|
- <filename moreinfo="none">parser/digest</filename> subdirectory. There might be several header
|
|
|
- fields containing digest response, for example Proxy-Authorization or WWW-Authorization. The parser
|
|
|
- can be used for all of them.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The parser is not called automatically when by the main parser. It is your responsibility to call the
|
|
|
- parser when you want a digest response to be parsed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Main function is <function moreinfo="none">parse_credentials</function> defined in
|
|
|
- <filename moreinfo="none">digest.c</filename>. The function accepts one parameter which is header
|
|
|
- field to be parsed. As result the function will create an instance of
|
|
|
- <structname>auth_body_t</structname> structure which will represent the parsed digest credentials.
|
|
|
- Pointer to the structure will be put in <structfield>parsed</structfield> field of the
|
|
|
- <structname>hdr_field</structname> structure representing the parsed header field. It will be freed
|
|
|
- when the whole message is being destroyed.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- The digest parser contains 32-bit digest parameter parser. The parser was in detail described in
|
|
|
- section <link linkend="hfname-parser">Header Field Name Parser</link>. See that section for more
|
|
|
- details about the digest parameter parser algorithm, they work in the same way.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- Description of digest related structures follows:
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct auth_body {
|
|
|
- /* This is pointer to header field containing
|
|
|
- * parsed authorized digest credentials. This
|
|
|
- * pointer is set in sip_msg->{authorization,proxy_auth}
|
|
|
- * hooks.
|
|
|
- *
|
|
|
- * This is necessary for functions called after
|
|
|
- * {www,proxy}_authorize, these functions need to know
|
|
|
- * which credentials are authorized and they will simply
|
|
|
- * look into
|
|
|
- * sip_msg->{authorization,proxy_auth}->parsed->authorized
|
|
|
- */
|
|
|
- struct hdr_field* authorized;
|
|
|
- dig_cred_t digest; /* Parsed digest credentials */
|
|
|
- unsigned char stale; /* Flag is set if nonce is stale */
|
|
|
- int nonce_retries; /* How many times the nonce was used */
|
|
|
-} auth_body_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This is the <quote>main</quote> structure. Pointer to the structure will be stored in
|
|
|
- <structfield>parsed</structfield> field of <structname>hdr_field</structname> structure. Detailed
|
|
|
- description of its fields follows:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>authorized</structfield> - This is a hook to header field containing
|
|
|
- authorized credentials.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- A <acronym>SIP</acronym> message may contain several credentials. They are distinguished
|
|
|
- using realm parameter. When the server is trying to authorize the message, it must first
|
|
|
- find credentials with corresponding realm and than authorize the credentials. To authorize
|
|
|
- credentials server calculates response string and if the string matches to response string
|
|
|
- contained in the credentials, credentials are authorized (in fact it means that the user
|
|
|
- specified in the credentials knows password, nothing more, nothing less).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- It would be good idea to remember which credentials contained in the message are authorized,
|
|
|
- there might be other functions interested in knowing which credentials are authorized.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- That is what is this field for. A function that successfully authorized credentials
|
|
|
- (currently there is only one such function in the server, it is function
|
|
|
- <function moreinfo="none">authorize</function> in auth module) will put pointer to header
|
|
|
- field containing the authorized credentials in this field. Because there might be several
|
|
|
- header field containing credentials, the pointer will be put in
|
|
|
- <structfield>authorized</structfield> field in the first header field in the message
|
|
|
- containing credentials. That means that it will be either header field whose pointer is
|
|
|
- in <structfield>www_auth</structfield> or <structfield>proxy_auth</structfield> field
|
|
|
- of <structname>sip_msg</structname> structure representing the message.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When a function wants to find authorized credentials, it will simply look in
|
|
|
- <structfield>msg->www_auth->parsed->authorized</structfield> or
|
|
|
- <structfield>msg->proxy_auth->parsed->authorized</structfield>,
|
|
|
- where <structfield>msg</structfield> is variable containing pointer to
|
|
|
- <structname>sip_msg</structname> structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- To simplify the task of saving and retrieving pointer to authorized credentials, there
|
|
|
- are two convenience functions defined in <filename moreinfo="none">digest.c</filename> file.
|
|
|
- They will be described later.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>digest</structfield> - Structure containing parsed digest credentials. The
|
|
|
- structure will be described in detail later.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>stale</structfield> - This field will be set to 1 if the server received
|
|
|
- a stale nonce. Next time when the server will be sending another challenge, it will use
|
|
|
- <quote>stale=true</quote> parameter. <quote>stale=true</quote> indicates to the client
|
|
|
- that username and password used to calculate response were correct, but nonce was stale.
|
|
|
- The client should recalculate response with the same username and password (without
|
|
|
- disturbing user) and new nonce. For more details see <acronym>RFC2617</acronym>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>nonce_retries</structfield> - This fields indicates number of authorization
|
|
|
- attempts with same nonce.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/*
|
|
|
- * Errors returned by check_dig_cred
|
|
|
- */
|
|
|
-typedef enum dig_err {
|
|
|
- E_DIG_OK = 0, /* Everything is OK */
|
|
|
- E_DIG_USERNAME = 1, /* Username missing */
|
|
|
- E_DIG_REALM = 2, /* Realm missing */
|
|
|
- E_DIG_NONCE = 4, /* Nonce value missing */
|
|
|
- E_DIG_URI = 8, /* URI missing */
|
|
|
- E_DIG_RESPONSE = 16, /* Response missing */
|
|
|
- E_DIG_CNONCE = 32, /* CNONCE missing */
|
|
|
- E_DIG_NC = 64, /* Nonce-count missing */
|
|
|
-} dig_err_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This is enum of all possible errors returned by <function moreinfo="none">check_dig_cred</function>
|
|
|
- function.
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>E_DIG_OK</emphasis> - No error found.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>E_DIG_USERNAME</emphasis> - Username parameter missing in digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>E_DIG_REALM</emphasis> - Realm parameter missing in digest response.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>E_DIG_NONCE</emphasis> - Nonce parameter missing in digest response.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>E_DIG_URI</emphasis> - Uri parameter missing in digest response.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>E_DIG_RESPONSE</emphasis> - Response parameter missing in digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>E_DIG_CNONCE</emphasis> - Cnonce parameter missing in digest response.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>E_DIG_NC</emphasis> - Nc parameter missing in digest response.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/* Type of algorithm used */
|
|
|
-typedef enum alg {
|
|
|
- ALG_UNSPEC = 0, /* Algorithm parameter not specified */
|
|
|
- ALG_MD5 = 1, /* MD5 - default value*/
|
|
|
- ALG_MD5SESS = 2, /* MD5-Session */
|
|
|
- ALG_OTHER = 4 /* Unknown */
|
|
|
-} alg_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This is enum of recognized algorithm types. (See description of <structname>algorithm</structname>
|
|
|
- structure for more details).
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>ALG_UNSPEC</emphasis> - Algorithm was not specified in digest response.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>ALG_MD5</emphasis> - <quote>algorithm=MD5</quote> was found in digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>ALG_MD5SESS</emphasis> - <quote>algorithm=MD5-Session</quote> was found in
|
|
|
- digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>ALG_OTHER</emphasis> - Unknown algorithm parameter value was found in
|
|
|
- digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/* Quality Of Protection used */
|
|
|
-typedef enum qop_type {
|
|
|
- QOP_UNSPEC = 0, /* QOP parameter not present in response */
|
|
|
- QOP_AUTH = 1, /* Authentication only */
|
|
|
- QOP_AUTHINT = 2, /* Authentication with integrity checks */
|
|
|
- QOP_OTHER = 4 /* Unknown */
|
|
|
-} qop_type_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This enum lists all recognized qop parameter values.
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>QOP_UNSPEC</emphasis> - qop parameter was not found in digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>QOP_AUTH</emphasis> - <quote>qop=auth</quote> was found in digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>QOP_AUTHINT</emphasis> - <quote>qop=auth-int</quote> was found in digest
|
|
|
- response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>QOP_OTHER</emphasis> - Unknown qop parameter value was found in digest response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/* Algorithm structure */
|
|
|
-struct algorithm {
|
|
|
- str alg_str; /* The original string representation */
|
|
|
- alg_t alg_parsed; /* Parsed value */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- The structure represents <quote>algorithm</quote> parameter of digest response. Description of fields
|
|
|
- follows:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>alg_str</structfield> - Algorithm parameter value as string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>alg_parsed</structfield> - Parsed algorithm parameter value.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/* QOP structure */
|
|
|
-struct qp {
|
|
|
- str qop_str; /* The original string representation */
|
|
|
- qop_type_t qop_parsed; /* Parsed value */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This structure represents <quote>qop</quote> parameter of digest response. Description of fields
|
|
|
- follows:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>qop_str</structfield> - Qop parameter value as string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>qop_parsed</structfield> - Parsed <quote>qop</quote> parameter value.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <programlisting format="linespecific">
|
|
|
-/*
|
|
|
- * Parsed digest credentials
|
|
|
- */
|
|
|
-typedef struct dig_cred {
|
|
|
- str username; /* Username */
|
|
|
- str realm; /* Realm */
|
|
|
- str nonce; /* Nonce value */
|
|
|
- str uri; /* URI */
|
|
|
- str response; /* Response string */
|
|
|
- str algorithm; /* Algorithm in string representation */
|
|
|
- struct algorithm alg; /* Type of algorithm used */
|
|
|
- str cnonce; /* Cnonce value */
|
|
|
- str opaque; /* Opaque data string */
|
|
|
- struct qp qop; /* Quality Of Protection */
|
|
|
- str nc; /* Nonce count parameter */
|
|
|
-} dig_cred_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- This structure represents set of digest credentials parameters. Description of field follows:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>username</structfield> - Value of <quote>username</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>realm</structfield> - Value of <quote>realm</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>nonce</structfield> - Value of <quote>nonce</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>uri</structfield> - Value of <quote>uri</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>response</structfield> - Value of <quote>response</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>algorithm</structfield> - Value of <quote>algorithm</quote> parameter
|
|
|
- as string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>alg</structfield> - Parsed value of <quote>algorithm</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>cnonce</structfield> - Value of <quote>cnonce</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>opaque</structfield> - Value of <quote>opaque</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>qop</structfield> - Value of <quote>qop</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>nc</structfield> - Value of <quote>nc</quote> parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="other-funcs">
|
|
|
- <title>Other Functions Of the Digest Body Parser</title>
|
|
|
- <para>
|
|
|
- There are some other mainly convenience functions defined in the parser. The function will be
|
|
|
- in detail described in this section. All the functions are defined in
|
|
|
- <filename moreinfo="none">digest.c</filename> file.
|
|
|
- </para>
|
|
|
-
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>dig_err_t <function moreinfo="none">check_dig_cred</function></funcdef>
|
|
|
- <paramdef>dig_cred_t* <parameter moreinfo="none">_c</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
-
|
|
|
- <para>
|
|
|
- This function performs some basic sanity check over parsed digest credentials. The following
|
|
|
- conditions must be met for the checks to be successful:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- There must be non-empty <quote>username</quote> parameter in the credentials.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- There must be non-empty <quote>realm</quote> parameter in the credentials.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- There must be non-empty <quote>nonce</quote> parameter in the credentials.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- There must be non-empty <quote>uri</quote> parameter in the credentials.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- There must be non-empty <quote>response</quote> parameter in the credentials.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If qop parameter is set to QOP_AUTH or QOP_AUTHINT, then there must be also
|
|
|
- non-empty <quote>cnonce</quote> and <quote>nc</quote> parameters in the digest.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- It is recommended to call <function moreinfo="none">check_dig_cred</function> before you
|
|
|
- try to authorize the credentials. If the function fails, there is no need to try to authorize
|
|
|
- the credentials because the authorization will fail for sure.
|
|
|
- </para>
|
|
|
- </note>
|
|
|
-
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">mark_authorized_cred</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">_m</parameter></paramdef>
|
|
|
- <paramdef>struct hdr_field* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
-
|
|
|
- <para>
|
|
|
- This is convenience function. The function saves pointer to the authorized credentials. For
|
|
|
- more info see description of <structfield>authorized</structfield> field in
|
|
|
- <structname>auth_body</structname> structure.
|
|
|
- </para>
|
|
|
-
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">get_authorized_cred</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">_m</parameter></paramdef>
|
|
|
- <paramdef>struct hdr_field** <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
-
|
|
|
- <para>
|
|
|
- This is convenience function. The function will retrieve pointer to authorized credentials
|
|
|
- previously saved using <function moreinfo="none">mark_authorized_cred</function> function.
|
|
|
- If there is no such credentials, 0 will be stored in variable pointed to by the second
|
|
|
- parameter. The function returns always zero. For more information see description of
|
|
|
- <structfield>authorized</structfield> field in <structname>auth_body</structname> structure.
|
|
|
- </para>
|
|
|
- </section> <!-- other-funcs -->
|
|
|
- </section> <!-- digest-parser -->
|
|
|
- </section> <!-- body-parsers -->
|
|
|
- </section> <!-- parser-organization -->
|
|
|
- </chapter> <!-- msg-parser -->
|
|
|
-
|
|
|
- <chapter id="module-interface">
|
|
|
- <title>The Module Interface</title>
|
|
|
- <para>
|
|
|
- The server can load additional functionality through modules. Module loading related functions and module
|
|
|
- interface will be described in this section.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- All the data structures and functions mentioned in this section can be found in files
|
|
|
- <filename moreinfo="none">sr_module.h</filename> and <function moreinfo="none">sr_module.c</function>.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="sr-module-struct">
|
|
|
- <title>Structure <structname>sr_module</structname></title>
|
|
|
- <para>
|
|
|
- Each loaded module is represented by an instance of <structname>sr_module</structname> structure. All
|
|
|
- the instances are linked. There is a global variable <varname>modules</varname> defined in file
|
|
|
- <filename moreinfo="none">sr_module.c</filename> which is head of linked-list of all loaded modules.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Detailed description of the structure follows:
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct sr_module{
|
|
|
- char* path;
|
|
|
- void* handle;
|
|
|
- struct module_exports* exports;
|
|
|
- struct sr_module* next;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- <emphasis>Fields and their description:</emphasis>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>path</structfield> - Path to the module. This is the path you pass as parameter
|
|
|
- to <function moreinfo="none">loadmodule</function> function in the config file.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>handle</structfield> - Handle returned by <function moreinfo="none">dlopen</function>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>exports</structfield> - Pointer to structure describing interface of the module (will
|
|
|
- be described later).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>next</structfield> - Pointer to the next <structname>sr_module</structname> structure
|
|
|
- in the linked list.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- </section> <!-- sr-module-struct -->
|
|
|
-
|
|
|
- <section id="module-exports-struct">
|
|
|
- <title>Structure <structname>module_exports</structname></title>
|
|
|
- <para>
|
|
|
- This structure describes interface that must be exported by each module. Every module must have a global
|
|
|
- variable named <varname>exports</varname> which is of type <structname>struct module_exports</structname>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Immediately after <function moreinfo="none">dlopen</function> the server will try to find symbol named
|
|
|
- <varname>exports</varname> in the module to be loaded. This symbol is a structure describing interface
|
|
|
- of the module. Pointer to the symbol will be then put in <structfield>exports</structfield> field of
|
|
|
- <structname>sr_module</structname> structure representing the module in the server.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Detailed description of the structure follows:
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-struct module_exports{
|
|
|
- char* name; /* null terminated module name */
|
|
|
- char** cmd_names; /* cmd names registered
|
|
|
- * by this modules */
|
|
|
- cmd_function* cmd_pointers; /* pointers to the
|
|
|
- * corresponding functions */
|
|
|
- int* param_no; /* number of parameters used by
|
|
|
- * the function */
|
|
|
- fixup_function* fixup_pointers; /* pointers to functions
|
|
|
- * called to "fix"
|
|
|
- * the params, e.g: precompile
|
|
|
- * a re */
|
|
|
- int cmd_no; /* number of registered commands
|
|
|
- * (size of cmd_{names,pointers}
|
|
|
- */
|
|
|
-
|
|
|
- char** param_names; /* parameter names registered
|
|
|
- * by this modules */
|
|
|
- modparam_t* param_types; /* Type of parameters */
|
|
|
- void** param_pointers; /* Pointers to the corresponding
|
|
|
- * memory locations */
|
|
|
- int par_no; /* number of registered parameters */
|
|
|
-
|
|
|
- init_function init_f; /* Initialization function */
|
|
|
- response_function response_f; /* function used for responses,
|
|
|
- * returns yes or no; can be null
|
|
|
- */
|
|
|
- destroy_function destroy_f; /* function called when the module
|
|
|
- * should be "destroyed", e.g: on
|
|
|
- * ser exit;
|
|
|
- * can be null */
|
|
|
- onbreak_function onbreak_f;
|
|
|
- child_init_function init_child_f; /* function called by all
|
|
|
- * processes after the fork */
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- <emphasis>Fields and their description</emphasis>:
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>name</structfield> - Name of the module.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>cmd_names</structfield> - Array of names of exported commands.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>cmd_pointers</structfield> - Array of pointers to functions implementing
|
|
|
- commands specified in <structfield>cmd_names</structfield> array.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">cmd_function</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">param1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">param2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The first parameter is <structname>sip_msg</structname> currently being processed.
|
|
|
- Remaining parameters are parameters from the config file. If the function accepts only
|
|
|
- one parameter, <parameter moreinfo="none">param2</parameter> will be set to zero, if the
|
|
|
- function accepts no parameters, <parameter moreinfo="none">param1</parameter> and
|
|
|
- <parameter moreinfo="none">param2</parameter> will be set to zero.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function should return number > 0 if everything went OK and processing of the message should
|
|
|
- continue. The function should return 0 if processing of the message should be stopped.
|
|
|
- The function should return number < 0 on an error.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_no</structfield> - Array of number of parameters of exported commands.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>fixup_pointer</structfield> - Array of pointers to fixup functions, each fixup
|
|
|
- function for one exported command. If there is no fixup function for a particular exported
|
|
|
- function, corresponding field in the array will contain zero.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">fixup_function</function></funcdef>
|
|
|
- <paramdef>void** <parameter moreinfo="none">param</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">param_no</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The first parameter is pointing to variable to be fixed. The second parameter
|
|
|
- is order of the variable.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function should return 0 if everything went OK and number < 0 on an error.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>cmd_no</structfield> - Number of exported commands.
|
|
|
- </para>
|
|
|
- <important>
|
|
|
- <para>
|
|
|
- <structfield>cmd_names</structfield>, <structfield>cmd_pointers</structfield>,
|
|
|
- <structfield>param_no</structfield> and <structfield>fixup_pointer</structfield> arrays must
|
|
|
- have at least <structfield>cmd_no</structfield> elements ! (It might even kill your cat if you
|
|
|
- fail to fulfill this condition).
|
|
|
- </para>
|
|
|
- </important>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_names</structfield> - Array of names of exported parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_types</structfield> - Array of types of parameters, each field of the array
|
|
|
- can be either STR_PARAM or INT_PARAM (currently only two parameter types are defined).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_pointers</structfield> - Array of pointers to variables, that hold values of the
|
|
|
- parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>param_no</structfield> - Number of exported parameters.
|
|
|
- </para>
|
|
|
- <important>
|
|
|
- <para>
|
|
|
- <structfield>param_names</structfield>, <structfield>param_types</structfield> and
|
|
|
- <structfield>param_pointers</structfield> arrays must have at least
|
|
|
- <structfield>param_no</structfield> elements ! (Remember the previous note about your cat ? The
|
|
|
- same might happen to your dog if you fail to fulfill the condition second time !).
|
|
|
- </para>
|
|
|
- </important>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>init_f</structfield> - Pointer to module's initialization function, 0 if the module
|
|
|
- doesn't need initialization function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">init_function</function></funcdef>
|
|
|
- <void>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function should return 0 if everything went OK and number < 0 on an error;
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>response_f</structfield> - If a module is interested in seeing responses, it will provide
|
|
|
- pointer to a function here. The function will be called when a response comes. The field will contain
|
|
|
- 0 if the module doesn't want to see responses.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">response_function</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function accepts one parameter which is structure representing the response currently
|
|
|
- being processed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function should return 0 if the response should be dropped.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>destroy_f</structfield> - Destroy function. The function will be called when the server
|
|
|
- is shutting down. Can be 0 if the module doesn't need destroy function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>void <function moreinfo="none">destroy_function</function></funcdef>
|
|
|
- <void>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>onbreak_f</structfield> - On break function. The function will be called when processing
|
|
|
- of a route statement was aborted. Can be 0 if module doesn't need this function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>void <function moreinfo="none">onbreak_function</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function accepts one parameter which is message currently being processed.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>init_child_f</structfield> - Child initialization
|
|
|
- function. This is an additional initialization
|
|
|
- function. <structfield>init_f</structfield> will be called from the main process
|
|
|
- <emphasis>BEFORE</emphasis> the main process forks children. <structfield>init_child_f</structfield>
|
|
|
- will be called from all children <emphasis>AFTER</emphasis> the fork.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Per-child specific initialization can be done here. For example, each child can open its own database
|
|
|
- connection in the function, and so on.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <emphasis>Function Prototype</emphasis>:
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">child_init_function</function></funcdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">rank</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function accepts one parameter, which is rank (starting from 0) of child executing the function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function should return 0 if everything went OK and number < 0 on an error.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- module-exports-struct -->
|
|
|
-
|
|
|
- <section id="module-loading">
|
|
|
- <title>Module Loading</title>
|
|
|
- <para>
|
|
|
- Modules are compiled and stored as shared objects. Shared objects have usually appendix <quote>.so</quote>.
|
|
|
- Shared objects can be loaded at runtime.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- When you instruct the server to load a module using <function moreinfo="none">loadmodule</function> command
|
|
|
- in the config file, it will call function <function moreinfo="none">load_module</function>. The function
|
|
|
- will do the following:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- It will try to open specified file using <function moreinfo="none">dlopen</function>. For example
|
|
|
- if you write loadmodule "/usr/lib/ser/modules/auth.so" in the config file, the server will try
|
|
|
- to open file <quote>/usr/lib/ser/modules/auth.so</quote> using
|
|
|
- <function moreinfo="none">dlopen</function> function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If <function moreinfo="none">dlopen</function> failed, the server will issue an error and abort.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- As the next step, list of all previously loaded modules will be searched for the same module.
|
|
|
- If such module is found, it means, that user is trying to load the same module twice. In such
|
|
|
- case an warning will be issued and server will abort.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- The server will try to find pointer to <quote>exports</quote> symbol using
|
|
|
- <function moreinfo="none">dlsym</function> in the module. If that fails, server will issue an
|
|
|
- error and abort.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- And as the last step, function <function moreinfo="none">register_module</function> will register
|
|
|
- the module with the server core and loading of the module is complete.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Function <function moreinfo="none">register_module</function> registers a module with the server core. By
|
|
|
- registration we mean the following set of steps (see function
|
|
|
- <function moreinfo="none">register_module</function> in file <filename moreinfo="none">sr_module.c</filename>
|
|
|
- for more details):
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- The function creates and initializes new instance of <structname>sr_module</structname>
|
|
|
- structure.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>path</structfield> field will be set to path of the module.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>handle</structfield> field will be set to handle previously returned by
|
|
|
- <function moreinfo="none">dlopen</function>.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <structfield>exports</structfield> field will be set to pointer to module's
|
|
|
- <varname>exports</varname> structure previously obtained through
|
|
|
- <function moreinfo="none">dlsym</function> in <function moreinfo="none">load_module</function>
|
|
|
- function.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- As the last step, the newly created structure will be inserted into linked list of all
|
|
|
- loaded modules and registration is complete.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- </section> <!-- module-loading -->
|
|
|
-
|
|
|
- <section id="module-config">
|
|
|
- <title>Module Configuration</title>
|
|
|
- <para>
|
|
|
- In addition to set of functions each module can export set of configuration variables.
|
|
|
- Value of a module's configuration variable can be changed in the config file using
|
|
|
- <function moreinfo="none">modparam</function> function. Module configuration will be described in this
|
|
|
- section.
|
|
|
- </para>
|
|
|
- <section id="modparam-func">
|
|
|
- <title>Function <function moreinfo="none">modparam</function></title>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">modparam</function> function accepts three parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>module name</emphasis> - Name of module as exported in <structfield>name</structfield>
|
|
|
- field of <varname>exports</varname> global variable.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>variable name</emphasis> - Name of variable to be set - it must be one of names
|
|
|
- specified in <structfield>param_names</structfield> field of <varname>exports</varname>
|
|
|
- variable of the module.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>value</emphasis> - New value of the variable. There are two types of variables:
|
|
|
- string and integer. If the last parameter (value) of
|
|
|
- <function moreinfo="none">modparam</function>
|
|
|
- function is enclosed in quotes, it is string parameter and server will try to find the
|
|
|
- corresponding variable among string parameters only.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Otherwise it is integer parameter and server will try to find corresponding variable among
|
|
|
- integer parameters only.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- </section> <!-- modparam-func -->
|
|
|
-
|
|
|
- <section id="set-mod-param-func">
|
|
|
- <title>Function <function moreinfo="none">set_mod_param</function></title>
|
|
|
- <para>
|
|
|
- When the server finds <function moreinfo="none">modparam</function> function in the config file, it
|
|
|
- will call <function moreinfo="none">set_mod_param</function> function. The function can be found
|
|
|
- in <filename moreinfo="none">modparam.c</filename> file. The function will do the following:
|
|
|
- </para>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- It tries to find corresponding variable using <function moreinfo="none">find_param_export</function>
|
|
|
- function.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- If it is string parameter, a new copy of the string will be obtained using
|
|
|
- <function moreinfo="none">strdup</function> function and pointer to the copy will be stored in the
|
|
|
- variable.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If it is integer parameter, its value will be simply copied in the variable.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- set-mod-param-func -->
|
|
|
-
|
|
|
- <section id="find-param-export-func">
|
|
|
- <title>Function <function moreinfo="none">find_param_export</function></title>
|
|
|
- <para>
|
|
|
- This function accepts 3 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>module</emphasis> - Name of module.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>parameter</emphasis> - Name of parameter to be found.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>type</emphasis> - Type of the parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function will search list of all modules until it finds module with given name.
|
|
|
- Then it will search through all module's exported parameters until it finds parameter
|
|
|
- with corresponding name and type. If such parameter was found, pointer to variable holding
|
|
|
- the parameter's value will be returned. If the function failed to find either module or
|
|
|
- parameter with given name and type then zero will be returned.
|
|
|
- </para>
|
|
|
- </section> <!-- find-param-export-func -->
|
|
|
- </section> <!-- module-config -->
|
|
|
-
|
|
|
- <section id="finding-exported">
|
|
|
- <title>Finding an Exported Function</title>
|
|
|
- <para>This section describes how to find an exported function.</para>
|
|
|
-
|
|
|
- <para>
|
|
|
- If you need to find exported function with given name and number of parameters,
|
|
|
- <function moreinfo="none">find_export</function> function is what you need. The function
|
|
|
- is defined in <filename moreinfo="none">sr_module.c</filename> file.
|
|
|
- The function accepts two parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>name</emphasis> - Name of function to be found.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>param_no</emphasis> - Number of parameters of the function.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function will search through list of all loaded modules and in each module through
|
|
|
- array of all exported functions until it finds function with given name and number of
|
|
|
- parameters. If such exported function was found, <function moreinfo="none">find_exported</function>
|
|
|
- will return pointer to the function, otherwise zero will be returned.
|
|
|
- </para>
|
|
|
- </section> <!--finding-exported -->
|
|
|
-
|
|
|
- <section id="additional-functions">
|
|
|
- <title>Additional Functions</title>
|
|
|
- <para>
|
|
|
- There are several additional functions defined in file <filename moreinfo="none">sr_module.c</filename>.
|
|
|
- There functions are mostly internal and shouldn't be used directly by user. We will shortly describe
|
|
|
- them here.
|
|
|
- </para>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">register_builtin_modules</function> - Some modules might be linked
|
|
|
- statically with main executable, this is handy for debugging. This function will register all
|
|
|
- such modules upon server startup.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">init_child</function> - This function will call child-initialization
|
|
|
- function of all loaded modules. The function will be called by the server core immediately after
|
|
|
- the fork.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">find_module</function> - The function accepts pointer to an exported
|
|
|
- function and number of parameters as parameters and returns pointer to corresponding module that
|
|
|
- exported the function.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">destroy_modules</function> - The function will call destroy function
|
|
|
- of all loaded modules. This function will be called by the server core upon shut down.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">init_modules</function> - The function will call initialization function
|
|
|
- of all loaded modules. The function will be called by the server before the fork.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- additional-functions -->
|
|
|
- </chapter> <!-- module-interface -->
|
|
|
-
|
|
|
-
|
|
|
- <chapter id="db-interface">
|
|
|
- <title>The Database Interface</title>
|
|
|
- <para>
|
|
|
- This is a generic database interface for modules that need to utilize a
|
|
|
- database. The interface should be used by all modules that access database.
|
|
|
- The interface will be independent of the underlying database server.
|
|
|
- </para>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- If possible, use predefined macros if you need to access any structure
|
|
|
- attributes.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- For additional description, see comments in sources of mysql module.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If you want to see more complicated examples of how the API could be used,
|
|
|
- see sources of dbexample, usrloc or auth modules.
|
|
|
- </para>
|
|
|
- </note>
|
|
|
-
|
|
|
- <section id="data-types">
|
|
|
- <title>Data types</title>
|
|
|
- <para>
|
|
|
- There are several data types. All of them are defined in header files under
|
|
|
- <filename moreinfo="none">db</filename> subdirectory,
|
|
|
- a client must include <filename moreinfo="none">db.h</filename> header file to be able to use them.
|
|
|
- </para>
|
|
|
- <section id="type-db-con">
|
|
|
- <title>Type <type>db_con_t</type></title>
|
|
|
- <para>
|
|
|
- This type represents a database connection, all database functions (described
|
|
|
- below) use a variable of this type as one argument. In other words, variable
|
|
|
- of <type>db_con_t</type> type serves as a handle for a particular database connection.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct db_con {
|
|
|
- char* table; /* Default table to use */
|
|
|
- void* con; /* Database connection */
|
|
|
- void* res; /* Result of previous operation */
|
|
|
- void* row; /* Internal, not for public use */
|
|
|
- int connected; /* 1 if connection is established */
|
|
|
-} db_con_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- There are no macros defined for <type>db_con_t</type> type.
|
|
|
- </para>
|
|
|
- </section> <!-- type-db-con -->
|
|
|
-
|
|
|
- <section id="type-db-key">
|
|
|
- <title>Type <type>db_key_t</type></title>
|
|
|
- <para>
|
|
|
- This type represents a database key. Every time you need to specify a key
|
|
|
- value, this type should be used. In fact, this type is identical to
|
|
|
- <type>const char*</type>.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
- typedef const char* db_key_t;
|
|
|
- </programlisting>
|
|
|
- <para>
|
|
|
- There are no macros defined (they are not needed).
|
|
|
- </para>
|
|
|
- </section> <!-- type-db-key -->
|
|
|
-
|
|
|
- <section id="type-db-type">
|
|
|
- <title>Type <type>db_type_t</type></title>
|
|
|
- <para>
|
|
|
- Each cell in a database table can be of a different type. To distinguish
|
|
|
- among these types, the <type>db_type_t</type> enumeration is used. Every
|
|
|
- value of the enumeration represents one data-type that is recognized by the
|
|
|
- database <acronym>API</acronym>. This enumeration is used in conjunction
|
|
|
- with <type>db_type_t</type>. For more information, see the next section.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef enum {
|
|
|
- DB_INT, /* Integer number */
|
|
|
- DB_DOUBLE, /* Decimal number */
|
|
|
- DB_STRING, /* String */
|
|
|
- DB_STR, /* str structure */
|
|
|
- DB_DATETIME /* Date and time */
|
|
|
- DB_BLOB /* Binary large object */
|
|
|
-} db_type_t;
|
|
|
-</programlisting>
|
|
|
- <para>
|
|
|
- There are no macros defined.
|
|
|
- </para>
|
|
|
- </section> <!-- type-db-type -->
|
|
|
-
|
|
|
- <section id="type-db-val">
|
|
|
- <title>Type <type>db_val_t</type></title>
|
|
|
- <para>
|
|
|
- This structure represents a value in the database. Several data-types are
|
|
|
- recognized and converted by the database <acronym>API</acronym>:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>DB_INT</emphasis> - Value in the database represents an integer number.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>DB_DOUBLE</emphasis> - Value in the database represents a decimal number.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>DB_STRING</emphasis> - Value in the database represents a string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>DB_STR</emphasis> - Value in the database represents a string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>DB_DATETIME</emphasis> - Value in the database represents date and time.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>DB_BLOB</emphasis> - Value in the database represents binary large object.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- These data-types are automatically recognized, converted from internal database
|
|
|
- representation and stored in a variable of corresponding type.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct db_val {
|
|
|
- db_type_t type; /* Type of the value */
|
|
|
- int nul; /* NULL flag */
|
|
|
- union {
|
|
|
- int int_val; /* Integer value */
|
|
|
- double double_val; /* Double value */
|
|
|
- time_t time_val; /* Unix time_t value */
|
|
|
- const char* string_val; /* Zero terminated string */
|
|
|
- str str_val; /* str structure */
|
|
|
- str blob_val; /* Structure describing blob */
|
|
|
- } val;
|
|
|
-} db_val_t;
|
|
|
-</programlisting>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- All macros expect pinter to <type>db_val_t</type> variable as a parameter.
|
|
|
- </para>
|
|
|
- </note>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_TYPE(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to set/get the type of the value
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_TYPE Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-VAL_TYPE(val) = DB_INT;
|
|
|
-if (VAL_TYPE(val) == DB_FLOAT)
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_NULL(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to set/get the null flag. Non-zero flag means that
|
|
|
- the corresponding cell in the database contained no data (NULL value in <acronym>MySQL</acronym>
|
|
|
- terminology).
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_NULL Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-if (VAL_NULL(val) == 1) {
|
|
|
- printf("The cell is NULL");
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_INT(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to access <type>integer</type> value in <type>db_val_t</type> structure.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_INT Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-if (VAL_TYPE(val) == DB_INT) {
|
|
|
- printf("%d", VAL_INT(val));
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_DOUBLE(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to access <type>double</type> value in the <type>db_val_t</type> structure.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_DOUBLE Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-if (VAL_TYPE(val) == DB_DOUBLE) {
|
|
|
- printf("%f", VAL_DOUBLE(val));
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_TIME(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to access <type>time_t</type> value in <type>db_val_t</type> structure.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_TIME Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-time_t tim;
|
|
|
-if (VAL_TYPE(val) == DB_DATETIME) {
|
|
|
- tim = VAL_TIME(val);
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_STRING(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to access <type>string</type> value in <type>db_val_t</type> structure.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_STRING Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-if (VAL_TYPE(val) == DB_STRING) {
|
|
|
- printf("%s", VAL_STRING(val));
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_STR(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to access <type>str</type> structure in <type>db_val_t</type> structure.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_STR Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-if (VAL_TYPE(val) == DB_STR) {
|
|
|
- printf("%.*s", VAL_STR(val).len, VAL_STR(val).s);
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">VAL_BLOB(value)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to access <type>blob</type> value in <type>db_val_t</type> structure.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>VAL_STR Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-if (VAL_TYPE(val) == DB_BLOB) {
|
|
|
- printf("%.*s", VAL_BLOB(val).len, VAL_BLOB(val).s);
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- type-db-val -->
|
|
|
-
|
|
|
- <section id="type-db-row">
|
|
|
- <title>Type <type>db_row_t</type></title>
|
|
|
- <para>
|
|
|
- This type represents one row in a database table. In other words, the row is an
|
|
|
- array of <type>db_val_t</type> variables, where each <type>db_val_t</type> variable
|
|
|
- represents exactly one cell in the table.
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct db_row {
|
|
|
- db_val_t* values; /* Array of values in the row */
|
|
|
- int n; /* Number of values in the row */
|
|
|
-} db_val_t;
|
|
|
-</programlisting>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">ROW_VALUES(row)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro to get pointer to array of <type>db_val_t</type> structures.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>ROW_VALUES Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-db_val_t* v = ROW_VALUES(row);
|
|
|
-if (VAL_TYPE(v) == DB_INT)
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">ROW_N(row)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro to get number of cells in a row.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>ROW_N Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-db_val_t* val = ROW_VALUES(row);
|
|
|
-for(i = 0; i < ROW_N(row); i++) {
|
|
|
- switch(VAL_TYPE(val + i)) {
|
|
|
- case DB_INT: ...; break;
|
|
|
- case DB_DOUBLE: ...; break;
|
|
|
- ...
|
|
|
- }
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- type-db-row -->
|
|
|
-
|
|
|
- <section id="type-db-res">
|
|
|
- <title>Type <type>db_res_t</type></title>
|
|
|
- <para>
|
|
|
- This type represents a result returned by <function moreinfo="none">db_query</function>
|
|
|
- function (see below). The result can consist of zero or more rows
|
|
|
- (see <type>db_row_t</type> description).
|
|
|
- </para>
|
|
|
- <note>
|
|
|
- <para>
|
|
|
- A variable of type <type>db_res_t</type> returned by <function moreinfo="none">db_query</function>
|
|
|
- function uses dynamically allocated memory, don't forget to call
|
|
|
- <function moreinfo="none">db_free_result</function> if you don't need the variable anymore.
|
|
|
- You will encounter memory leaks if you fail to do this !
|
|
|
- </para>
|
|
|
- </note>
|
|
|
- <para>
|
|
|
- In addition to zero or more rows, each <type>db_res_t</type> object contains also an array
|
|
|
- of <type>db_key_t</type> objects. The objects represent keys (names of columns).
|
|
|
- </para>
|
|
|
- <programlisting format="linespecific">
|
|
|
-typedef struct db_res {
|
|
|
- struct {
|
|
|
- db_key_t* keys; /* Array of column names */
|
|
|
- db_type_t* types; /* Array of column types */
|
|
|
- int n; /* Number of columns */
|
|
|
- } col;
|
|
|
- struct db_row* rows; /* Array of rows */
|
|
|
- int n; /* Number of rows */
|
|
|
-} db_res_t;
|
|
|
-</programlisting>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">RES_NAMES(res)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you want to obtain pointer to an array of cell names.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>RES_NAMES Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-db_key_t* column_names = ROW_NAMES(row);
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">RES_COL_N(res)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you want to get the number of columns in the result.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>RES_COL_N Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-int ncol = RES_COL_N(res);
|
|
|
-for(i = 0; i < ncol; i++) {
|
|
|
- /* do something with the column */
|
|
|
-}
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">RES_ROWS(res)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to obtain pointer to array of rows.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>RES_ROWS Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-db_row_t* rows = RES_ROWS(res);
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <function moreinfo="none">RES_ROW_N(res)</function> Macro.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Use this macro if you need to obtain the number of rows in the result.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>RES_ROW_N Macro</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-...
|
|
|
-int n = RES_ROW_N(res);
|
|
|
-...
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section> <!-- type-db-res -->
|
|
|
- </section> <!-- data-types -->
|
|
|
-
|
|
|
- <section id="db-functions">
|
|
|
- <title>Functions</title>
|
|
|
- <para>
|
|
|
- There are several functions that implement the database <acronym>API</acronym> logic. All function
|
|
|
- names start with db_ prefix, except <function moreinfo="none">bind_dbmod</function>.
|
|
|
- <function moreinfo="none">bind_dbmod</function> is implemented in <filename moreinfo="none">db.c</filename>
|
|
|
- file, all other functions are implemented in a standalone module.
|
|
|
- Detailed description of functions follows.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section id="bind-dbmod">
|
|
|
- <title><function moreinfo="none">bind_dbmod</function></title>
|
|
|
- <para>
|
|
|
- This function is special, it's only purpose is to call <function moreinfo="none">find_export</function>
|
|
|
- function in the <acronym>SER</acronym> core and find addresses of all other functions (starting with db_
|
|
|
- prefix). This function <emphasis>MUST</emphasis> be called <emphasis>FIRST</emphasis> !
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">bind_dbmod</function></funcdef>
|
|
|
- <void>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes no parameters.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if it was able to find addresses of all other
|
|
|
- functions, otherwise value < 0 is returned.
|
|
|
- </para>
|
|
|
- </section> <!-- bin-dbmod -->
|
|
|
-
|
|
|
- <section id="db-init">
|
|
|
- <title><function moreinfo="none">db_init</function></title>
|
|
|
- <para>
|
|
|
- Use this function to initialize the database <acronym>API</acronym> and open a new database
|
|
|
- connection. This function must be called after <function moreinfo="none">bind_dbmod</function>
|
|
|
- but before any other function is called.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>db_con_t* <function moreinfo="none">db_init</function></funcdef>
|
|
|
- <paramdef>const char* <parameter moreinfo="none">_sql_url</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes one parameter, the parameter must contain database
|
|
|
- connection <acronym>URL</acronym>. The <acronym>URL</acronym> is of the form
|
|
|
- mysql://username:password@host:port/database where:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>username</emphasis> - Username to use when logging into database (optional).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>password</emphasis> - Password if it was set (optional).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>host</emphasis> - Hostname or IP address of the host
|
|
|
- where database server lives (mandatory).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>port</emphasis> - Port number of the server if the port
|
|
|
- differs from default value (optional).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>database</emphasis> - If the database server supports
|
|
|
- multiple databases, you must specify name of the database (optional).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns pointer to <type>db_con_t</type>* representing the connection if it was
|
|
|
- successful, otherwise 0 is returned.
|
|
|
- </para>
|
|
|
- </section> <!-- db-init -->
|
|
|
-
|
|
|
- <section id="db-close">
|
|
|
- <title><function moreinfo="none">db_close</function></title>
|
|
|
- <para>
|
|
|
- The function closes previously open connection and frees all previously
|
|
|
- allocated memory. The function <function moreinfo="none">db_close</function> must be the very last
|
|
|
- function called.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>void <function moreinfo="none">db_close</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes one parameter, this parameter is a pointer to <type>db_con_t</type>
|
|
|
- structure representing database connection that should be closed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Function doesn't return anything.
|
|
|
- </para>
|
|
|
- </section> <!-- db-close -->
|
|
|
-
|
|
|
- <section id="db-query">
|
|
|
- <title><function moreinfo="none">db_query</function></title>
|
|
|
- <para>
|
|
|
- This function implements SELECT <acronym>SQL</acronym> directive.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">db_query</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
|
|
|
- <paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_c</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">_nc</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_o</parameter></paramdef>
|
|
|
- <paramdef>db_res_t** <parameter moreinfo="none">_r</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes 8 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_h</emphasis> - Database connection handle.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_k</emphasis> - Array of column names that will be compared and
|
|
|
- their values must match.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_v</emphasis> - Array of values, columns specified in _k parameter must match
|
|
|
- these values.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_c</emphasis> - Array of column names that you are interested in.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_n</emphasis> - Number of key-value pairs to match in _k and _v parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_nc</emphasis> - Number of columns in _c parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_o</emphasis> - Order by.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>_r</emphasis> - Address of variable where pointer to the result will be stored.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- If _k and _v parameters are NULL and _n is zero, you will get the whole table.
|
|
|
- If _c is NULL and _nc is zero, you will get all table columns in the result
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- _r will point to a dynamically allocated structure, it is necessary to call
|
|
|
- db_free_result function once you are finished with the result.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Strings in the result are not duplicated, they will be discarded if you call
|
|
|
- db_free_result, make a copy yourself if you need to keep it after db_free_result.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- You must call db_free_result <emphasis>BEFORE</emphasis> you can call db_query again !
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if everything is OK, otherwise value < 0 is returned.
|
|
|
- </para>
|
|
|
- </section> <!-- db-query -->
|
|
|
-
|
|
|
- <section id="db-free-query">
|
|
|
- <title><function moreinfo="none">db_free_result</function></title>
|
|
|
- <para>
|
|
|
- This function frees all memory allocated previously in <function moreinfo="none">db_query</function>,
|
|
|
- it is necessary to call this function for a <type>db_res_t</type> structure if you don't need the
|
|
|
- structure anymore. You must call this function <emphasis>BEFORE</emphasis> you call
|
|
|
- <function moreinfo="none">db_query</function> again !
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">db_free_result</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- <paramdef>db_res_t* <parameter moreinfo="none">_r</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes 2 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_h</parameter> - Database connection handle.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_r</parameter> - Pointer to db_res_t structure to destroy.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if everything is OK, otherwise the function returns
|
|
|
- value < 0.
|
|
|
- </para>
|
|
|
- </section> <!-- db-free-query -->
|
|
|
-
|
|
|
- <section id="db-insert">
|
|
|
- <title><function moreinfo="none">db_insert</function></title>
|
|
|
- <para>
|
|
|
- This function implements INSERT SQL directive, you can insert one or more
|
|
|
- rows in a table using this function.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">db_insert</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
|
|
|
- <paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes 4 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_h</parameter> - Database connection handle.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_k</parameter> - Array of keys (column names).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_v</parameter> - Array of values for keys specified in _k parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_n</parameter> - Number of keys-value pairs int _k and _v parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if everything is OK, otherwise the function returns
|
|
|
- value < 0.
|
|
|
- </para>
|
|
|
- </section> <!-- db-insert -->
|
|
|
-
|
|
|
- <section id="db-delete">
|
|
|
- <title><function moreinfo="none">db_delete</function></title>
|
|
|
- <para>
|
|
|
- This function implements DELETE SQL directive, it is possible to delete one or
|
|
|
- more rows from a table.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">db_delete</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
|
|
|
- <paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes 4 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_h</parameter> - Database connection handle.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_k</parameter> - Array of keys (column names) that will be matched.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_v</parameter> - Array of values that the row must match
|
|
|
- to be deleted.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_n</parameter> - Number of keys-value parameters in _k and _v
|
|
|
- parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- If _k is NULL and _v is NULL and _n is zero, all rows are deleted (table will
|
|
|
- be empty).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if everything is OK, otherwise the function returns
|
|
|
- value < 0.
|
|
|
- </para>
|
|
|
- </section> <!-- db-delete -->
|
|
|
-
|
|
|
- <section id="db-update">
|
|
|
- <title><function moreinfo="none">db_update</function></title>
|
|
|
- <para>
|
|
|
- The function implements UPDATE SQL directive. It is possible to modify one
|
|
|
- or more rows in a table using this function.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">db_update</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_k</parameter></paramdef>
|
|
|
- <paramdef>db_val_t* <parameter moreinfo="none">_v</parameter></paramdef>
|
|
|
- <paramdef>db_key_t* <parameter moreinfo="none">_uk</parameter></paramdef>
|
|
|
- <paramdef>db_val_t* <parameter moreinfo="none">_uv</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">_n</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">_un</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes 7 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_h</parameter> - Database connection handle.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_k</parameter> - Array of keys (column names) that will be matched.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_v</parameter> - Array of values that the row must match
|
|
|
- to be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_uk</parameter> - Array of keys (column names) that will be modified.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_uv</parameter> - New values for keys specified in _k parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_n</parameter> - Number of key-value pairs in _k and _v parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_un</parameter> - Number of key-value pairs
|
|
|
- in _uk and _uv parameters.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if everything is OK, otherwise the function returns
|
|
|
- value < 0.
|
|
|
- </para>
|
|
|
- </section> <!-- db-update -->
|
|
|
-
|
|
|
- <section id="db-use-table">
|
|
|
- <title><function moreinfo="none">db_use_table</function></title>
|
|
|
- <para>
|
|
|
- The function db_use_table takes a table name and stores it in db_con_t structure.
|
|
|
- All subsequent operations (insert, delete, update, query) are performed on
|
|
|
- that table.
|
|
|
- </para>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">db_use-table</function></funcdef>
|
|
|
- <paramdef>db_con_t* <parameter moreinfo="none">_h</parameter></paramdef>
|
|
|
- <paramdef>cons char* <parameter moreinfo="none">_t</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function takes 2 parameters:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_h</parameter> - Database connection handle.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <parameter moreinfo="none">_t</parameter> - Table name.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The function returns 0 if everything is OK, otherwise the function returns
|
|
|
- value < 0.
|
|
|
- </para>
|
|
|
- </section> <!-- db-use-table -->
|
|
|
- </section> <!-- db-functions -->
|
|
|
- </chapter> <!-- db-interface -->
|
|
|
-
|
|
|
-<!--
|
|
|
- <chapter id="fifo-server">
|
|
|
- <title>FIFO Server</title>
|
|
|
- <para>
|
|
|
- TBD.
|
|
|
- </para>
|
|
|
- </chapter>
|
|
|
--->
|
|
|
-
|
|
|
- <chapter id="basic-modules">
|
|
|
- <title>Basic Modules</title>
|
|
|
- <section id="auth">
|
|
|
- <title>Digest Authentication</title>
|
|
|
- <para>The module exports functions needed for digest authentication.</para>
|
|
|
- <para>
|
|
|
- The module depends on:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>mysql</emphasis> - Used as interface to database.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <emphasis>sl</emphasis> - Used for stateless replies.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>db_url</varname> - Database url string in form
|
|
|
- <quote>mysql://<user>:<pass>@host/database</quote>.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>mysql://serro:47serro11@localhost/ser</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>user_column</varname> - Name of column containing usernames in subscriber table.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>user</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>realm_column</varname> - Name of column containing realm in subscriber table.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>realm</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>password_column</varname> - Name of column containing
|
|
|
- (plaintext passwords)/(ha1 strings) if calculate_ha1 parameter is set to true/false.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>ha1</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>password_column_2</varname> - The parameter can be used if and only if USER_DOMAIN_HACK
|
|
|
- macro is set in defs.h header file. The column of this name contains
|
|
|
- alternate ha1 strings calculated from username containing also
|
|
|
- domain, for example username="[email protected]". This hack is
|
|
|
- necessary for some broken user agents. The parameter has no
|
|
|
- meaning if "calculate_ha1" is set to true.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>ha1b</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>secret</varname> - Nonce secret phrase.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: Randomly generated string.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>group_table</varname> - Name of table containing group definitions.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>grp</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>group_user_column</varname> - Name of column containing usernames in group table.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>user</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>group_group_column</varname> - Name of column containing groups in group table.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>grp</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>calculate_ha1</varname> - If set to true, auth module assumes that
|
|
|
- <quote>password_column</quote> contains plaintext passwords and ha1 string will be calculated
|
|
|
- at runtime. If set to false, "password_column" must contain pre-calculated ha1 strings.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: false
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>nonce_expire</varname> - Every nonce is valid only for a limited amount of time. This
|
|
|
- parameter specifies nonce validity interval in seconds.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 300
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>retry_count</varname> - This parameter specifies how many times a user is allowed to
|
|
|
- retry authentication with incorrect credentials. After that
|
|
|
- the user will receive 403 Forbidden and must retry with different
|
|
|
- credentials. This should prevent DoS attacks from misconfigured
|
|
|
- user agents which try to authenticate with incorrect password
|
|
|
- again and again and again.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 5
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">www_authorize</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function checks credentials in Authorization header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>realm</varname> - Realm string
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>table</varname> - Subscriber table name
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>www_authorize</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-if (!www_authorize( "iptel.org", "subscriber" )) {
|
|
|
- www_challenge( "iptel.org", "0");
|
|
|
- break;
|
|
|
-}
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">proxy_authorize</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function checks credentials in Proxy-Authorization header field.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>realm</varname> - Realm string
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>table</varname> - Subscriber table name
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>proxy_authorize</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-if (!proxy_authorize( "iptel.org", "subscriber" )) {
|
|
|
- proxy_challenge( "iptel.org", "0");
|
|
|
- break;
|
|
|
-}
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">www_challenge</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">qop</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Challenges a user agent using WWW-Authenticate header
|
|
|
- field. The second parameter specifies if qop parameter
|
|
|
- (according to rfc2617) should be used or not.
|
|
|
- (Turning off is useful primarily to make UAC happy, which
|
|
|
- have a broken qop implementation, particularly M$ Messenger 4.6).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>realm</varname> - Realm string
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>qop</varname> - Qop string, <quote>1</quote> means use qop parameter
|
|
|
- <quote>0</quote> means do not use qop parameter.
|
|
|
-
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">proxy_challenge</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">realm</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">qop</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Challenges a user agent using Proxy-Authenticate header
|
|
|
- field. The second parameter specifies if qop parameter
|
|
|
- (according to rfc2617) should be used or not.
|
|
|
- (Turning off is useful primarily to make UAC happy, which
|
|
|
- have a broken qop implementation, particularly M$ Messenger 4.6).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>realm</varname> - Realm string
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>qop</varname> - Qop string, <quote>1</quote> means use qop parameter
|
|
|
- <quote>0</quote> means do not use qop parameter.
|
|
|
-
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">is_user</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">username</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Checks if the specified username and matches the username
|
|
|
- in credentials.
|
|
|
- Call after *_authorize, otherwise an error will be issued.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>username</varname> - Username string.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">is_in_group</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">group</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Checks if the user specified in credentials is member of
|
|
|
- given group
|
|
|
- Call after *_authorize, otherwise an error will be issued.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>group</varname> - Group name.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">check_to</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Checks if the username given in credentials and username in
|
|
|
- To header field are equal
|
|
|
- Call after *_authorize, otherwise an error will be issued.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>check_to</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-if (method=="REGISTER" & proxy_authorize("iptel.org", "subscriber" ) {
|
|
|
- if (!check_to) {
|
|
|
- sl_send_reply("403", "cheating: user!=to");
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">check_from</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Checks if the username given in credentials and username in
|
|
|
- From header field are equal.
|
|
|
- Call after *_authorize, otherwise an error will be issued.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">consume_credentials</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Removes previously authorized credentials from the message.
|
|
|
- The function must be called after {www,proxy}_authorize.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">is_user_in</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">hf</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">group</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Checks, if the user is in specified table.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>hf</varname> - Use username in this header field, the following values
|
|
|
- are recognized:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <quote>From</quote> - Extract username from From URI.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <quote>To</quote> - Extract username from To URI.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <quote>Request-URI</quote> - Extract username from Request-URI.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <quote>credentials</quote> - Use username digest parameter.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>group</varname> - Group name.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
- </section> <!-- auth -->
|
|
|
-
|
|
|
-
|
|
|
- <section id="max-fwd">
|
|
|
- <title>Max Forwards</title>
|
|
|
- <para>
|
|
|
- Implements all the operations regarding MAX-Forward header, like adding it (if
|
|
|
- not present) or decrementing and checking the value of the existent one.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Module dependencies: none.
|
|
|
- </para>
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
- <para>
|
|
|
- None.
|
|
|
- </para>
|
|
|
- </section>
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">mf_process_maxfwd_header</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">max_value</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- If no Max-Forwards header is present in the received request, a header will be
|
|
|
- added having the original value equal with "max_value". An OK code is returned
|
|
|
- by the function.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- If a Max-Forwards header is already present, its value will be decremented. If
|
|
|
- after this operation its value will be positive non-zero, an OK code will be
|
|
|
- returned. Otherwise (for a zero value) an error code will be returned.
|
|
|
- Note that an error code will be also returned if the SIP message couldn't
|
|
|
- be parsed or if the Max-Forwards header's body invalid (non numerical string or
|
|
|
- negative numerical value)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Parameter s is not used.
|
|
|
- </para>
|
|
|
- </section>
|
|
|
-
|
|
|
- </section> <!-- max-fwd -->
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <section id="registrar">
|
|
|
- <title>Registrar</title>
|
|
|
- <para>The module contains REGISTER processing logic.</para>
|
|
|
- <para>
|
|
|
- The module depends on:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>usrloc</emphasis> - User location module.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para><emphasis>sl</emphasis> - Used for stateless replies.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>default_expires</varname> - If the processed message contains neither Expires HFs nor
|
|
|
- expires contact parameters, this value will be used
|
|
|
- for newly created usrloc records. The parameter contains
|
|
|
- number of second to expire (for example use 3600 for one hour).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 3600
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>default_q</varname> - The parameter represents default q value for new contacts. Because
|
|
|
- ser doesn't support float parameter types, the value in the parameter
|
|
|
- is divided by 100 and stored as float. For example, if you want default_q
|
|
|
- to be 0.38, use value 38 here.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 0
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>append_branches</varname> - The parameter controls how lookup function processes
|
|
|
- multiple contacts. If there are multiple contacts for the given username in usrloc and this
|
|
|
- parameter is set to 1, Request-URI will be overwritten with the highest-q
|
|
|
- rated contact and the rest will be appended to sip_msg structure and can
|
|
|
- be later used by tm for forking. If the parameter is set to 0, only
|
|
|
- Request-URI will be overwritten with the highest-q rated contact and the
|
|
|
- rest will be left unprocessed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 1
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
- <itemizedlist>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">save</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function processes a REGISTER message. It can add, remove or modify
|
|
|
- usrloc records depending on Contact and Expires HFs in the REGISTER message.
|
|
|
- On success, 200 OK will be returned listing all contacts that are currently
|
|
|
- in usrloc. On an error, error message will be send with a short description
|
|
|
- in reason phrase.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>table</varname> - Table name where contacts should be stored.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">lookup</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">table</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The functions extracts username from Request-URI and tries to find all contacts
|
|
|
- for the username in usrloc. If there are no such contacts, -1 will be returned.
|
|
|
- If there are such contacts, Request-URI will be overwritten with the contact that
|
|
|
- has the highest q value and optionally the rest will be appended to the message
|
|
|
- (depending on append_branches parameter value).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>table</varname> - Name of table that should be used for the lookup.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
- </section> <!-- registrar -->
|
|
|
-
|
|
|
-
|
|
|
- <section id="rr">
|
|
|
- <title>Record-Routing</title>
|
|
|
- <para>Record Routing module.</para>
|
|
|
- <para>
|
|
|
- The module depends on: None.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
- <para>
|
|
|
- None.
|
|
|
- </para>
|
|
|
- </section>
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">rewriteFromRoute</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- If there are any Route HFs in the message, the function
|
|
|
- takes the first one, rewrites Request-URI with it's value
|
|
|
- and removes the first URI from Route HFs.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">addRecordRoute</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function adds a new Record-Route header field. The
|
|
|
- header field will be inserted in the message before any
|
|
|
- other Record-Route header fields.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
- </section> <!-- rr -->
|
|
|
-
|
|
|
-
|
|
|
- <section id="sl">
|
|
|
- <title>Stateless Replies</title>
|
|
|
- <para>
|
|
|
- The SL module provide possibilities to send stateless replies for the current
|
|
|
- request. Additional, a filter function is available for checking the ACK
|
|
|
- requests generated by sending a SL reply to a INVITE req. Also, offers the
|
|
|
- possibility to send explanatory SL replies in case of an internal error.
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- For the SL module to be able to recognize the ACKs generated by INVITE's
|
|
|
- replies sent by itself, all the sent replies will have attached to TO header
|
|
|
- a "tag" param. having a unique value (that was random generated at ser
|
|
|
- startup).When an ACK is received, the TO tag param tag is checked if
|
|
|
- corresponds - all UAS MUST copy the TO tag from replies into ACK requests!
|
|
|
- TO speed up the filtering process, the module uses a timeout mechanism. When
|
|
|
- a reply is sent, a timer us set. As time as the timer is valid, The incoming
|
|
|
- ACK requests will be checked using TO tag value Once the timer expires, all
|
|
|
- the ACK are let through - a long time passed till it sent a reply, so it does
|
|
|
- not expect any ACK that have to be blocked.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
- <para>None.</para>
|
|
|
- </section>
|
|
|
-
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">sl_send_reply</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">code</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">text_reason</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- For the current request, a reply is sent back having the given code and text
|
|
|
- reason. The reply is sent stateless, totally independent of the Transaction
|
|
|
- module and with no retransmission for the INVITE's replies.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>code</varname> - Reply code to be used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>text_reason</varname> - Reason phrase to be used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">sl_filter_ACK</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Identifies and blocks the ACK requests generated by INVITE's replies sent
|
|
|
- using the sl_send_reply() or sl_send_error() functions.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">sl_reply_error</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Identifies and blocks the ACK requests generated by INVITE's replies sent
|
|
|
- using the sl_send_reply() or sl_send_error() functions.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
- </section> <!-- sl -->
|
|
|
-
|
|
|
- <section id="tm">
|
|
|
- <title>Transaction Module</title>
|
|
|
- <para>
|
|
|
- The module implements logic necessary to manage SIP transactions.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- The module depends on: None.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- TM Module enables stateful processing of SIP transactions.
|
|
|
- The main use of stateful logic, which is costly in terms of
|
|
|
- memory and CPU, is some services inherently need state.
|
|
|
- For example, transaction-based accounting (module acc) needs
|
|
|
- to process transaction state as opposed to individual messages,
|
|
|
- and any kinds of forking must be implemented statefully.
|
|
|
- Other use of stateful processing is it trading CPU caused by
|
|
|
- retransmission processing for memory. That makes however only
|
|
|
- sense if CPU consumption per request is huge. For example,
|
|
|
- if you want to avoid costly DNS resolution for every retransmission
|
|
|
- of a request to an unresolvable destination, use stateful mode.
|
|
|
- Then, only the initial message burdens server by DNS queries,
|
|
|
- subsequent retransmissions will be dropped and will not result in
|
|
|
- more processes blocked by DNS resolution. The price is more
|
|
|
- memory consumption and higher processing latency.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- From user's perspective, there are two major functions :
|
|
|
- t_relay and t_relay_to. Both setup transaction state,
|
|
|
- absorb retransmissions from upstream, generate downstream
|
|
|
- retransmissions and correlate replies to requests.
|
|
|
- t_relay forwards to current uri (be it original request's
|
|
|
- uri or a uri changed by some of uri-modifying functions,
|
|
|
- such as sethost). t_relay_to forwards to a specific address.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- In general, if TM is used, it copies clones of received SIP
|
|
|
- messages in shared memory. That costs the memory and also CPU
|
|
|
- time (memcpys, lookups, shmem locks, etc.) Note that non-TM
|
|
|
- functions operate over the received message in private memory,
|
|
|
- that means that any core operations will have no effect on
|
|
|
- statefully processed messages after creating the transactional
|
|
|
- state. For example, calling addRecordRoute *after* t_relay
|
|
|
- is pretty useless, as the RR is added to privately held message
|
|
|
- whereas its TM clone is being forwarded.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- TM is quite big and uneasy to program -- lot of mutexes, shared
|
|
|
- memory access, malloc & free, timers -- you really need to be careful
|
|
|
- when you do anything. To simplify TM programming, there is the
|
|
|
- instrument of callbacks. The callback mechanisms allow programmers
|
|
|
- to register their functions to specific event. See t_hooks.h
|
|
|
- for a list of possible events.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Other things programmers may want to know is UAC -- it is
|
|
|
- a very simplistic code which allows you to generate your own
|
|
|
- transactions. Particularly useful for things like NOTIFYs or
|
|
|
- IM gateways. The UAC takes care of all the transaction
|
|
|
- machinery: retransmissions , FR timeouts, forking, etc.
|
|
|
- See t_uac prototype in uac.h for more details. Who wants to
|
|
|
- see the transaction result may register for a callback.
|
|
|
- </para>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>External Usage of TM</title>
|
|
|
- <para>
|
|
|
- There are applications which would like to generate SIP
|
|
|
- transactions without too big involvement in SIP stack, transaction
|
|
|
- management, etc. An example of such an application
|
|
|
- is sending instant messages from a website. To address needs
|
|
|
- of such apps, SER accepts requests for new transactions via
|
|
|
- fifo pipes too. If you want to enable this feature, start
|
|
|
- FIFO server by configuration option
|
|
|
- fifo=<quote>/tmp/filename</quote>
|
|
|
- Then, an application can easily launch a new transaction by
|
|
|
- writing a transaction request to this named pipe. The request
|
|
|
- must follow very simple format, which is
|
|
|
- <programlisting format="linespecific">
|
|
|
-:t_uac:[<file_name>]\n
|
|
|
-<method>\n
|
|
|
-<dst uri>\n
|
|
|
-<CR_separated_headers>\n
|
|
|
-<body>\n
|
|
|
-\n
|
|
|
-\n
|
|
|
-</programlisting>
|
|
|
- (Filename is to where a report will be dumped. ser assumes /tmp
|
|
|
- as file's directory.)
|
|
|
- </para>
|
|
|
-
|
|
|
- <para>
|
|
|
- A convenience library fifo_uac.c implements this simple functionality.
|
|
|
- Note the the request write must be atomic, otherwise the request
|
|
|
- might get intermixes with writes from other writers.
|
|
|
- You can easily use it via Unix command-line tools, see the following
|
|
|
- example:
|
|
|
- <example>
|
|
|
- <title>UAC</title>
|
|
|
- <screen format="linespecific">
|
|
|
-[jiri@bat jiri]$ cat > /tmp/fifo
|
|
|
-:t_uac:xxx
|
|
|
-MESSAGE
|
|
|
-sip:[email protected]
|
|
|
-header:value
|
|
|
-foo:bar
|
|
|
-bznk:hjhjk
|
|
|
-p_header: p_value
|
|
|
-
|
|
|
-body body body
|
|
|
-yet body
|
|
|
-end of body
|
|
|
-</screen>
|
|
|
- </example>
|
|
|
- Or use an example file and call cat test/transaction.fifo > /tmp/fifo
|
|
|
- </para>
|
|
|
- </section>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
- <itemizedlist>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>fr_timer</varname> - Timer which hits if no final reply for a request or
|
|
|
- ACK for a negative INVITE reply arrives.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (seconds)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 30
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>fr_inv_timer</varname> - Timer which hits if no final reply for an INVITE
|
|
|
- arrives after a provisional message was received.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (seconds)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 120
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>wt_timer</varname> - Time for which a transaction stays in memory to absorb
|
|
|
- delayed messages after it completed; also, when this
|
|
|
- timer hits, retransmission of local cancels is stopped
|
|
|
- (a puristic but complex behavior would be not to enter
|
|
|
- wait state until local branches are finished by a final
|
|
|
- reply or FR timer -- we simplified)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (seconds)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 5
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>delete_timer</varname> - Time after which a to-be-deleted transaction currently
|
|
|
- ref-ed by a process will be tried to be deleted again.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (seconds)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 2
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>retr_timer1p1, 2, 3</varname> - Retransmission period.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (seconds)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: RETR_T1=1, 2*RETR_T1, 4*RETR_T1
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>retr_timer2</varname> - Maximum retransmission period.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (seconds)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: RETR_T2=4
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>noisy_ctimer</varname> - If set, on FR timer INVITE transactions will be
|
|
|
- explicitly canceled if possible, silently dropped
|
|
|
- otherwise; preferably, it is turned off to allow
|
|
|
- very long ringing; this behavior is overridden if
|
|
|
- a request is forked, or some functionality explicitly
|
|
|
- turned it off for a transaction (like acc does to avoid
|
|
|
- unaccounted transactions due to expired timer).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type> (boolean)
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 0 (false)
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
-
|
|
|
- <itemizedlist>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_relay_to</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">ip_address</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">port_number</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Relay a message statefully to a fixed destination; this along with
|
|
|
- t_relay is the function most users want to use -- all other are
|
|
|
- mostly for programming; programmers interested in writing TM
|
|
|
- logic should review how t_relay is implemented in tm.c and how
|
|
|
- TM callbacks work.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>ip_address</varname> - IP address of the destination.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>port_number</varname> - Port of the destination.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>t_relay_to</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-if (!t_relay_to("1.2.3.4", "5060")) {
|
|
|
- sl_reply_error();
|
|
|
- break;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_relay</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Relay a message statefully to destination indicated in current URI;
|
|
|
- (if the original URI was rewritten by UsrLoc, RR, strip/prefix,
|
|
|
- etc., the new URI will be taken); returns a negative value on
|
|
|
- failure -- you may still want to send a negative reply upstream
|
|
|
- statelessly not to leave upstream UAC in lurch.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>t_relay</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-if (!t_relay()) {
|
|
|
- sl_reply_error();
|
|
|
- break;
|
|
|
-};
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_on_negative</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">reply_route</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Sets reply routing block, to which control is passed after
|
|
|
- a transaction completed with a negative result but before
|
|
|
- sending a final reply; In the referred block, you can
|
|
|
- either start a new branch (good for services such as
|
|
|
- forward_on_no_reply) or send a final reply on your own
|
|
|
- (good for example for message silo, which received
|
|
|
- a negative reply from upstream and wants to tell
|
|
|
- upstream "202 I will take care of it"); Note that the
|
|
|
- set of command which are usable within reply_routes is
|
|
|
- strictly limited to rewriting URI, initiating new branches,
|
|
|
- logging, and sending 'unsafe' replies (t_reply_unsafe). Any
|
|
|
- other commands may result in unpredictable behavior and
|
|
|
- possible server failure.
|
|
|
- Note that whenever reply_route is entered, uri is reset to
|
|
|
- value which it had on relaying. If it temporarily changed
|
|
|
- during a reply_route processing, subsequent reply_route
|
|
|
- will ignore the changed value and use again the original
|
|
|
- one.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>reply_route</varname> - Reply routing block.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s</varname> - Not used.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>t_on_negative</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-route {
|
|
|
- t_on_negative("1");
|
|
|
- t_relay();
|
|
|
-} reply_route[1] {
|
|
|
- revert_uri();
|
|
|
- setuser("voicemail");
|
|
|
- append_branch();
|
|
|
-}
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_newtran</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Creates a new transaction, returns a negative value on
|
|
|
- error; this is the only way a script can add a new transaction
|
|
|
- in an atomic way; typically, it is used to deploy a UAS
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- <example>
|
|
|
- <title>t_newtran</title>
|
|
|
- <programlisting format="linespecific">
|
|
|
-if (t_newtran()) {
|
|
|
- log("UAS logic");
|
|
|
- t_reply("999","hello");
|
|
|
-} else sl_reply_error();
|
|
|
-</programlisting>
|
|
|
- </example>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_reply</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">code</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">reason_phrase</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Sends a stateful reply after a transaction has been
|
|
|
- established; see t_newtran for usage; note: never use
|
|
|
- t_reply from within reply_route ... always use t_reply_unsafe.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>code</varname> - Code of the response.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>reason_phrase</varname> - Reason phrase of the response.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_lookup_request</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Checks if a transaction exists; returns a positive value
|
|
|
- if so, negative otherwise; most likely you will not want
|
|
|
- to use it, as a typical application of a look-up is to
|
|
|
- introduce a new transaction if none was found; however
|
|
|
- this is safely (atomically) done using t_newtran.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_retransmit_reply</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Retransmits a reply sent previously by UAS transaction.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_release</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s1</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s2</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Remove transaction from memory (it will be first put on
|
|
|
- a wait timer to absorb delayed messages).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s1</varname> - Not used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s2</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_forward_noack</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">ip</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">port</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Mainly for internal -- forward a non-ACK request statefully.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>ip</varname> - IP address.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>port</varname> - Port number.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">register_tmcb</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">cb_type</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">cb_func</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- For programmatic use only -- register a function to be called
|
|
|
- back on an event; see t_hooks.h for more details.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>cb_type</varname> - Callback type.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>cb_func</varname> - Callback function.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">load_tm</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">import_structure</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">s</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- For programmatic use only -- import exported TM functions;
|
|
|
- see the acc module for an example of use.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>import_structure</varname> - Structure where pointers to tm functions will be stored.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>s</varname> - Not used.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">t_reply_unsafe</function></funcdef>
|
|
|
- <paramdef>struct sip_msg* <parameter moreinfo="none">msg</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">code</parameter></paramdef>
|
|
|
- <paramdef>char* <parameter moreinfo="none">reason_phrase</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Sends a stateful reply after a transaction has been
|
|
|
- established; it can only be used from reply processing;
|
|
|
- using it from regular processing will introduce erroneous
|
|
|
- conditions; using t_reply from reply_processing will
|
|
|
- introduce a deadlock.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>code</varname> - Code of the reply.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>reason_phrase</varname> - Reason phrase of the reply.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Known Issues</title>
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>Need to revisit profiling again.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Review whether there is not potential for to-tag rewriting and ACK matching.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>We don't have authentication merging on forking.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Branch tid is not used yet.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>local ACK/CANCELs copy'n'pastes Route and ignores deleted Routes</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>6xx should be delayed.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Possibly, performance could be improved by not parsing non-INVITEs,
|
|
|
- as they do not be replied with 100, and do not result in ACK/CANCELs,
|
|
|
- and other things which take parsing. However, we need to rethink
|
|
|
- whether we don't need parsed headers later for something else.
|
|
|
- Remember, when we now conserver a request in sh_mem, we can't apply
|
|
|
- any pkg_mem operations to it any more. (that might be redesigned too).
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- t_replicate should be done more cleanly -- Vias, Routes, etc. should
|
|
|
- be removed from a message prior to replicating it.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>SNMP support.</para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Lookup fails to recognize subsequent requests which have additional
|
|
|
- leading spaces in header field values.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- Make UAC session-aware (as opposed to just transaction aware) -- needed
|
|
|
- for keeping SUB-NOT dialog state, etc. Currently, there are only
|
|
|
- place-holders for in in TM.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>Places labeled with "HACK" strongly deserve beautification.</para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
- </section> <!-- tm -->
|
|
|
-
|
|
|
- <section id="usrloc">
|
|
|
- <title>User Location Module</title>
|
|
|
- <para>Support for location of users.</para>
|
|
|
- <para>Module depends on: Optionally mysql (if configured for persistence)</para>
|
|
|
-
|
|
|
- <important>
|
|
|
- <para>
|
|
|
- Usrloc is convenient module only. It's functions cannot be called from scripts
|
|
|
- directly, but are used by registrar module internally. This module will be
|
|
|
- utilized by more modules in the future and therefore it is standalone. Use
|
|
|
- registrar module functions if you need usrloc support in your scripts.
|
|
|
- </para>
|
|
|
- </important>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Parameters</title>
|
|
|
- <itemizedlist>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>user_col</varname> - Name of column containing usernames.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>user</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>contact_col</varname> - Name of column containing contacts.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>contact</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>expires_col</varname> - Name of column containing expires.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>expires</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>q_col</varname> - Name of column containing q values.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>q</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>callid_col</varname> - Name of column containing callids.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>callid</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>cseq_col</varname> - Name of column containing cseq numbers.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>cseq</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>method_col</varname> - Name of column containing supported methods.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>method</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>db_url</varname> - URL of the database that should be used.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>string</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: <quote>mysql://ser:heslo@localhost/ser</quote>
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>timer_interval</varname> - Number of seconds between two timer runs. The
|
|
|
- module uses timer to delete expired contacts,
|
|
|
- synchronize with database and other tasks, that
|
|
|
- need to be run periodically.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 60 seconds
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- <varname>db_mode</varname> - The usrloc module can utilize database for persistent
|
|
|
- contact storage. If you use database, your contacts
|
|
|
- will survive machine restarts or SW crashes. The
|
|
|
- disadvantage is that accessing database can be very
|
|
|
- time consuming. Therefore, usrloc module implements
|
|
|
- three database accessing modes:
|
|
|
- <itemizedlist>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- 0 - This disables database completely. Only memory
|
|
|
- will be used. Contacts will not survive restart.
|
|
|
- Use this value if you need a really fast usrloc
|
|
|
- and contact persistence is not necessary or is
|
|
|
- provided by other means.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- 1 - <emphasis>Write-Through</emphasis> scheme. All changes to usrloc are
|
|
|
- immediately reflected in database too. This is
|
|
|
- very slow, but very reliable. Use this scheme
|
|
|
- if speed is not your priority but need to make
|
|
|
- sure that no registered contacts will be lost
|
|
|
- during crash or reboot.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- <listitem>
|
|
|
- <para>
|
|
|
- 2 - <emphasis>Write-Back</emphasis> scheme. This is a combination of
|
|
|
- previous two schemes. All changes are made to
|
|
|
- memory and database synchronization is done
|
|
|
- in the timer. The timer deletes all expired contacts
|
|
|
- and flushes all modified or new contacts to database.
|
|
|
- Use this scheme if you encounter high-load peaks and
|
|
|
- want them to process as fast as possible. The mode
|
|
|
- will not help at all if the load is high all the time.
|
|
|
- Also, latency of this mode is much lower than latency
|
|
|
- of mode 1, but slightly higher than latency of mode 0.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Type: <type>integer</type>
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- Default: 0
|
|
|
- </para>
|
|
|
- <warning>
|
|
|
- <para>
|
|
|
- In case of crash or restart contacts that
|
|
|
- are in memory only and haven't been flushed
|
|
|
- yet will get lost. If you want minimize the
|
|
|
- risk, use shorter timer interval.
|
|
|
- </para>
|
|
|
- </warning>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
-
|
|
|
- <section>
|
|
|
- <title>Exported Functions</title>
|
|
|
- <itemizedlist>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_register_domain</function></funcdef>
|
|
|
- <paramdef>const char* <parameter moreinfo="none">name</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function registers a new domain. Domain is just another name
|
|
|
- for table used in registrar. The function is called from fixups
|
|
|
- in registrar. It gets name of the domain as a parameter and returns
|
|
|
- pointer to a new domain structure. The fixup than 'fixes' the
|
|
|
- parameter in registrar so that it will pass the pointer instead of
|
|
|
- the name every time save() or lookup() is called. Some usrloc functions
|
|
|
- get the pointer as parameter when called. For more details see
|
|
|
- implementation of save function in registrar.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>name</varname> - Name of the domain (also called table) to be
|
|
|
- registered.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_insert_urecord</function></funcdef>
|
|
|
- <paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">aor</parameter></paramdef>
|
|
|
- <paramdef>urecord_t** <parameter moreinfo="none">rec</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function creates a new record structure and inserts it in the specified
|
|
|
- domain. The record is structure that contains all the contacts for belonging
|
|
|
- to the specified username.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>domain</varname> - Pointer to domain returned by ul_register_udomain.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>aor</varname> - Address of Record (aka username) of the new record
|
|
|
- (at this time the record will contain no contacts yet).
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>rec</varname> - The newly created record structure.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_delete_urecord</function></funcdef>
|
|
|
- <paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">aor</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function deletes all the contacts bound with the given Address Of Record.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>domain</varname> - Pointer to domain returned by ul_register_udomain.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>aor</varname> - Address of record (aka username) of the record, that should
|
|
|
- be deleted.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_get_urecord</function></funcdef>
|
|
|
- <paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">aor</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function returns pointer to record with given Address of Record.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>domain</varname> - Pointer to domain returned by ul_register_udomain.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>aor</varname> - Address of Record of request record.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_lock_udomain</function></funcdef>
|
|
|
- <paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function lock the specified domain, it means, that no other processes
|
|
|
- will be able to access during the time. This prevents race conditions. Scope
|
|
|
- of the lock is the specified domain, that means, that multiple domain can be
|
|
|
- accessed simultaneously, they don't block each other.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>domain</varname> - Domain to be locked.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_unlock_udomain</function></funcdef>
|
|
|
- <paramdef>udomain_t* <parameter moreinfo="none">domain</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Unlock the specified domain previously locked by ul_lock_udomain.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>domain</varname> - Domain to be unlocked.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_release_urecord</function></funcdef>
|
|
|
- <paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- Do some sanity checks - if all contacts have been removed, delete the entire
|
|
|
- record structure.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>record</varname> - Record to be released.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_insert_ucontact</function></funcdef>
|
|
|
- <paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">contact</parameter></paramdef>
|
|
|
- <paramdef>time_t <parameter moreinfo="none">expires</parameter></paramdef>
|
|
|
- <paramdef>float <parameter moreinfo="none">q</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">callid</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">cseq</parameter></paramdef>
|
|
|
- <paramdef>ucontact_t* <parameter moreinfo="none">cont</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function inserts a new contact in the given record with specified parameters.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>record</varname> - Record in which the contact should be inserted.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>contact</varname> - Contact URL.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>expires</varname> - Expires of the contact in absolute value.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>q</varname> - q value of the contact.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>callid</varname> - Call-ID of the REGISTER message that contained the contact.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>cseq</varname> - CSeq of the REGISTER message that contained the contact.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>cont</varname> - Pointer to newly created structure.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_delete_ucontact</function></funcdef>
|
|
|
- <paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
|
|
|
- <paramdef>ucontact_t* <parameter moreinfo="none">contact</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function deletes given contact from record.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>record</varname> - Record from which the contact should be removed.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>contact</varname> - Contact to be deleted.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_get_ucontact</function></funcdef>
|
|
|
- <paramdef>urecord_t* <parameter moreinfo="none">record</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">contact</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function tries to find contact with given Contact URI and returns
|
|
|
- pointer to structure representing the contact.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>record</varname> - Record to be searched for the contact.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>contact</varname> - URI of the request contact.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
-
|
|
|
-
|
|
|
- <listitem>
|
|
|
- <funcsynopsis>
|
|
|
- <funcprototype>
|
|
|
- <funcdef>int <function moreinfo="none">ul_update_ucontact</function></funcdef>
|
|
|
- <paramdef>ucontact_t* <parameter moreinfo="none">contact</parameter></paramdef>
|
|
|
- <paramdef>time_t <parameter moreinfo="none">expires</parameter></paramdef>
|
|
|
- <paramdef>float <parameter moreinfo="none">q</parameter></paramdef>
|
|
|
- <paramdef>str* <parameter moreinfo="none">callid</parameter></paramdef>
|
|
|
- <paramdef>int <parameter moreinfo="none">cseq</parameter></paramdef>
|
|
|
- </funcprototype>
|
|
|
- </funcsynopsis>
|
|
|
- <para>
|
|
|
- The function updates contact with new values.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>contact</varname> - Contact to be updated.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>expires</varname> - New expires value.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>q</varname> - New q value.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>callid</varname> - New Call-ID.
|
|
|
- </para>
|
|
|
- <para>
|
|
|
- <varname>cseq</varname> - New CSeq.
|
|
|
- </para>
|
|
|
- </listitem>
|
|
|
- </itemizedlist>
|
|
|
- </section>
|
|
|
- </section> <!-- usrloc -->
|
|
|
- </chapter> <!-- basic-modules -->
|
|
|
-
|
|
|
-<!--
|
|
|
-
|
|
|
- jak se prochazi vsechny hlavicky daneho typu
|
|
|
- Jak vlozit header na konec hlavicky
|
|
|
- jak vlozit prvni header
|
|
|
- jak neco vymazat
|
|
|
- jak vlozit header do odpovedi
|
|
|
- jak postupne prochazet headery stejneho typu dokud
|
|
|
- nenaleznu ten pravy
|
|
|
- jak spravne parsovat !!!
|
|
|
- jak se vola destroy, z jakeho procesu, kolikrat
|
|
|
- proc se init modules vola tam, kde se vola
|
|
|
- fix_rls se vola az po ini_modules - proc
|
|
|
- mod_init je vzdycky prvni zavolana funkce modulu !
|
|
|
- nelze destroy data z potomku
|
|
|
- builtin core commands -description
|
|
|
- popsat system proxy
|
|
|
- vsechno spravne prolinkovat
|
|
|
- Popsat flagy
|
|
|
- Dopsat nekam poznamku ze vetsina field pri parsovani nejsou ukoncena
|
|
|
- 0 a ze jsou to pouze pointery a delky do buf bufferu zpravy
|
|
|
- Adding a new header field body parser
|
|
|
- How to parse a header field body
|
|
|
- Jak udelat funkce, ktere nepujdou volat ze skriptu, ale jenom z ostatnich
|
|
|
- modulu.
|
|
|
- FAQ
|
|
|
- Dopsat interface configuration sekci.
|
|
|
- Use command tag
|
|
|
- Use error code tag
|
|
|
- qandaset - FAQ
|
|
|
--->
|
|
|
-</book>
|