tutorials:faq:main
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorials:faq:main [2013/04/06 12:42] – [Getting Started] oej | tutorials:faq:main [2021/08/27 06:11] (current) – [SIP Message Processing] miconda | ||
---|---|---|---|
Line 47: | Line 47: | ||
??? Is it possible to reload Kamailio configuration file? | ??? Is it possible to reload Kamailio configuration file? | ||
- | !!! No, you must restart after you update the configuration file. | + | !!! If you use native scripting language, you must restart after you update the configuration file. |
But note that many global parameters can be changed via RPC/MI commands without restart (e.g., TCP connecting timeout, debug level). Applying changes related to loaded modules or routing block require always a restart. | But note that many global parameters can be changed via RPC/MI commands without restart (e.g., TCP connecting timeout, debug level). Applying changes related to loaded modules or routing block require always a restart. | ||
+ | |||
+ | If you use a KEMI scripting language (Lua, Python, JavaScript, Ruby, Squirrel), then you can reload the routing logic script without restarting Kamailio by issuing an RPC command (see KEMI interpreter modules documentation for more details: app_lua, app_python, app_python3, | ||
??? What is the license of Kamailio? | ??? What is the license of Kamailio? | ||
- | !!! Kamailio is an open source application licensed under GNU Public License version 2 (aka GPLv2). It can be used for free "as in beer". | + | !!! Kamailio is an open source application licensed under GNU Public License version 2 (aka GPLv2). It can be used for free "as in beer" |
Starting with end of 2008, contributions to core and several modules are done under BSD license. That means parts of it can be extracted and used under BSD license terms. But over all, when used as one application, | Starting with end of 2008, contributions to core and several modules are done under BSD license. That means parts of it can be extracted and used under BSD license terms. But over all, when used as one application, | ||
Line 130: | Line 132: | ||
make install include_modules=" | make install include_modules=" | ||
</ | </ | ||
+ | |||
+ | ??? How to compile only one module? | ||
+ | |||
+ | !!! First be sure that the core compiles fine with the command: | ||
+ | |||
+ | < | ||
+ | make | ||
+ | </ | ||
+ | |||
+ | To compile a single module, use: | ||
+ | |||
+ | < | ||
+ | make modules modules=modules/ | ||
+ | </ | ||
+ | |||
+ | Replace modname with the real name of the module you want to compile -- for example, compiling only tls module: | ||
+ | |||
+ | < | ||
+ | make modules modules=modules/ | ||
+ | </ | ||
+ | |||
=?==== SIP Message Processing ===== | =?==== SIP Message Processing ===== | ||
Line 144: | Line 167: | ||
* without applying changes | * without applying changes | ||
- | < | + | < |
append_hf(" | append_hf(" | ||
Line 156: | Line 179: | ||
* with applying changes | * with applying changes | ||
- | < | + | < |
append_hf(" | append_hf(" | ||
Line 168: | Line 191: | ||
</ | </ | ||
+ | ??? Why parts of From/To header appear many times? | ||
+ | |||
+ | !!! After doing header management operations, it can result that parts of From/To header are duplicated or the result is the concatenation of many values. That is related to previous question, because the changes are not applied immediately and updates to parts of headers are not a simple set operation. | ||
+ | |||
+ | For example, if From username is " | ||
+ | |||
+ | <code c> | ||
+ | $fU = " | ||
+ | ... | ||
+ | $fU = " | ||
+ | </ | ||
+ | |||
+ | The result can be that From username is " | ||
+ | |||
+ | One solution is to use **msg_apply_changes()** in between: | ||
+ | |||
+ | <code c> | ||
+ | $fU = " | ||
+ | msg_apply_changes(); | ||
+ | ... | ||
+ | $fU = " | ||
+ | </ | ||
+ | |||
+ | Another solution is to keep the value in a variable (e.g., avp or xavp) and do the operation only once, like: | ||
+ | |||
+ | <code c> | ||
+ | $xavp(fuser) = " | ||
+ | ... | ||
+ | $xavp(fuser[0]) = " | ||
+ | ... | ||
+ | $fU = $xavp(fuser); | ||
+ | </ | ||
+ | |||
+ | Updating From/To headers is recommended to be done in **branch_route**, | ||
+ | |||
+ | The examples above were with assignments to $fU (can be other vars as well, such as $fu, $tU, $tu, ..), but it is the same behaviour when using functions such as uac_replace_from() or uac_replace_to(). | ||
+ | |||
+ | ??? Why body or other parts of the SIP message appear multiple times? | ||
+ | |||
+ | !!! It is practically the same reason as for multiple From/To parts. | ||
+ | |||
+ | The configuration file does an operation that changes parts in the headers or body many times. For example, if the body has two concatenated IP addresses for media stream, then likely the rtpproxy function is used twice, or, if the SDP appears two time, then the rtpengine function is used two times. | ||
+ | |||
+ | If the update has to be done many times, use **msg_apply_changes()** in between, otherwise refactor the config to perform the operation only once (e.g., the RTP relaying functions should be used in a branch_route block). | ||
+ | |||
+ | ??? How to set different header values for each destination of a SIP request? | ||
+ | |||
+ | !!! Set the value of the header inside a **branch_route**. | ||
+ | |||
+ | All the operations done over a SIP message inside the **request_route** (including from the sub-routes executed from request_route) will be common to all outgoing branches. If you want to do updates only for specific destinations, | ||
+ | |||
+ | Example: | ||
+ | |||
+ | * add X-VBox header only when sending to voicemail server | ||
+ | * add X-Peer-ID header when sending somewhere else | ||
+ | |||
+ | <code c> | ||
+ | request_route { | ||
+ | ... | ||
+ | if(is_method(" | ||
+ | t_on_branch(" | ||
+ | t_on_failure(" | ||
+ | } | ||
+ | t_relay(); | ||
+ | exit; | ||
+ | } | ||
+ | |||
+ | branch_route[SETHEADERS] { | ||
+ | | ||
+ | | ||
+ | } else { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | failure_route[REROUTE] { | ||
+ | if (t_is_canceled()) { | ||
+ | exit; | ||
+ | } | ||
+ | if (t_check_status(" | ||
+ | $du = $null; | ||
+ | $ru = " | ||
+ | t_on_failure(" | ||
+ | exit; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Very important is also to be aware that doing same operation many times in request_route is not overwriting the previous value, but combines them. For example, if you do two times uac_replace_from(), | ||
+ | |||
+ | <code c> | ||
+ | request_route { | ||
+ | ... | ||
+ | uac_replace_from(" | ||
+ | uac_replace_from(" | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Results in From header having the URI: **sip: | ||
+ | |||
+ | |||
+ | ??? How to remove a single header field when a header appears multiple times? | ||
+ | |||
+ | !!! SIP allows that certain header fields may appear multiple times in a SIP message. This header fields (e.g. Via, Route, Record-Route, | ||
+ | |||
+ | The remove_hf() function from textops module always removes all header fields with a certain name, thus it can not be used in this case. | ||
+ | |||
+ | To address a certain header (regardless if headers are in a single line or in separate lines) use the @hf_value select. The trick is to load the textopsx module (this select used to be in ser's textops module). Note, header names must use ' | ||
+ | |||
+ | For example, incoming message: | ||
+ | < | ||
+ | Record-Route: | ||
+ | Record-Route: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Dump all headers: | ||
+ | < | ||
+ | xlog(" | ||
+ | </ | ||
+ | |||
+ | Dump the first header (< | ||
+ | < | ||
+ | xlog(" | ||
+ | </ | ||
+ | |||
+ | Dump the second last header (< | ||
+ | < | ||
+ | xlog(" | ||
+ | </ | ||
+ | |||
+ | Remove the last header (< | ||
+ | < | ||
+ | remove_hf_value(" | ||
+ | #or in above case: | ||
+ | remove_hf_value(" | ||
+ | </ | ||
+ | |||
+ | ??? Why the SIP requests are replied with "483 Too Many Hops" or "513 Message Too Large"? | ||
+ | |||
+ | !!! In both cases, the reason is probably an error in request routing script which caused an infinite loop. | ||
+ | |||
+ | You can easily verify whether this happens by watching SIP traffic on loopback interface, for example using ngrep: | ||
+ | |||
+ | < | ||
+ | ngrep -d lo -qt -W byline port 5060 | ||
+ | </ | ||
+ | |||
+ | |||
+ | A typical reason for misrouting is a failure to match local domain correctly. If a server fails to recognize a request for itself, it will try to forward it to current URI in believe it would forward them to a foreign domain. | ||
+ | |||
+ | Alas, it forwards the request to itself again. This continues to happen until value of the max_forwards header field reaches zero or the request grows too big. | ||
+ | |||
+ | The solution: make sure that domain matching is correctly configured. | ||
+ | |||
+ | A quick way to achieve that is to introduce a config option to kamailio.cfg: | ||
+ | |||
+ | < | ||
+ | alias=domainname | ||
+ | </ | ||
+ | |||
+ | where domainname has to be replaced with name of domain, which you wish to serve by Kamailio and which appears in request-URIs. | ||
+ | |||
+ | |||
+ | ??? I send SIP requests to Kamailio, but nothing happens, why? | ||
+ | |||
+ | !!! Check if you have a firewall rule dropping traffic on SIP port (5060). Note that network sniffing tools have hooks in kernel before the firewall, so even if you see the SIP packets with ngrep or wireshark, they may be dropped by the firewall. | ||
+ | |||
+ | If you have the pike module loaded, double check to see if you don't block valid trusted traffic with it. | ||
+ | |||
+ | You can increase the debug parameter value to 3 in the configuration file, restart kamailio and watch syslog messages to see if there is any text printed by kamailio. For each SIP packet received on the networks, Kamailio is printing at least few debug messages. | ||
=?==== Media Streams ===== | =?==== Media Streams ===== | ||
Line 173: | Line 368: | ||
!!! No, //however// Kamailio can be configured to proxy media if needed. | !!! No, //however// Kamailio can be configured to proxy media if needed. | ||
- | * [[http:// | + | * [[http:// |
??? What codecs are supported by Kamailio? | ??? What codecs are supported by Kamailio? | ||
Line 228: | Line 423: | ||
!!! Use the bug tracker available at: | !!! Use the bug tracker available at: | ||
- | * http://sip-router.org/tracker | + | * https://github.com/kamailio/ |
??? Where can I buy commercial support? | ??? Where can I buy commercial support? | ||
Line 354: | Line 549: | ||
</ | </ | ||
- | =?==== SIP Requests Routing ===== | + | ??? What is a pseudo-variable? |
- | ??? Why the SIP requests are replied | + | !!! A pseudo-variable is a special token that is expanded at runtume |
- | !!! In both cases, | + | A pseudo-variable can refer to the value of an avp, body of a header, part of a SIP message or other variables from system. |
- | You can easily verify whether this happens by watching SIP traffic on loopback interface, for example using ngrep: | + | For more see: |
+ | * http:// | ||
- | < | + | ??? How to iterate through the items in a comma separated string? |
- | ngrep -d lo -qt -W byline port 5060 | + | |
+ | !!! If you have a variable holding a string like " | ||
+ | |||
+ | Here is an example: | ||
+ | |||
+ | < | ||
+ | $var(x) = " | ||
+ | $var(i) = 0; | ||
+ | $var(n) = $(var(x){s.count,, | ||
+ | |||
+ | while( $var(i) <= $var(n) ) { | ||
+ | | ||
+ | | ||
+ | } | ||
</ | </ | ||
+ | ??? How is the function return code evaluated? | ||
- | A typical reason for misrouting is a failure to match local domain correctly. If a server fails to recognize a request for itself, it will try to forward it to current URI in believe it would forward them to a foreign domain. | + | !!! Configuration file interpreter evaluates the return code of a function as follow: |
- | Alas, it forwards the request | + | * <0 (negative value) - it is evaluated |
+ | * >0 (positive | ||
+ | * =0 (zero) - it is evaluated as exit (stop execution of configuration file) | ||
- | The solution: make sure that domain matching is correctly configured. | + | Example: |
- | A quick way to achieve that is to introduce a config option to kamailio.cfg: | + | <code c> |
- | < | + | if(function_returns_one()) { |
- | alias=domainname | + | # it goes here |
+ | } else { | ||
+ | # it doesn' | ||
+ | } | ||
+ | ... | ||
+ | if(function_returns_minus_one()) { | ||
+ | # it doesn' | ||
+ | } else { | ||
+ | # it goes here | ||
+ | } | ||
+ | ... | ||
+ | if(function_returns_zero()) { | ||
+ | # it doesn' | ||
+ | } else { | ||
+ | # it doesn' | ||
+ | } | ||
</ | </ | ||
- | where domainname has to be replaced with name of domain, which you wish to serve by Kamailio and which appears in request-URIs. | + | Note that you can use $rc to get the return code value, like: |
+ | <code c> | ||
+ | function(); | ||
+ | xlog(" | ||
+ | </ | ||
- | ??? I send SIP requests to Kamailio, but nothing happens, why? | + | However, if return code is 0, the next action after function() is not executed. It can be used only of positive or negative response code. |
- | !!! Check if you have a firewall rule dropping traffic on SIP port (5060). Note that network sniffing tools have hooks in kernel before the firewall, so even if you see the SIP packets with ngrep or wireshark, they may be dropped by the firewall. | + | On the other hand, the pseudo-variables |
- | You can increase | + | <code c> |
+ | $var(x) = 0; | ||
+ | if($var(x) == 0) { | ||
+ | # do something | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | To compare | ||
+ | |||
+ | <code c> | ||
+ | function_returns_four(); | ||
+ | $var(rc4) = $rc; | ||
+ | if($var(rc4)==4) { | ||
+ | # it goes here | ||
+ | } else { | ||
+ | # it doesn' | ||
+ | } | ||
+ | ... | ||
+ | function_returns_two(); | ||
+ | $var(rc2) = $rc; | ||
+ | if($var(rc4)==$var(rc2)) { | ||
+ | # it doesn' | ||
+ | } else { | ||
+ | # it goes here | ||
+ | } | ||
+ | ... | ||
+ | if (function_returns_four() && $rc ieq 6 ) { | ||
+ | # it doesn' | ||
+ | } else if ($rc ieq 4) { | ||
+ | # it goes here | ||
+ | } else { | ||
+ | # it doesn' | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Note that $rc is overwritten by a new function call, therefore store its value in another variable (like $var(...)) if it is needed for longer time. | ||
+ | |||
+ | For pseudo-variables, | ||
+ | |||
+ | <code c> | ||
+ | $var(x) = 1; | ||
+ | if($var(x)) { | ||
+ | # do something | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ??? How is the SIP request retransmission handled? | ||
+ | |||
+ | !!! The next snippet is detecting retransmissions: | ||
+ | |||
+ | <code c> | ||
+ | # handle retransmissions | ||
+ | if (!is_method(" | ||
+ | if(t_precheck_trans()) { | ||
+ | t_check_trans(); | ||
+ | exit; | ||
+ | } | ||
+ | t_check_trans(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The **ACK** request is skipped because it doesn' | ||
+ | |||
+ | The function **t_precheck_trans()** returns true if the same SIP request is processed at that time by another Kamailio process, so in this case it is a retransmission. The inner **t_check_trans()** has the role of detecting if the SIP transaction was created by the other process, and if yes, send again the last SIP response of the transaction, | ||
+ | If the function **t_precheck_trans()** returns false, the SIP request is not under processing by another Kamailio process, but it can be the case that the request processing was finished, request being sent out in stateful mode, therefore **t_check_trans()** is used to see if a transaction is found in shared memory corresponding to the same request. If such transaction is found in shared memory, then **t_check_trans()** triggers internally the **exit** for configuration file execution. | ||
=?==== Troubleshooting ===== | =?==== Troubleshooting ===== | ||
Line 400: | Line 695: | ||
To increase the sizes for memory pools you have to give following command line parameters: | To increase the sizes for memory pools you have to give following command line parameters: | ||
* **-m SIZE** - specify the shared memory size in MB | * **-m SIZE** - specify the shared memory size in MB | ||
- | * **-M SIZE** - specify the shared | + | * **-M SIZE** - specify the private |
For example, start Kamailio with 512MB of shared memory and 8MB of private memory: | For example, start Kamailio with 512MB of shared memory and 8MB of private memory: | ||
Line 440: | Line 735: | ||
Check also the access privileges of the FIFO file in order to be sure that the user running kamctl can read and write to the file. | Check also the access privileges of the FIFO file in order to be sure that the user running kamctl can read and write to the file. | ||
+ | |||
+ | ??? Kamcmd sometime fails to execute RPC commands with number parameters, why? | ||
+ | |||
+ | !!! There are situations when a **kamcmd** RPC command fails because the parameters that are provided are auto-converted to integer numbers. This happens when the implementation of the RPC commands expects a string parameter (e.g., username). | ||
+ | |||
+ | To prevent **kamcmd** to do the auto-conversion, | ||
+ | |||
+ | Example: | ||
+ | |||
+ | < | ||
+ | # - next command fails | ||
+ | kamcmd uac.reg_refresh 1001 | ||
+ | |||
+ | # use instead | ||
+ | kamcmd uac.reg_refresh s:1001 | ||
+ | </ |
tutorials/faq/main.1365252133.txt.gz · Last modified: 2013/04/06 12:42 by oej