123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
- <section id="routing_engine" xmlns:xi="http://www.w3.org/2001/XInclude">
- <sectioninfo>
- <revhistory>
- <revision>
- <revnumber>$Revision$</revnumber>
- <date>$Date$</date>
- </revision>
- </revhistory>
- </sectioninfo>
- <title>The Routing Engine</title>
- <para>
- In a previous section we discussed how routing part of a config file
- gets translated into binary representation. In this section, we will
- discuss how the binary representation is used during message
- processing.
- </para>
- <para>
- Upon a <acronym>SIP</acronym> message receipt, the server performs some
- basic sanity checks and converts the message into
- <structname>sip_msg</structname> structure. After that the Routing
- Engine will start processing the message.
- </para>
- <para>
- The routing engine can be found in file <filename>action.c</filename>.
- </para>
- <para>
- The main function is <function>run_actions.</function> The function
- accepts two parameters. The first parameter is list of actions to be
- processed (Remember, the config file gets translated into array of
- linked lists. Each linked list in the array represents one "route" part
- of the config file). The second parameter is
- <structname>sip_msg</structname> structure representing the message to
- be processed.
- </para>
- <para>
- Upon a receipt of a request, the linked list representing the main
- route part will be processed so the first parameter will be
- <varname>rlist[0]</varname>. (The linked list of main route part is
- always at index 0).
- </para>
- <para>
- The function will then sequentially call <function>do_action</function>
- function for each element of the linked list. Return value of the
- function is important. If the function returns 0, processing of the
- list will be stopped. By returning 0 a command can indicate that
- processing of the message should be stopped and the message will be
- dropped.
- </para>
- <para>
- Modules may export so-called <emphasis>on_break handlers</emphasis>.
- <emphasis>on_break</emphasis> handler is a function, that will be
- called when processing of the linked-list is interrupted (ret ==
- 0). All such handlers will be called when processing of the linked-list
- is finished and ret == 0.
- </para>
- <section id="do_action">
- <title><function>do_action</function> Function</title>
- <para>
- <function>do_action</function> function is core of the routing
- engine. There is a big <function>switch</function> statement. Each
- case of the statements is one command handled by the server core
- itself.
- </para>
- <para>
- The following commands are handled by the <acronym>SER</acronym> core
- itself:
- <function>drop</function>,
- <function>forward</function>,
- <function>send</function>,
- <function>log</function>,
- <function>append_branch</function>,
- <function>len_gt</function>,
- <function>setflag</function>,
- <function>resetflag</function>,
- <function>isflagset</function>,
- <function>setavpflag</function>,
- <function>resetavpflag</function>,
- <function>isavpflagset</function>,
- <function>error</function>,
- <function>route</function>,
- <function>exec</function>,
- <function>revert_uri</function>,
- <function>set_host</function>,
- <function>set_hostport</function>,
- <function>set_user</function>,
- <function>set_userpass</function>,
- <function>set_port</function>,
- <function>set_uri</function>,
- <function>prefix</function>,
- <function>strip</function>,
- <function>if</function>,
- <function>module</function>.
- </para>
- <para>
- Each of the commands is represented by a <emphasis>case</emphasis>
- statement in the switch. (For example, if you are interested in
- implementation of <function>drop</function> command, look at
- "case DROP_T:" statement in the function.
- </para>
- <para>
- The respective commands will be described now.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <function>drop</function> - This command is very simple, it
- simply returns 0 which will result in abortion of
- processing of the request. No other commands after
- <function>drop</function> will be executed.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>forward</function> - The function will forward
- the message further. The message will be either forwarded
- to the Request <acronym>URI</acronym> of the message or to
- <acronym>IP</acronym> or host given as parameter.
- </para>
- <para>
- In the first case, host in the Request
- <acronym>URI</acronym> must be converted into corresponding
- <acronym>IP</acronym> address. Function
- <function>mk_proxy</function> converts hostname to
- corresponding <acronym>IP</acronym> address. The message
- is then sent out using <function>forward_request</function>
- function.
- </para>
- <para>
- In the second case, hostname was converted to
- <acronym>IP</acronym> address in fixup i.e. immediately
- after the config file was compiled into its binary
- representation. The first parameter is pointer to
- <structname>proxy</structname> structure created in the
- fixup and therefore we only need to call
- <function>forward_request</function> here to forward the
- message further.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>send</function> - This functions sends the
- message to a third-party host. The message will be sent out
- as is - i.e. without Request <acronym>URI</acronym> and Via
- altering.
- </para>
- <para>
- Hostname or <acronym>IP</acronym> address of the
- third-party host is specified as a parameter of the
- function.
- </para>
- <para>
- The message will be sent out using
- <function>udp_send</function> directly.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>log</function> - The message given as a parameter
- will be logged using system logger. It can be either
- <command>syslog</command> or <varname>stderr</varname>
- (depends on configuration). The message is logged using
- <function>LOG</function> which is a macro defined in
- <filename>dprint.h</filename> header file.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>append_branch</function> - Append a new
- <acronym>URI</acronym> for forking.
- </para>
- <para>
- More than one destinations may be associated with a single
- <acronym>SIP</acronym> request. If the server was
- configured so, it will use all the destinations and fork
- the request.
- </para>
- <para>
- The server keeps an array of all destinations, that should
- be used when forking. The array and related functions can
- be found in file <filename>dset.c</filename>. There is
- function <function>append_branch</function> which adds a
- new destination to the set.
- </para>
- <para>
- This command simply calls
- <function>append_branch</function> function and adds a new
- destination to the destination set.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>len_gt</function> - The command accepts one
- number as a parameter. It then compares the number with
- length of the message. If the message length is greater or
- equal then the number then 1 will be returned otherwise the
- function returns -1.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>setflag</function> - Sets a flag in the
- message. The command simply calls
- <function>setflags</function> function that will set the
- flag. Fore more information see file
- <filename>flag.c</filename>.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>resetflag</function> - Same as command
- <function>setflag</function> - only resetflag will be
- called instead of setflag.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>isflagset</function> - Test if the flag
- is set or not.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>setavpflag(avp, flag_id)</function> - Sets a flag in the
- AVP(s). The command simply set custom flag of AVP. The flags
- may be used in script using <function>isavpflagset</function>
- or in a module to perform specific operation on marked AVPs.
- Flag identifier must be declared via <emphasis>avpflags</emphasis>
- statement.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>resetavpflag(avp, flag_id)</function> - Same as command
- <function>setavpflag</function> - only resetavpflag will be
- called instead of setavpflag.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>isavpflagset(avp, flag_id)</function> - Test if the avp flag
- is set or not.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>error</function> - Log a message with NOTICE log
- level.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>route</function> - Execute another
- route statement.
- </para>
- <para>
- As we have mentioned already, there can be more that one
- route statement in the config file. One of them is main
- (without number), the other are additional. This command
- makes it possible to execute an additional route statement.
- </para>
- <para>
- The command accepts one parameter which is route statement
- number. First sanity checks over the parameter will be
- performed. If the checks passed, function
- <function>run_actions</function> will be called. The
- function accepts two parameters. The first one is linked
- list to execute, the second one is
- <structname>sip_msg</structname> structure representing the
- message to be processed.
- </para>
- <para>
- As you might remember, each route statement was compiled
- into linked list of commands to be executed and head of the
- linked list was stored in <varname>rlist</varname>
- array. For example, head of linked list representing route
- statement with number 4 will be stored at position 4 in the
- array (position 0 is reserved for the main route
- statement).
- </para>
- <para>
- So the command will simply call
- <function>run_actions(rlist[a->p1.number], msg)</function>
- and that will execute route statement with number given as
- parameter.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>exec</function> - Execute a shell command.
- </para>
- <para>
- The command accepts one parameter of type
- <type>char*</type>. The string given as parameter will be
- passed to <function>system</function> function which will
- in turn execute <function>/bin/sh -c
- <string></function>.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>revert_uri</function> - Revert changes made to
- the Request <acronym>URI</acronym>.
- </para>
- <para>
- If there is a new <acronym>URI</acronym> stored in
- <structfield>new_uri</structfield> of
- <structname>sip_msg</structname> structure, it will be
- freed. The original Request <acronym>URI</acronym> will be
- used when forwarding the message.
- </para>
- <para>
- If there is a valid <acronym>URI</acronym> in
- <structfield>parsed_uri</structfield> field of
- <structname>sip_msg</structname> structure (indicated by
- <structfield>parsed_uri_ok</structfield> field), it will be
- freed too.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>set_host</function> - Change hostname of Request
- <acronym>URI</acronym> to value given as parameter.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- modified, otherwise the original Request
- <acronym>URI</acronym> will be modified.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>set_hostport</function> - change hostname and
- port of Request <acronym>URI</acronym> to value given as
- string parameter.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- modified, otherwise the original Request
- <acronym>URI</acronym> will be modified. </para>
- </listitem>
- <listitem>
- <para>
- <function>set_user</function> - Set username part of
- Request <acronym>URI</acronym> to string given as
- parameter.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- modified, otherwise the original Request
- <acronym>URI</acronym> will be modified.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>set_userpass</function> - Set username and
- password part of Request <acronym>URI</acronym> to string
- given as parameter.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- modified, otherwise the original Request
- <acronym>URI</acronym> will be modified. </para>
- </listitem>
- <listitem>
- <para>
- <function>set_port</function> - Set port of Request
- <acronym>URI</acronym> to value given as parameter.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- modified, otherwise the original Request
- <acronym>URI</acronym> will be modified.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>set_uri</function> - Set a new Request
- <acronym>URI</acronym>.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- freed. If there is a valid <acronym>URI</acronym> in
- <structfield>parsed_uri</structfield> field, it will be
- freed too.
- </para>
- <para>
- Then <acronym>URI</acronym> given as parameter will be
- stored in <structfield>new_uri</structfield> field. (If
- <structfield>new_uri</structfield> contains a
- <acronym>URI</acronym> it will be used instead of Request
- <acronym>URI</acronym> when forwarding the message).
- </para>
- </listitem>
- <listitem>
- <para>
- <function>prefix</function> - Set the parameter as username
- prefix.
- </para>
- <para>
- The string will be put immediately after "sip:" part of the
- Request <acronym>URI</acronym>.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in
- <structfield>new_uri</structfield> field, it will be
- modified, otherwise the original Request
- <acronym>URI</acronym> will be modified.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>strip</function> - Remove first n characters of
- username in Request <acronym>URI</acronym>.
- </para>
- <para>
- If there is a <acronym>URI</acronym> in <structfield>new_uri</structfield>
- field, it will be modified, otherwise the original Request
- <acronym>URI</acronym> will be modified.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>if</function> - if Statement.
- </para>
- <para>
- There is an expression associated with the command and one
- or two linked lists of commands. The expression is a
- regular expression compiled into binary form in the fixup
- when the config file was compiled.
- </para>
- <para>
- The expression will be evaluated now. If the result is >
- 0, the first linked list will be executed using
- <function>run_action</function> function. The linked list
- represents command enclosed in curly braces of
- <function>if</function> command.
- </para>
- <para>
- Otherwise, if there is the second list, it will be executed
- in the same way. The second list represents commands of
- <function>else</function> statement.
- </para>
- </listitem>
- <listitem>
- <para>
- <function>module</function> - Execute a function exported by
- a module.
- </para>
- <para>
- When a command in a route statement is not recognized by
- the core itself (i.e. it is not one of commands handled by
- the core itself), list of exported functions of all loaded
- modules will be searched for a function with corresponding
- name and number of parameters.
- </para>
- <para>
- If the function was found, <function>module</function>
- command (this one) will be created and pointer to the
- function will be stored in
- <structfield>p1.data</structfield> field.
- </para>
- <para>
- So, this command will simply call function whose pointer is
- in <structfield>p1.data</structfield> field and will pass 2
- parameters to the function. If one or both of the
- parameters were not used, 0 will be passed instead.
- </para>
- <para>
- Return value of the function will be returned as return
- value of <function>module</function> command.
- </para>
- <para>
- This command makes <acronym>SER</acronym> pretty extensible
- while the core itself is still reasonably small and
- clean. Additional functionality is put in modules and
- loaded only when needed.
- </para>
- </listitem>
- </itemizedlist>
- </section> <!-- do-action -->
- </section>
|