User Tools

Site Tools


cookbooks:devel:core

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
cookbooks:devel:core [2019/10/18 09:35]
jih
cookbooks:devel:core [2021/04/03 08:18]
miconda [if]
Line 1: Line 1:
-====== Kamailio SIP Server v5.4.x (devel): Core Cookbook ======+====== Core Cookbook ======
  
 +Version: Kamailio SIP Server v5.5.x (devel)
 ===== Overview ===== ===== Overview =====
  
Line 9: Line 10:
 ===== Structure ===== ===== Structure =====
  
-The structure of the kamailio.cfg can be seen as thee parts:+The structure of the kamailio.cfg can be seen as three parts:
  
   * global parameters   * global parameters
Line 358: Line 359:
     * text on the same line as the directive will cause problems. Keep the directive lines clean and only comment on a line before or after.      * text on the same line as the directive will cause problems. Keep the directive lines clean and only comment on a line before or after. 
  
 +==== defenv ====
 +
 +Preprocessor directive to define an ID to the value of an environment variable with the name ENVVAR.
 +
 +<code c>
 +#!defenv ID=ENVVAR
 +</code>
 +
 +It can also be just **$!defenv ENVVAR** and the defined ID is the ENVVAR name.
 +
 +Example:
 +
 +<code c>
 +#!defenv SHELL
 +</code>
 +
 +If environment variable $SHELL is '/bin/bash', then it is like:
 +
 +<code c>
 +#!define SHELL /bin/bash
 +</code>
 +
 +Full expression variant:
 +
 +<code c>
 +#!defenv ENVSHELL=SHELL
 +</code>
 +
 +Then it is like:
 +
 +<code c>
 +#!define ENVSHELL /bin/bash
 +</code>
 +
 +It is a simplified alternative of using **#!substdef** with **$env(NAME)** in the replacement part.
 +    
 ==== subst ==== ==== subst ====
  
Line 727: Line 764:
 ==== async_workers ==== ==== async_workers ====
  
-Specify how many child processes to create for asynchronous execution. These are processes that can receive tasks from various components and execute them locally, which is different process than the task sender.+Specify how many child processes (workers) to create for asynchronous execution in the group "default". These are processes that can receive tasks from various components (e.g, modules such as async, acc, sqlops) and execute them locally, which is different process than the task sender.
  
 Default: 0 (asynchronous framework is disabled). Default: 0 (asynchronous framework is disabled).
Line 736: Line 773:
     async_workers=4     async_workers=4
 </code> </code>
 +
 +==== async_nonblock ====
 +
 +Set the non-block mode for the internal sockets used by default group of async workers.
 +
 +Default: 0
 +
 +Example:
 +
 +<code>
 +    async_nonblock=1
 +</code>
 +
 +==== async_usleep ====
 +
 +Set the number of microseconds to sleep before trying to receive next task (can be useful when async_nonblock=1).
 +
 +Default: 0
 +
 +Example:
 +
 +<code>
 +    async_usleep=100
 +</code>
 +
 +==== async_workers_group ====
 +
 +Define groups of asynchronous worker processes.
 +
 +Prototype:
 +
 +<code>
 +async_workers_group="name=X;workers=N;nonblock=[0|1];usleep=M"
 +</code>
 +
 +The attributes are:
 +
 +  * **name** - the group name (used by functions such as **sworker_task(name)**)
 +  * **workers** - the number of processes to create for this group
 +  * **nonblock** - set or not set the non-block flag for internal communication socket
 +  * **usleep** - the number of microseconds to sleep before trying to receive next task (can be useful if nonblock=1)
 +
 +Default: "".
 +
 +Example:
 +
 +<code>
 +    async_workers_group="name=reg;workers=4;nonblock=0;usleep=0"
 +</code>
 +
 +If the **name** is default, then it overwrites the value set by **async_workers**.
 +
 +See also **event_route[core:pre-routing]** and **sworker** module.
  
 ==== auto_aliases ==== ==== auto_aliases ====
Line 970: Line 1060:
 </code> </code>
  
 +
 +==== ipv6_hex_style ====
 +
 +Can be set to "a", "A" or "c" to specify if locally computed string representation of IPv6 addresses should be expanded lowercase, expanded uppercase or compacted lowercase hexa digits.
 +
 +Default is "c" (compacted lower hexa digits, conforming better with RFC 5952).
 +
 +"A" is preserving the behaviour before this global parameter was introduced, while "a" enables the ability to follow some of the recommendations of RFC 5952, section 4.3.
 +
 +Example of usage:
 +
 +<code c>
 +  ipv6_hex_style = "a"
 +</code>
 ==== kemi.onsend_route_callback ==== ==== kemi.onsend_route_callback ====
  
Line 1011: Line 1115:
 kemi.onsend_route_callback="ksr_my_reply_route" kemi.onsend_route_callback="ksr_my_reply_route"
 </code> </code>
 +
 +==== kemi.pre_routing_callback ====
 +
 +Set the name of callback function in the KEMI script to be executed as the equivalent of `event_route[core:pre-routing]` block (from the native configuration file).
 +
 +Default value: none
 +
 +Set it to empty string or "none" to skip execution of this callback function.
 +
 +Example:
 +
 +<code c>
 +kemi.pre_routing_callback="ksr_pre_routing"
 +</code>
 +
 ==== latency_cfg_log ==== ==== latency_cfg_log ====
  
Line 1025: Line 1144:
 ==== latency_limit_action ==== ==== latency_limit_action ====
  
-Limit of latency in ms for config actions. If a config action executed by cfg interpreter takes longer than its value, a message is printed in the logs, showing config path, line and action name when it is a module function, as well as internal action id.+Limit of latency in us (micro-seconds) for config actions. If a config action executed by cfg interpreter takes longer than its value, a message is printed in the logs, showing config path, line and action name when it is a module function, as well as internal action id.
  
 Default value is 0 (disabled). Default value is 0 (disabled).
Line 1058: Line 1177:
 ==== listen ==== ==== listen ====
  
-Set the network addresses the SIP server should listen to. It can be an IP address, hostname or network iterface id or combination of protocol:address:port (e.g., udp:10.10.10.10:5060). This parameter can be set multiple times in same configuration file, the server listening on all addresses specified.+Set the network addresses the SIP server should listen to. It can be an IP address, hostname or network interface id or combination of protocol:address:port (e.g., udp:10.10.10.10:5060). This parameter can be set multiple times in same configuration file, the server listening on all addresses specified.
  
 Example of usage: Example of usage:
Line 1073: Line 1192:
  
 <code c> <code c>
-    listen=udp:[2a02:1850:1:1::13]:5060+    listen=udp:[2a02:1850:1:1::18]:5060
 </code> </code>
  
Line 1079: Line 1198:
  
 <code c> <code c>
-    listen=udp:10.10.10.10:5060 advertise  11.11.11.11:5060+    listen=udp:10.10.10.10:5060 advertise 11.11.11.11:5060
 </code> </code>
  
Line 1085: Line 1204:
  
 A typical use case for advertise address is when running SIP server behind a NAT/Firewall, when the local IP address (to be used for bind) is different than the public IP address (to be used for advertising). A typical use case for advertise address is when running SIP server behind a NAT/Firewall, when the local IP address (to be used for bind) is different than the public IP address (to be used for advertising).
 +
 +A unique name can be set for sockets to simplify the selection of the socket for sending out. For example, the rr and path modules can use the socket name to advertise it in header URI parameter and use it as a shortcut to select the corresponding socket for routing subsequent requests.
 +
 +The name has to be provided as a string enclosed in between quotes after the **name** identifier.
 +
 +<code c>
 +    listen=udp:10.0.0.10:5060 name "s1"
 +    listen=udp:10.10.10.10:5060 advertise 11.11.11.11:5060 name "s2"
 +    listen=udp:10.10.10.20:5060 advertise "mysipdomain.com" name "s3"
 +    listen=udp:10.10.10.30:5060 advertise "mysipdomain.com" name "s4"
 +    ...
 +    $fsn = "s4";
 +    t_relay();
 +</code>
 +
 +Note that there is no internal check for uniqueness of the socket names, the admin has to ensure it in order to be sure the desired socket is selected, otherwise the first socket with a matching name is used.
 ==== loadmodule ==== ==== loadmodule ====
  
Line 1102: Line 1237:
     loadmodule "dialplan.so"     loadmodule "dialplan.so"
 </code> </code>
 +
 +==== loadmodulex ====
 +
 +Similar to **loadmodule** with the ability to evaluate variables in its parameter.
  
 ==== loadpath ==== ==== loadpath ====
Line 1125: Line 1264:
 The proxy tries to find the modules in a smart way, e.g: loadmodule "uri" tries to find uri.so in the loadpath, but also uri/uri.so. The proxy tries to find the modules in a smart way, e.g: loadmodule "uri" tries to find uri.so in the loadpath, but also uri/uri.so.
  
 +==== local_rport ====
 +
 +Similar to **add_local_rport()** function, but done in a global scope, so the function does not have to be executed for each request.
 +
 +Default: off
 +
 +Example:
 +
 +<code c>
 +local_rport = on
 +</code>
  
 ==== log_engine_data ==== ==== log_engine_data ====
Line 1333: Line 1483:
 It can be set via config reload framework. It can be set via config reload framework.
  
-Default is (disabled).+Default is (enabled).
  
 <code c> <code c>
Line 1410: Line 1560:
  
 ==== modparam ==== ==== modparam ====
 +
 The modparam command will be used to set the options of the modules.  The modparam command will be used to set the options of the modules. 
  
Line 1419: Line 1570:
 See the documenation of the respective module to find out the available options. See the documenation of the respective module to find out the available options.
  
 +==== modparamx ====
 +
 +Similar to **modparam**, with ability to evaluate the variables in its parameters.
 ==== onsend_route_reply ==== ==== onsend_route_reply ====
  
Line 1527: Line 1681:
 ==== route_locks_size ==== ==== route_locks_size ====
  
-Set the number of mutex locks to be used for synchronizing the execution of messages sharing the same Call-Id. In other words, enables Kamailio to execute sequentially the requests and replies received within the same dialog -- a new message received within the same dialog waits until the previous one is routed out.+Set the number of mutex locks to be used for synchronizing the execution of config script for messages sharing the same Call-Id. In other words, enables Kamailio to execute the config script sequentially for the requests and replies received within the same dialog -- a new message received within the same dialog waits until the previous one is routed out.
  
-For smaller impact on parallel processing, its value it should be at least twice the number of kamailio processes (children+For smaller impact on parallel processing, its value it should be at least twice the number of Kamailio processes (all children processes).
  
 Example: Example:
Line 1536: Line 1690:
 route_locks_size = 256 route_locks_size = 256
 </code> </code>
 +
 +Note that ordering of the SIP messages can still be changed by network transmission (quite likely for UDP, especially on long distance paths) or CPU allocation for processes when executing pre-config and post-config tasks (very low chance, but not to be ruled out completely).
 ==== server_id ==== ==== server_id ====
  
Line 1576: Line 1732:
  
 shm_mem_size = 64 (default 64) shm_mem_size = 64 (default 64)
 +
 +==== sip_parser_log ====
 +
 +Log level for printing debug messages for some of the SIP parsing errors.
 +
 +Default: 0 (L_WARN)
 +
 +<code c>
 +sip_parser_log = 1
 +</code>
 +
 +==== sip_parser_mode ====
 +
 +Control sip parser behaviour.
 +
 +If set to 1, the parser is more strict in accepting messages that have invalid headers (e.g., duplicate To or From). It can make the system safer, but loses the flexibility to be able to fix invalid messages with config operations.
 +
 +If set to 0, the parser is less strict on checking validity of headers.
 +
 +Default: 1
 +
 +<code c>
 +sip_parser_mode = 0
 +</code>
  
 ==== sip_warning (noisy feedback) ==== ==== sip_warning (noisy feedback) ====
  
-Can be 0 or 1. If set to 1 (default value) a 'Warning' header is added to each reply generated by Kamailio.+Can be 0 or 1. If set to 1 (default value is 0) a 'Warning' header is added to each reply generated by Kamailio.
 The header contains several details that help troubleshooting using the network traffic dumps, but might reveal details of your network infrastructure and internal SIP routing. The header contains several details that help troubleshooting using the network traffic dumps, but might reveal details of your network infrastructure and internal SIP routing.
  
Line 1662: Line 1842:
  
  
 +==== stats_name_separator ====
  
 +Specify the character used as a separator for the internal statistics' names. 
 +Default value is "_".
 +
 +Example of usage:
  
 +    stats_name_separator = "-"
  
 ==== tos ==== ==== tos ====
Line 1743: Line 1929:
    version_table="version44"    version_table="version44"
 </code> </code>
 +
 +==== wait_worker1_mode ====
 +
 +Enable waiting for child SIP worker one to complete initialization, then create the other child worker processes.
 +
 +Default: 0 (do not wait for child worker one to complete initialization).
 +
 +Example:
 +
 +<code c>
 +wait_worker1_mode = 1
 +</code>
 +
 +==== wait_worker1_time ====
 +
 +How long to wait for child worker one to complete the initialization. In micro-seconds.
 +
 +Default: 4000000 (micro-seconds = 4 seconds).
 +
 +Example:
 +
 +<code c>
 +wait_worker1_time = 1000000
 +</code>
 +
 +==== wait_worker1_usleep ====
 +
 +How long to wait for child worker one to complete the initialization. In micro-seconds.
 +
 +Default: 100000 (micro-seconds = 0.1 seconds).
 +
 +Example:
 +
 +<code c>
 +wait_worker1_usleep = 50000
 +</code>
 +
 ==== workdir ==== ==== workdir ====
  
Line 2460: Line 2683:
  
  
-===== Blacklist Parameters =====+===== Blocklist Parameters =====
  
-==== dst_blacklist_expire ====+==== dst_blocklist_expire ====
  
-**Alias name: dst_blacklist_ttl**+**Alias name: dst_blocklist_ttl**
  
-How much time a blacklisted destination will be kept in the blacklist (w/o any update).+How much time a blocklisted destination will be kept in the blocklist (w/o any update).
  
-  dst_blacklist_expire = time in s (default 60 s)+  dst_blocklist_expire = time in s (default 60 s)
  
-==== dst_blacklist_gc_interval ====+==== dst_blocklist_gc_interval ====
 How often the garbage collection will run (eliminating old, expired entries). How often the garbage collection will run (eliminating old, expired entries).
  
-  dst_blacklist_gc_interval = time in s (default 60 s)+  dst_blocklist_gc_interval = time in s (default 60 s)
  
-==== dst_blacklist_init ==== +==== dst_blocklist_init ==== 
-If off, the blacklist is not initialized at startup and cannot be enabled runtime, that saves some memory.+If off, the blocklist is not initialized at startup and cannot be enabled runtime, that saves some memory.
  
-  dst_blacklist_init = on | off (default on)+  dst_blocklist_init = on | off (default on)
  
-==== dst_blacklist_mem ==== +==== dst_blocklist_mem ==== 
-Maximum shared memory amount used for keeping the blacklisted destinations.+Maximum shared memory amount used for keeping the blocklisted destinations.
  
-  dst_blacklist_mem = size in Kb (default 250 Kb)+  dst_blocklist_mem = size in Kb (default 250 Kb)
  
-==== use_dst_blacklist ==== +==== use_dst_blocklist ==== 
-Enable the destination blacklist: Each failed send attempt will cause the destination to be added to the blacklist. Before any send, this blacklist will be checked and if a match is found, the send is no longer attempted (an error is returned immediately). +Enable the destination blocklist: Each failed send attempt will cause the destination to be added to the blocklist. Before any send, this blocklist will be checked and if a match is found, the send is no longer attempted (an error is returned immediately). 
  
-Note: using the blacklist incurs a small performance penalty.+Note: using the blocklist incurs a small performance penalty.
  
-See also doc/dst_blacklist.txt.+See also doc/dst_blocklist.txt.
  
-  use_dst_blacklist = on | off (default off)+  use_dst_blocklist = on | off (default off)
  
 ===== Real-Time Parameters ===== ===== Real-Time Parameters =====
Line 2636: Line 2859:
  
 Force to send the message from the specified socket (it _must_ be one of the sockets specified with the "listen" directive). If the protocol doesn't match (e.g. UDP message "forced" to a TCP socket) the closest socket of the same protocol is used. Force to send the message from the specified socket (it _must_ be one of the sockets specified with the "listen" directive). If the protocol doesn't match (e.g. UDP message "forced" to a TCP socket) the closest socket of the same protocol is used.
 +
 +This function does not support pseudo-variables, use the set_send_socket function from the corex module instead.
  
 Example of usage: Example of usage:
Line 2769: Line 2994:
 </code> </code>
  
 +See also the FAQ for how the function return code is evaluated:
 +
 +  * https://www.kamailio.org/wiki/tutorials/faq/main#how_is_the_function_return_cod
 ==== revert_uri ==== ==== revert_uri ====
  
Line 2856: Line 3084:
  
  
 +==== selval ====
  
 +Select a value based on conditional expression.
 +
 +Prototype:
 +
 +<code c>
 +selval(evalexpr, valexp1, valexpr2)
 +</code>
 +
 +This is a core statement that return the 2nd parameter if the 1st parameter is evaluated to true, or 3rd parameter if the 1st parameter is evaluated to false. It can be considered a core function that is equivalent of ternary condition/operator
 +
 +Example:
 +
 +<code c>
 +$var(x) = selval($Ts mod 2, "true/" + $ru, "false/" + $rd);
 +</code>
 +
 +The first parameter is a conditional expression, like those used for IF, the 2nd and 3rd parameters can be expressions like those used in the right side of assignments.
 ==== set_advertised_address ==== ==== set_advertised_address ====
  
Line 2992: Line 3238:
  
 Add "user=phone" parameter to R-URI. Add "user=phone" parameter to R-URI.
 +
 ===== Custom Global Parameters ===== ===== Custom Global Parameters =====
  
-These are parameters that can be defined by the writer of kamailio.cfg in order to be used inside routing blocks. +These are parameters that can be defined by the writer of kamailio.cfg in order to be used inside routing blocks. One of the important properties for custom global parameters is that their value can be changed at runtime via RPC commands, without restarting Kamailio. 
 + 
 +The definition of a custom global parameter must follow the pattern: 
 + 
 +<code> 
 +group.variable = value desc "description" 
 + 
 +</code> 
 + 
 +The value can be a quoted string or integer number. 
 + 
 +Example: 
 + 
 +<code c> 
 +pstn.gw_ip = "1.2.3.4" desc "PSTN GW Address" 
 +</code> 
 + 
 +The custom global parameter can be accessed inside a routing block via: 
 + 
 +<code> 
 +$sel(cfg_get.group.variable) 
 +</code> 
 + 
 +Example: 
 + 
 +<code c> 
 +$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip); 
 +</code> 
 + 
 +**Note:** Some words cannot be used as (part of) names for custom variables or groups, and if they are used a syntax error is logged  by kamailio. These keywords are: "yes", "true", "on", "enable", "no", "false", "off", "disable", "udp", "UDP", "tcp", "TCP", "tls", "TLS", "sctp", "SCTP", "ws", "WS", "wss", "WSS", "inet", "INET", "inet6", "INET6", "sslv23", "SSLv23", "SSLV23", "sslv2", "SSLv2", "SSLV2", "sslv3", "SSLv3", "SSLV3", "tlsv1", "TLSv1", "TLSV1" 
 + 
 +===== Routing Blocks ===== 
 + 
 +The routing blocks are the parts of the configuration file executed by kamailio at runtime. They can be seen as blocks of actions similar to functions (or procedures) from common programming languages. 
 + 
 +A routing block is identified by a specific token, followed by a name in between square brackets and actions in between curly braces. 
 + 
 +<code c> 
 +route_block_id[NAME] { 
 +  ACTIONS 
 +
 +</code> 
 + 
 +The name can be any alphanumeric string, with specific routing blocks enforcing a particular format.  
 + 
 +<fc #4682b4>Note: route(number) is equivalent to route("number").</fc> 
 + 
 +Route blocks can be executed on network events (e.g., receiving a SIP message), timer events (e.g., retransmission timeout) or particular events specific to modules. 
 + 
 +There can be so called sub-route blocks, which can be invoked from another route blocks, like a function. Invocation is done with 'route' followed by the name of sub-route to execute, enclosed in between parentheses. 
 + 
 +Example: 
 + 
 +<code c> 
 +  request_route{ 
 +    ... 
 +    route("test"); 
 +    ... 
 +  } 
 + 
 +  route["test"]{ 
 +    ... 
 +  } 
 +</code> 
 + 
 +==== request_route ==== 
 + 
 +Request routing block -  is executed for each SIP request. 
 + 
 +It contains a set of actions to be executed for SIP requests received from the network. It is the equivalent of *main()* function for handling the SIP requests. 
 + 
 +<fc #4682b4>For backward compatibility reasons, the main request 'route' block can be identified by 'route{...}' or 'route[0]{...}'.</fc> 
 + 
 +The implicit action after execution of the main route block is to drop the SIP request. To send a reply or forward the request, explicit actions (e.g., sl_send_reply(), forward(), t_relay()) must be called inside the route block. 
 + 
 +Example of usage: 
 + 
 +<code c> 
 +    request_route { 
 +         if(is_method("OPTIONS")) { 
 +            # send reply for each options request 
 +            sl_send_reply("200", "ok"); 
 +            exit(); 
 +         } 
 +         route(FWD); 
 +    } 
 +    route[FWD] { 
 +         # forward according to uri 
 +         forward(); 
 +    } 
 +</code> 
 + 
 +==== route ==== 
 + 
 +This block is used to define 'sub-routes' - group of actions that can be executed from another routing block. Originally targeted as being executed from 'request_route', it can be executed now from all the other blocks. Be sure you put there the actions valid for the root routing block executing the sub-route. 
 + 
 +The definition of the sub-route block follows the general rules, with a name in between square brackets and actions between curly braces. A sub-route can return an integer value back to the routing block that executed it. The return code can be retrieved via $rc variables. 
 + 
 +Evaluation of the return of a subroute is done with following rules: 
 +  * negative value is evaluated as false 
 +  * 0 - is interpreted as **exit** 
 +  * positive value is evaluated as true 
 + 
 + 
 +<code c> 
 +request_route { 
 +  if(route(POSITIVE)) { 
 +    xlog("return number is positive\n"); 
 +  } 
 +  if( ! route(NEGATIVE)) { 
 +    xlog("return number is negative\n"); 
 +  } 
 +  if( route(ZERO)) { 
 +    xlog("this log message does not appear\n"); 
 +  } 
 +
 + 
 +route[POSITIVE] { 
 +  return 10; 
 +
 + 
 +route[NEGATIVE] { 
 +  return -8; 
 +
 + 
 +route[ZERO] { 
 +  return 0; 
 +
 +</code> 
 + 
 +A sub-route can execute another sub-route. There is a limit to the number of recursive levels, avoiding ending up in infinite loops -- see **max_recursive_level** global parameter. 
 + 
 +The sub-route blocks allow to make the configuration file modular, simplifying the logic and helping to avoid duplication of actions. 
 +==== branch_route ==== 
 + 
 +Request's branch routing block. It contains a set of actions to be taken for each branch of a SIP request. It is executed only by TM module after it was armed via t_on_branch("branch_route_index"). 
 + 
 +Example of usage: 
 + 
 +<code c> 
 +    request_route { 
 +        lookup("location"); 
 +        t_on_branch("OUT"); 
 +        if(!t_relay()) { 
 +            sl_send_reply("500", "relaying failed"); 
 +        } 
 +    } 
 +    branch_route[OUT] { 
 +        if(uri=~"10\.10\.10\.10") { 
 +            # discard branches that go to 10.10.10.10 
 +            drop(); 
 +        } 
 +    } 
 +</code> 
 + 
 +==== failure_route ==== 
 + 
 +Failed transaction routing block. It contains a set of actions to be taken each transaction that received only negative replies (>=300) for all branches. The 'failure_route' is executed only by TM module after it was armed via t_on_failure("failure_route_index"). 
 + 
 +Note that in 'failure_route' is processed the request that initiated the transaction, not the reply . 
 + 
 + 
 +Example of usage: 
 + 
 +<code c> 
 +    request_route { 
 +        lookup("location"); 
 +        t_on_failure("TOVOICEMAIL"); 
 +        if(!t_relay()) { 
 +            sl_send_reply("500", "relaying failed"); 
 +        } 
 +    } 
 +    failure_route[TOVOICEMAIL] { 
 +        if(is_method("INVITE")) { 
 +             # call failed - relay to voice mail 
 +             t_relay_to_udp("voicemail.server.com","5060"); 
 +        } 
 +    } 
 +</code> 
 + 
 +==== reply_route ==== 
 + 
 +Main SIP response (reply) handling block - it contains a set of actions to be executed for SIP replies. It is executed for all replies received from the network. 
 + 
 +It does not have a name and it is executed by the core, before any other module handling the SIP reply. It is triggered only by SIP replies received on the network. 
 + 
 +There is no network route that can be enforced for a SIP reply - it is sent based on Via header, according to SIP RFC3261 - therefore no dedicated actions for forwarding the reply must be used in this block. 
 + 
 +This routing block is optional, if missing, the SIP reply is sent to the address in 2nd Via header. 
 + 
 +One can decide to drop a SIP reply by using **drop** action. 
 + 
 +Example: 
 + 
 +<code c> 
 +reply_route { 
 +  if(status=="128") { 
 +    drop; 
 +  } 
 +
 +</code> 
 + 
 +<fc #4682b4>Note: for backward compatibility reasons, the main 'reply' routing block can be also identified by 'onreply_route {...}' or 'onreply_route[0] {...}'.</fc> 
 + 
 +==== onreply_route ==== 
 + 
 + 
 +SIP reply routing block executed by **tm** module. It contains a set of actions to be taken for SIP replies in the contect of an active transaction. 
 + 
 +The 'onreply_route' must be armed for the SIP requests whose replies should be processed within it, via t_on_reply("onreply_route_index"). 
 + 
 +Core 'reply_route' block is executed before a possible **tm** 'onreply_route' block. 
 + 
 +<code c> 
 +  request_route { 
 +      lookup("location"); 
 +      t_on_reply("LOGRPL"); 
 +      if(!t_relay()) { 
 +          sl_send_reply("500", "relaying failed"); 
 +      } 
 +  } 
 + 
 +  reply_route { 
 +      if(!t_check_trans()) { 
 +          drop; 
 +      } 
 +  } 
 + 
 +  onreply_route[LOGRPL] { 
 +      if(status=~"1[0-9][0-9]") { 
 +           log("provisional response\n"); 
 +      } 
 +  } 
 +</code> 
 +==== onsend_route ==== 
 + 
 +The route is executed in when a SIP request is sent out. Only a limited number of commands are allowed (drop, if + all the checks, msg flag manipulations, send(), log(), textops::search()). 
 + 
 +In this route the final destination of the message is available and can be checked (with snd_ip, snd_port, to_ip, to_port, snd_proto, snd_af). 
 + 
 +This route is executed only when forwarding requests - it is not executed for replies, retransmissions, or locally generated messages (e.g. via fifo uac). 
 + 
 +Example: 
 + 
 +<code c> 
 +  onsend_route { 
 +    if(to_ip==1.2.3.4 && !isflagset(12)){ 
 +      log(1, "message blocked\n"); 
 +      drop; 
 +    } 
 +  } 
 +</code> 
 + 
 +  * snd_ip, snd_port - behave like src_ip/src_port, but contain the ip/port Kamailio will use to send the message 
 +  * to_ip, to_port - like above, but contain the ip/port the message will be sent to (not to be confused with dst_ip/dst_port, which are the destination of the original received request: Kamailio's ip and port on which the message was received) 
 +  * snd_proto, snd_af - behave like proto/af but contain the protocol/address family that Kamailio will use to send the message 
 +  * msg:len - when used in an onsend_route, msg:len will contain the length of the message on the wire (after all the changes in the script are applied, Vias are added a.s.o) and not the lentgh of the original message. 
 + 
 +==== event_route ==== 
 + 
 +Generic type of route executed when specific events happen. 
 + 
 +Prototype: event_route[groupid:eventid] 
 +  * groupid - should be the name of the module that triggers the event 
 +  * eventid - some meaningful short text describing the event 
 + 
 +=== Core Event Routes === 
 + 
 +Implementations: 
 + 
 +  * **event_route[core:worker-one-init]** - executed by core after the first udp sip worker process executed the child_init() for all modules, before starting to process sip traffic 
 +    * note that due to forking, other sip workers can get faster to listening for sip traffic 
 + 
 +<code c> 
 +event_route[core:worker-one-init] { 
 +        xlog("L_INFO","Hello world\n"); 
 +
 +</code> 
 + 
 +  * **event_route[core:msg-received]** - executed when a message is received from the network. It runs with a faked request and makes available the $rcv(key) variables to access what was received and related attribtues. 
 +    * it has to be enabled with received_route_mode global parameter. For usage via Kemi, set kemi.received_route_callback global parameter. 
 +    * if drop is executed, the received message is no longer processed 
 + 
 +<code c> 
 +event_route[core:msg-received] { 
 +  xlog("rcv on $rcv(af)/$rcv(proto): ($rcv(len)) [$rcv(buf)] from [$rcv(srcip):$rcv(srcport)] to [$rcv(rcvip):$rcv(rcvport)]\n"); 
 +  if($rcv(srcip) == "1.2.3.4") { 
 +    drop; 
 +  } 
 +
 +</code> 
 + 
 +  * **event_route[core:pre-routing]** - executed by core on receiving SIP traffic before running request_route or reply_route. 
 +    * if drop is used, then the message is not processed further with request_route or reply_route in the same process. This can be useful together with sworker module which can delegate the processing to another worker. 
 + 
 +<code c> 
 +async_workers_group="name=reg;workers=4" 
 +... 
 +event_route[core:pre-routing] { 
 +    xinfo("pre-routing rules\n"); 
 +    if(is_method("REGISTER")) { 
 +        # delegate processing of REGISTERs to a special group of workers 
 +        if(sworker_task("reg")) { 
 +            drop; 
 +        } 
 +    } 
 +
 +</code> 
 + 
 +  * ** event_route[core:receive-parse-error]** - executed by core on receiving a broken SIP message that can not be parsed. 
 +    * note that the SIP message is broken in this case, but it gets access to source and local socket addresses (ip, port, proto, af) as    well as the whole message buffer and its size  
 + 
 +<code c> 
 +event_route[core:receive-parse-error] { 
 +        xlog("got an parsing error from $si:$sp, message $mb\n"); 
 +
 + 
 +</code> 
 + 
 +=== Module Event Routes === 
 + 
 +Here are only a few examples, to see if a module exports event_route blocks and when they are executed, check the readme of the module. 
 + 
 + 
 +  * **event_route[htable:mod-init]** - executed by **htable** module after all modules have been initialised. Good for initialising values in hash tables. 
 +<code c> 
 +modparam("htable", "htable", "a=>size=4;"
 + 
 +event_route[htable:mod-init] { 
 +  $sht(a=>calls-to::10.10.10.10) = 0; 
 +  $sht(a=>max-calls-to::10.10.10.10) = 100; 
 +
 + 
 +request_route { 
 +  if(is_method("INVITE") && !has_totag()) 
 +  { 
 +    switch($rd) { 
 +      case "10.10.10.10": 
 +        lock("calls-to::10.10.10.10"); 
 +        $sht(a=>calls-to::10.10.10.10) = 
 +            $sht(a=>calls-to::10.10.10.10) + 1; 
 +        unlock("calls-to::10.10.10.10"); 
 +        if($sht(a=>calls-to::10.10.10.10)>$sht(a=>max-calls-to::10.10.10.10)) 
 +        { 
 +           sl_send_reply("500", "To many calls to .10"); 
 +           exit; 
 +        } 
 +      break; 
 +      ... 
 +    } 
 +  } 
 +
 +</code> 
 +  * **event_route [tm:local-request]** - executed on locally generated requests. 
 +<code c> 
 +event_route [tm:local-request] { # Handle locally generated requests 
 +  xlog("L_INFO", "Routing locally generated $rm to <$ru>\n"); 
 +  t_set_fr(10000, 10000); 
 +
 +</code> 
 + 
 +  * **event_route [tm:branch-failure]** - executed on all failure responses. 
 +<code c> 
 +request_route { 
 +    ... 
 +    t_on_branch_failure("myroute"); 
 +    t_relay(); 
 +
 + 
 +event_route[tm:branch-failure:myroute] { 
 +  xlog("L_INFO", "Handling $T_reply_code response to $rm to <$ru>\n"); 
 +  if (t_check_status("430")) { # Outbound flow failed 
 +    unregister("location", "$tu", "$T_reply_ruid"); 
 +    if (t_next_contact_flow()) { 
 +      t_relay(); 
 +    } 
 +  } 
 +
 + 
 +</code> 
 + 
 +===== Script Statements ===== 
 + 
 +==== if ==== 
 +IF-ELSE statement 
 + 
 +Prototype: 
 + 
 +<code> 
 +    if(expr) { 
 +       actions; 
 +    } else { 
 +       actions; 
 +    } 
 +</code> 
 + 
 +The 'expr' should be a valid logical expression. 
 + 
 +The logical operators that can be used in 'expr': 
 + 
 +<code> 
 +  ==      equal 
 +  !=      not equal 
 +  =~      regular expression matching: Note: Posix regular expressions will be used, e.g. use [[:digit:]]{3} instead of \d\d\d 
 +  !~      regular expression not-matching (NOT PORTED from Kamailio 1.x, use '!(x =~ y)') 
 +  >       greater 
 +  >=      greater or equal 
 +  <       less 
 +  <=      less or equal 
 +  &&      logical AND 
 +  ||      logical OR 
 +  !       logical NOT 
 +</code> 
 + 
 +Example of usage: 
 + 
 +    if(is_method("INVITE")) 
 +    { 
 +        log("this sip message is an invite\n"); 
 +    } else { 
 +        log("this sip message is not an invite\n"); 
 +    } 
 + 
 +See also the FAQ for how the function return code is evaluated: 
 + 
 +  * https://www.kamailio.org/wiki/tutorials/faq/main#how_is_the_function_return_cod 
 +==== switch ==== 
 + 
 +SWITCH statement - it can be used to test the value of a pseudo-variable.  
 + 
 +IMPORTANT NOTE: 'break' can be used only to mark the end of a 'case' branch (as it is in shell scripts). If you are trying to use 'break' outside a 'case' block the script will return error -- you must use 'return' there. 
 + 
 + 
 +Example of usage: 
 +<code> 
 +    route { 
 +        route(1); 
 +        switch($retcode) 
 +        { 
 +            case -1: 
 +                log("process INVITE requests here\n"); 
 +            break; 
 +            case 1: 
 +                log("process REGISTER requests here\n"); 
 +            break; 
 +            case 2: 
 +            case 3: 
 +                log("process SUBSCRIBE and NOTIFY requests here\n"); 
 +            break; 
 +            default: 
 +                log("process other requests here\n"); 
 +       } 
 + 
 +        # switch of R-URI username 
 +        switch($rU) 
 +        { 
 +            case "101": 
 +                log("destination number is 101\n"); 
 +            break; 
 +            case "102": 
 +                log("destination number is 102\n"); 
 +            break; 
 +            case "103": 
 +            case "104": 
 +                log("destination number is 103 or 104\n"); 
 +            break; 
 +            default: 
 +                log("unknown destination number\n"); 
 +       } 
 +    } 
 + 
 +    route[1]{ 
 +        if(is_method("INVITE")) 
 +        { 
 +            return(-1); 
 +        }; 
 +        if(is_method("REGISTER")) 
 +            return(1); 
 +        } 
 +        if(is_method("SUBSCRIBE")) 
 +            return(2); 
 +        } 
 +        if(is_method("NOTIFY")) 
 +            return(3); 
 +        } 
 +        return(-2); 
 +    } 
 +</code> 
 + 
 +NOTE: take care while using 'return' - 'return(0)' stops the execution of the script. 
 + 
 + 
 +==== while ==== 
 + 
 +while statement 
 + 
 +Example of usage: 
 +     
 +    $var(i) = 0; 
 +    while($var(i) < 10) 
 +    { 
 +        xlog("counter: $var(i)\n"); 
 +        $var(i) = $var(i) + 1; 
 +    } 
 + 
 +===== Script Operations ===== 
 + 
 +Assignments together with string and arithmetic operations can be done directly in configuration file. 
 +==== Assignment ==== 
 + 
 +Assignments can be done like in C, via '=' (equal). The following pseudo-variables can be used in left side of an assignment: 
 +  * Unordered List Item AVPs - to set the value of an AVP 
 +  * script variables ($var(...)) -  to set the value of a script variable 
 +  * shared variables ($shv(...)) 
 +  * $ru - to set R-URI 
 +  * $rd - to set domain part of R-URI 
 +  * $rU - to set user part of R-URI 
 +  * $rp - to set the port of R-URI 
 +  * $du - to set dst URI 
 +  * $fs - to set send socket 
 +  * $br - to set branch 
 +  * $mf - to set message flags value 
 +  * $sf - to set script flags value 
 +  * $bf - to set branch flags value 
 + 
 +<code> 
 +$var(a) = 123; 
 +</code> 
 + 
 +For avp's there a way to remove all values and assign a single value in one statement (in other words, delete existing AVPs with same name, add a new one with the right side value). This replaces the := assignment operator from kamailio < 3.0. 
 +<code> 
 +$(avp(i:3)[*]) = 123; 
 +$(avp(i:3)[*]) = $null; 
 +</code> 
 + 
 +==== String Operations ==== 
 +For strings, '+' is available to concatenate. 
 + 
 +<code> 
 +$var(a) = "test"; 
 +$var(b) = "sip:" + $var(a) + "@" + $fd; 
 +</code> 
 +==== Arithmetic Operations ==== 
 + 
 +For numbers, one can use: 
 +  * + : plus 
 +  * - : minus 
 +  * / : divide 
 +  * * : multiply 
 +  * % : modulo (Kamailio uses 'mod' instead of '%'
 +  * | : bitwise OR 
 +  * & : bitwise AND 
 +  * ^ : bitwise XOR 
 +  * ~ : bitwise NOT 
 +  * <nowiki><<</nowiki> : bitwise left shift 
 +  * <nowiki>>></nowiki> : bitwise right shift 
 + 
 + 
 +Example: 
 + 
 +<code> 
 +$var(a) = 4 + ( 7 & ( ~2 ) ); 
 +</code> 
 + 
 +NOTE: to ensure the priority of operands in expression evaluations do use __parenthesis__. 
 + 
 +Arithmetic expressions can be used in condition expressions. 
 + 
 +<code> 
 +if( $var(a) & 4 ) 
 +    log("var a has third bit set\n"); 
 +</code> 
 + 
 +===== Operators ===== 
 + 
 +  - type casts operators: (int), (str). 
 +  - string comparison: eq, ne 
 +  - integer comparison: ieq, ine  
 + 
 +Note: The names are not yet final (use them at your own risk). Future version might use ==/!= only for ints (ieq/ine) and eq/ne for strings (under debate). They are almost equivalent to == or !=, but they force the conversion of their operands (eq to string and ieq to int), allowing among other things better type checking on startup and more optimizations. 
 + 
 +Non equiv. examples: 
 + 
 +0 == "" (true) is not equivalent to 0 eq "" (false: it evaluates to "0" eq ""). 
 + 
 +"a" ieq "b" (true: (int)"a" is 0 and (int)"b" is 0) is not equivalent to "a" == "b" (false). 
 + 
 +Note: internally == and != are converted on startup to eq/ne/ieq/ine  whenever possible (both operand types can be safely determined at start time and they are the same).  
 + 
 +  - Kamailio tries to guess what the user wanted when operators that support multiple types are used on different typed operands. In general convert the right operand to the type of the left operand and then perform the operation. Exception: the left operand is undef. This applies to the following operators: +, == and !=. 
 +     Special case: undef as left operand: 
 +     For +: undef + expr -> undef is converted to string => "" + expr. 
 +     For == and !=:   undef == expr -> undef is converted to type_of expr. 
 +     If expr is undef, then undef == undef is true (internally is converted 
 +     to string). 
 + 
 +  - expression evaluation changes: Kamailio will auto-convert to integer or string in function of the operators:  
 +       int(undef)==0,  int("")==0, int("123")==123, int("abc")==0 
 +       str(undef)=="", str(123)=="123"
 + 
 +  - script operators for dealing with empty/undefined variables 
 +      defined expr - returns true if expr is defined, and false if not. 
 +                     Note: only a standalone avp or pvar can be 
 +                     undefined, everything else is defined. 
 +      strlen(expr) - returns the lenght of expr evaluated as string. 
 +      strempty(expr) - returns true if expr evaluates to the empty 
 +                       string (equivalent to expr==""). 
 +      Example: if (defined $v && !strempty($v)) $len=strlen($v); 
 + 
 +===== Command Line Parameters ===== 
 + 
 +Kamailio can be started with a set of command line parameters, providing more flexibility to control what is doing at runtime. Some of them can be quite useful when running on containerised environments. 
 + 
 +To see the the available command line parameters, run **kamailio -h**: 
 + 
 +<code> 
 +# kamailio -h 
 + 
 +version: kamailio 5.4.0-dev4 (x86_64/darwin) 8c1864 
 +Usage: kamailio [options] 
 +Options: 
 +    -a mode      Auto aliases mode: enable with yes or on, 
 +                  disable with no or off 
 +    --alias=val  Add an alias, the value has to be '[proto:]hostname[:port]' 
 +                  (like for 'alias' global parameter) 
 +    -A define    Add config pre-processor define (e.g., -A WITH_AUTH, 
 +                  -A 'FLT_ACC=1', -A 'DEFVAL="str-val"'
 +    -b nr        Maximum receive buffer size which will not be exceeded by 
 +                  auto-probing procedure even if  OS allows 
 +    -c           Check configuration file for syntax errors 
 +    -d           Debugging mode (multiple -d increase the level) 
 +    -D           Control how daemonize is done: 
 +                  -D..do not fork (almost) anyway; 
 +                  -DD..do not daemonize creator; 
 +                  -DDD..daemonize (default) 
 +    -e           Log messages printed in terminal colors (requires -E) 
 +    -E           Log to stderr 
 +    -f file      Configuration file (default: /usr/local/etc/kamailio/kamailio.cfg) 
 +    -g gid       Change gid (group id) 
 +    -G file      Create a pgid file 
 +    -h           This help message 
 +    --help       Long option for `-h` 
 +    -I           Print more internal compile flags and options 
 +    -K           Turn on "via:" host checking when forwarding replies 
 +    -l address   Listen on the specified address/interface (multiple -l 
 +                  mean listening on more addresses). The address format is 
 +                  [proto:]addr_lst[:port][/advaddr], 
 +                  where proto=udp|tcp|tls|sctp, 
 +                  addr_lst= addr|(addr, addr_lst), 
 +                  addr=host|ip_address|interface_name and 
 +                  advaddr=addr[:port] (advertised address). 
 +                  E.g: -l localhost, -l udp:127.0.0.1:5080, -l eth0:5062, 
 +                  -l udp:127.0.0.1:5080/1.2.3.4:5060, 
 +                  -l "sctp:(eth0)", -l "(eth0, eth1, 127.0.0.1):5065"
 +                  The default behaviour is to listen on all the interfaces. 
 +    --loadmodule=name load the module specified by name 
 +    --log-engine=log engine name and data 
 +    -L path      Modules search path (default: /usr/local/lib64/kamailio/modules) 
 +    -m nr        Size of shared memory allocated in Megabytes 
 +    --modparam=modname:paramname:type:value set the module parameter 
 +                  type has to be 's' for string value and 'i' for int value, 
 +                  example: --modparam=corex:alias_subdomains:s:kamailio.org 
 +    -M nr        Size of private memory allocated, in Megabytes 
 +    -n processes Number of child processes to fork per interface 
 +                  (default: 8) 
 +    -N           Number of tcp child processes (default: equal to `-n'
 +    -O nr        Script optimization level (debugging option) 
 +    -P file      Create a pid file 
 +    -Q           Number of sctp child processes (default: equal to `-n'
 +    -r           Use dns to check if is necessary to add a "received=" 
 +                  field to a via 
 +    -R           Same as `-r` but use reverse dns; 
 +                  (to use both use `-rR`) 
 +    --server-id=num set the value for server_id 
 +    --subst=exp set a subst preprocessor directive 
 +    --substdef=exp set a substdef preprocessor directive 
 +    --substdefs=exp set a substdefs preprocessor directive 
 +    -S           disable sctp 
 +    -t dir       Chroot to "dir" 
 +    -T           Disable tcp 
 +    -u uid       Change uid (user id) 
 +    -v           Version number 
 +    --version    Long option for `-v` 
 +    -V           Alternative for `-v` 
 +    -x name      Specify internal manager for shared memory (shm) 
 +                  - can be: fm, qm or tlsf 
 +    -X name      Specify internal manager for private memory (pkg) 
 +                  - if omitted, the one for shm is used 
 +    -Y dir       Runtime dir path 
 +    -w dir       Change the working directory to "dir" (default: "/"
 +    -W type      poll method (depending on support in OS, it can be: poll, 
 +                  epoll_lt, epoll_et, sigio_rt, select, kqueue, /dev/poll) 
 +</code> 
 + 
 +==== Log Engine CLI Parameter ==== 
 + 
 +The **--log-engine** parameter allows to specify what logging engine to be used, which is practically about the format of the log messages. If not set at all, then Kamailio does the classic style of line-based plain text log messages. 
 + 
 +The value of this parameter can be **--log-engine=name** or **--log-engine=name:data**. 
 + 
 +The name of the log engine can be: 
 + 
 +  * **json** - write logs in structured JSON format 
 +    * the **data** for **json** log engine can be a set of character flags: 
 +      * **a** - add log prefix as a special field 
 +      * **A** - do not add log prefix 
 +      * **c** - add Call-ID (when available) as a dedicated JSON attribute 
 +      * **M** - strip EOL ('\n') from the value of the log message field 
 +      * **N** - do not add EOL at the end of JSON document 
 + 
 +Example of JSON logs when running Kamailio with "**--log-engine=json:M**"
 + 
 +<code> 
 +{ "idx": 1, "pid": 18239, "level": "DEBUG", "module": "maxfwd", "file": "mf_funcs.c", "line": 74, "function": "is_maxfwd_present", "logprefix": "{1 1 OPTIONS 715678756@192.168.188.20} ", "message": "value = 70 " } 
 + 
 +{ "idx": 1, "pid": 18239, "level": "DEBUG", "module": "core", "file": "core/socket_info.c", "line": 644, "function": "grep_sock_info", "logprefix": "{1 1 OPTIONS 715678756@192.168.188.20} ", "message": "checking if host==us: 9==9 && [127.0.0.1] == [127.0.0.1]"
 + 
 +</code>
cookbooks/devel/core.txt · Last modified: 2022/04/11 17:10 by bkaufman