mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
654 lines
20 KiB
654 lines
20 KiB
<?xml version="1.0" encoding='ISO-8859-1'?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
|
|
|
|
<!-- Include general documentation entities -->
|
|
<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
|
|
%docentities;
|
|
|
|
]>
|
|
<!-- Module User's Guide -->
|
|
|
|
<chapter>
|
|
|
|
<title>&adminguide;</title>
|
|
|
|
<section>
|
|
<title>Overview</title>
|
|
<para>
|
|
This module provides reimplementation of a few very old functions that
|
|
used to be in the core and supported only static string or integer parameters.
|
|
The new versions bring support for dynamic parameters (allowing
|
|
variables inside the parameters).
|
|
</para>
|
|
<para>
|
|
There are also brand new features, related to core internals, but
|
|
controlled from configuration file or via control interfaces.
|
|
</para>
|
|
<para>
|
|
Contributions to this module must be done under the BSD license, to
|
|
follow the requirements of the core contributions.
|
|
</para>
|
|
<para>
|
|
This module now also provides access to network input / output data through
|
|
event_route[network:msg]. The raw data received from a remote host or about to
|
|
be sent to a remote host is available in variable $mb. The script writer may
|
|
manipulate this data and save the final result in an AVP defined by msg_avp
|
|
module parameter. The content of this AVP will then be processed by SIP worker
|
|
as normal, i.e. a received message will be parsed and sent to appropriate
|
|
route block while a sent message is forwarded to remote host.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Dependencies</title>
|
|
<section>
|
|
<title>&kamailio; Modules</title>
|
|
<para>
|
|
The following modules must be loaded before this module:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>None</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>External Libraries or Applications</title>
|
|
<para>
|
|
The following libraries or applications must be installed before running
|
|
&kamailio; with this module loaded:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>None</emphasis>
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Parameters</title>
|
|
<section id="corex.p.alias_subdomains">
|
|
<title><varname>alias_subdomains</varname> (string)</title>
|
|
<para>
|
|
Register a domain and all its sub-domains to match the <quote>myself</quote>
|
|
condition. It can be set many times. Its full format is:
|
|
'proto:domain:port', allowing to set restrictions on protocol
|
|
and port as well. Protocol and port are optional.
|
|
</para>
|
|
<para>
|
|
<emphasis>
|
|
Default value is <quote>NULL</quote>.
|
|
</emphasis>
|
|
</para>
|
|
<example>
|
|
<title>Set <varname>alias_subdomains</varname> parameter</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
modparam("corex", "alias_subdomains", "kamailio.org")
|
|
modparam("corex", "alias_subdomains", "udp:sip-router.org:5060")
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="corex.p.network_io_intercept">
|
|
<title><varname>network_io_intercept</varname> (int)</title>
|
|
<para>
|
|
If set to non-zero then raw data received from a remote host or about to
|
|
be sent to a remote host is made available in event_route[network:msg].
|
|
The script writer may modify this and save to msg_avp, which will then
|
|
be processed by SIP worker as normal.
|
|
</para>
|
|
<para>
|
|
<emphasis>
|
|
Default value is 0, i.e. do not allow access to network io data.
|
|
</emphasis>
|
|
</para>
|
|
<example>
|
|
<title>Set <varname>network_io_intercept</varname> parameter</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
modparam("corex", "network_io_intercept", 1)
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="corex.p.min_msg_len">
|
|
<title><varname>min_msg_len</varname> (int)</title>
|
|
<para>
|
|
Minimum content length of the packet to execute the event_route[network:msg].
|
|
This only works if network_io_intercept parameter is set to non-zero.
|
|
</para>
|
|
<para>
|
|
<emphasis>
|
|
Default value is 0.
|
|
</emphasis>
|
|
</para>
|
|
<example>
|
|
<title>Set <varname>min_msg_len</varname> parameter</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
modparam("corex", "min_msg_len", 32)
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="corex.p.msg_avp">
|
|
<title><varname>msg_avp</varname> (string)</title>
|
|
<para>
|
|
AVP name to store modified content to be set in the packet. If not set in
|
|
event_route[network:msg], then all changes are lost and original contents
|
|
are used. This only works if network_io_intercept parameter is to set non-zero.
|
|
</para>
|
|
<para>
|
|
<emphasis>
|
|
Default value is empty.
|
|
</emphasis>
|
|
</para>
|
|
<example>
|
|
<title>Set <varname>msg_avp</varname> parameter</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
modparam("corex", "msg_avp", "$avp(msg)")
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Functions</title>
|
|
<section id="corex.f.append_branch">
|
|
<title>
|
|
<function moreinfo="none">append_branch([ uri, [ q ] ])</function>
|
|
</title>
|
|
<para>
|
|
Append a new branch to the destination set, useful to build the
|
|
set of destination addresses for parallel forking or redirect replies.
|
|
</para>
|
|
<para>
|
|
Both parameters are optional, If no uri parameter is provided,
|
|
then the address from request URI (r-uri) is used to build the
|
|
new branch.
|
|
</para>
|
|
<para>Meaning of the parameters is as follows:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>uri</emphasis> - SIP address of the branch to be
|
|
used as R-URI in the outgoing request.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>q</emphasis> - the Q value to set the priority
|
|
of the branch based on Contact address specifications
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
This function can be used from REQUEST_ROUTE or FAILURE_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>append_branch</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
append_branch();
|
|
append_branch("$avp(uri)", "0.5");
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.send">
|
|
<title>
|
|
<function moreinfo="none">send([ host [ :port ] ])</function>
|
|
</title>
|
|
<para>
|
|
Send the original SIP message to a specific destination in stateless
|
|
mode. No changes are applied to received message, no Via header is
|
|
added. Host can be an IP address or hostname. Port is optional and
|
|
defaults to 5060. Used protocol: UDP.
|
|
</para>
|
|
<para>
|
|
The parameter is optional and defaults to the destination URI from
|
|
the SIP message if left out. Otherwise it's a string parameter
|
|
(supporting pseudo-variables) in format
|
|
"<emphasis>hostname</emphasis>" or
|
|
"<emphasis>hostname</emphasis>:<emphasis>port</emphasis>",
|
|
where <emphasis>hostname</emphasis>" can also be a numeric IP
|
|
address.
|
|
</para>
|
|
<para>
|
|
This function can be used from REQUEST_ROUTE or FAILURE_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>send</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
send();
|
|
send("10.20.15.10");
|
|
send("sip.example.com:5070");
|
|
send("$var(res)");
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.send_tcp">
|
|
<title>
|
|
<function moreinfo="none">send_tcp([ host [ :port ] ])</function>
|
|
</title>
|
|
<para>
|
|
This function is identical to <emphasis>send()</emphasis>
|
|
described above, except that it sends the SIP message using the
|
|
TCP protocol instead of UDP.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="corex.f.send_data">
|
|
<title>
|
|
<function moreinfo="none">send_data(uri, data)</function>
|
|
</title>
|
|
<para>
|
|
Send the data to address specified by uri. Both parameters can
|
|
contain pseudo-variables. The uri parameter has to be a valid
|
|
SIP URI. The data parameter can by any arbitrary content.
|
|
</para>
|
|
<para>
|
|
This function can be used from ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>send_data</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
send_data("sip:example.com:5070;transport=sctp", "Message at $Ts");
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="corex.f.is_incoming">
|
|
<title>
|
|
<function moreinfo="none">is_incoming()</function>
|
|
</title>
|
|
<para>
|
|
Returns true if contents of message buffer $mb are the data received from
|
|
remote host, otherwise false indicating that the contents of $mb are data
|
|
that is about to be sent out to remote host. This only works if
|
|
network_io_intercept parameter is set to non-zero.
|
|
</para>
|
|
<para>
|
|
This function can be used from event_route[network:msg].
|
|
</para>
|
|
<example>
|
|
<title><function>is_incoming</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[network:msg] {
|
|
if (is_incoming()) {
|
|
xlog("L_INFO", "Received message '$mb' \n");
|
|
$avp(msg) = $mb;
|
|
} else {
|
|
xlog("L_INFO", "Sending message '$mb' \n");
|
|
$avp(msg) = $mb;
|
|
};
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.msg_iflag_set">
|
|
<title>
|
|
<function moreinfo="none">msg_iflag_set(flagname)</function>
|
|
</title>
|
|
<para>
|
|
Set internal SIP message flag. The parameter flagname can be:
|
|
USE_UAC_FROM, USE_UAC_TO or UAC_AUTH.
|
|
</para>
|
|
<para>
|
|
This functions should not be used in configuration file for
|
|
(re)setting the internal flags, those are done by various
|
|
functions internally, however, in very particular cases they
|
|
might be useful (e.g., changing From/To via textops functions).
|
|
</para>
|
|
<para>
|
|
This function can be used from ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msg_iflag_set</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
msg_iflag_set("UAC_AUTH");
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.msg_iflag_reset">
|
|
<title>
|
|
<function moreinfo="none">msg_iflag_reset(flagname)</function>
|
|
</title>
|
|
<para>
|
|
Reset the internal flag given as parameter.
|
|
</para>
|
|
<para>
|
|
This function can be used from ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msg_iflag_reset</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
msg_iflag_reset("UAC_AUTH");
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.msg_iflag_is_set">
|
|
<title>
|
|
<function moreinfo="none">msg_iflag_is_set(flagname)</function>
|
|
</title>
|
|
<para>
|
|
Test if the internal flag given as parameter is set.
|
|
</para>
|
|
<para>
|
|
This function can be used from ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msg_iflag_is_set</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
if(msg_iflag_is_set("UAC_AUTH")) { ... }
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.file_read">
|
|
<title>
|
|
<function moreinfo="none">file_read(fpath, var)</function>
|
|
</title>
|
|
<para>
|
|
Read content of a text file into a variable.
|
|
</para>
|
|
<para>
|
|
This function can be used from ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>file_read</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
if(file_read("/tmp/data.txt", "$var(data)")) { ... }
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section id="corex.f.file_write">
|
|
<title>
|
|
<function moreinfo="none">file_write(fpath, content)</function>
|
|
</title>
|
|
<para>
|
|
Write content of parameter to a text file.
|
|
</para>
|
|
<para>
|
|
This function can be used from ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>file_write</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
if(file_write("/tmp/data.txt", "Data is: $var(data)")) { ... }
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>RPC Commands</title>
|
|
<section id="corex.rpc.list_sockets">
|
|
<title>
|
|
<function moreinfo="none">corex.list_sockets</function>
|
|
</title>
|
|
<para>
|
|
Print the list of sockets the application is listening on.
|
|
</para>
|
|
<para>
|
|
Example:
|
|
</para>
|
|
<programlisting format="linespecific">
|
|
&sercmd; corex.list_sockets
|
|
</programlisting>
|
|
</section>
|
|
<section id="corex.rpc.list_aliases">
|
|
<title>
|
|
<function moreinfo="none">corex.list_aliases</function>
|
|
</title>
|
|
<para>
|
|
Print the list of hostname aliases used to match the myself
|
|
condition.
|
|
</para>
|
|
<para>
|
|
Example:
|
|
</para>
|
|
<programlisting format="linespecific">
|
|
&sercmd; corex.list_aliases
|
|
</programlisting>
|
|
</section>
|
|
<section id="corex.rpc.shm_status">
|
|
<title>
|
|
<function moreinfo="none">corex.shm_status</function>
|
|
</title>
|
|
<para>
|
|
Trigger shm status dump to syslog.
|
|
</para>
|
|
<para>
|
|
Example:
|
|
</para>
|
|
<programlisting format="linespecific">
|
|
&sercmd; corex.shm_status
|
|
</programlisting>
|
|
</section>
|
|
<section id="corex.rpc.shm_summary">
|
|
<title>
|
|
<function moreinfo="none">corex.shm_summary</function>
|
|
</title>
|
|
<para>
|
|
Trigger shm summary dump to syslog.
|
|
</para>
|
|
<para>
|
|
Example:
|
|
</para>
|
|
<programlisting format="linespecific">
|
|
&sercmd; corex.shm_summary
|
|
</programlisting>
|
|
</section>
|
|
<section id="corex.rpc.pkg_summary">
|
|
<title>
|
|
<function moreinfo="none">corex.pkg_summary</function>
|
|
</title>
|
|
<para>
|
|
Trigger pkg summary dump to syslog for a specific pid or
|
|
process index. It has two parameters: first to specify what
|
|
matching type is desired (can be 'pid' or 'idx'); second to
|
|
specify the value for desired match.
|
|
</para>
|
|
<para>
|
|
The dump is happening when the selected process is doing a
|
|
runtime handling (e.g., processing a sip message).
|
|
</para>
|
|
<para>
|
|
Example:
|
|
</para>
|
|
<programlisting format="linespecific">
|
|
&sercmd; corex.pkg_summary pid 2345
|
|
&sercmd; corex.pkg_summary idx 1
|
|
</programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Event Routes</title>
|
|
<section id="async.evr.network_io">
|
|
<title>
|
|
<function moreinfo="none">event_route[network:msg]</function>
|
|
</title>
|
|
<para>
|
|
Event route block to be executed when new data is received from network
|
|
or the data that is about to be sent to a remote host by a SIP worker
|
|
process.
|
|
</para>
|
|
<para>
|
|
The kamailio script writer can check which type of data triggered this
|
|
event route using is_incoming method.
|
|
</para>
|
|
<para>
|
|
After executing of this event route, if msg_avp was defined and set then
|
|
its value is used for further processing, otherwise, original value of
|
|
$mb is used. If message was received from remote host, then it is parsed
|
|
and proceeds to appropriate route. Oterhwise if message set to send out,
|
|
then is sent to remote host per configured SIP timers in config script.
|
|
</para>
|
|
<para>
|
|
Please note this event route is meant to <emphasis>prepare</emphasis>
|
|
the message for on-wire communication, e.g. to do custom encryption or
|
|
decryption, compression/decompression etc. of the message sent to or
|
|
received from remote host. Therefore, except text operations,
|
|
no module fucntions or pseudo variables are available in this event route.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Examples of Usage</title>
|
|
<para>
|
|
To use network event_route[network:msg] the remote SIP UA must also implement and
|
|
understand the encoding / decoding done in this event route. It is up to &kamailio;
|
|
config script writer to define and implement how encoding and decoding is done.
|
|
Any language module such as app_perl or app_lua can be called in
|
|
in event_route[network:msg] to implement desired logic.
|
|
</para>
|
|
<para>
|
|
The most simple use case is to compress the SIP packet on-wire. As SIP is a
|
|
text based protocol, so it is highly compressable. Using this module, one can
|
|
compress entire SIP message, including headers and message body before sending
|
|
it to remote host using any compression algorithm of choice, thus saving
|
|
significant bandwidth on mobile data networks.
|
|
</para>
|
|
<para>
|
|
A useful case is to use this function between SIP edge proxy and SIP application
|
|
server. The SIP messages received from end-user at SIP edge proxy may be decrypted
|
|
and sent to SIP application server at remote location unencrypted, where they are
|
|
processed as normal. One the way back, the messages received from SIP application
|
|
server at edge proxy can be encrpyted before being sent to actual destination.
|
|
The edge proxy can check whether received message came from end-user or SIP
|
|
application server by using simple regular expressions.
|
|
</para>
|
|
<para>
|
|
Another use case is to implement a virtual HTTP tunnel for SIP messages. The SIP
|
|
client app can convert SIP message to binary e.g. by doing XOR, Base64 etc., then
|
|
prepend some fake HTTP headers to make it look like an HTTP request before sending
|
|
it to kamailio over SIP TCP socket. At kamailio, the fake headers are removed and data
|
|
is decoded back to normal SIP and processed per config script logic. For the data that
|
|
is to be sent to SIP client app, one can prepend fake HTTP reply headers to encoded
|
|
data before sending it to client app.
|
|
</para>
|
|
<para>
|
|
More advance use cases may involve custom encryption algorithms such as
|
|
ITV encryption algorithm,
|
|
<ulink url="https://github.com/mshary/itv"></ulink>
|
|
</para>
|
|
<para>
|
|
For example, the client app running on Android or iPhone, may send device UUID along
|
|
with ITV key, encrypted using RSA or AES256 with pre-shared secret, as first packet,
|
|
which is set as cookie by server in e.g. memcache. This cookie is referred by client
|
|
app in each next packet, so server can retrive encyption key from cache and use that
|
|
for decryption. Same can be done for server at client app side, so messages encrypted
|
|
by server can be decrypted at client app.
|
|
</para>
|
|
<para>
|
|
Next is a basic usage example where encoding and decoding is done using PERL,
|
|
</para>
|
|
<example>
|
|
<title><function>event_route[network:msg]</function> use cases</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
loadmodule "app_perl.so"
|
|
loadmodule "corex.so"
|
|
...
|
|
# ----- app_perl params -----
|
|
modparam("app_perl", "filename", "/usr/local/etc/kamailio/custom_compress.pl")
|
|
modparam("app_perl", "modpath", "/usr/local/lib64/kamailio/perl")
|
|
|
|
# ----- corex params -----
|
|
modparam("corex", "network_io_intercept", 32)
|
|
modparam("corex", "min_msg_len", 32)
|
|
modparam("corex", "msg_avp", "$avp(msg)")
|
|
...
|
|
event_route[network:msg] {
|
|
if (is_incoming()) {
|
|
if (perl_exec_simple("do_uncompress", "" + $mb + "")) {
|
|
xlog("L_INFO", "Received message '$avp(msg)' \n");
|
|
} else {
|
|
xlog("L_INFO", "Received message '$mb' \n");
|
|
$avp(msg) = $mb;
|
|
};
|
|
} else {
|
|
xlog("L_INFO", "Sending message '$mb' \n");
|
|
if (!perl_exec_simple("do_compress", "" + $mb + "")) {
|
|
$avp(msg) = $mb;
|
|
};
|
|
};
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>Sample PERL code for do_compress and do_uncompress</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
use strict;
|
|
use warnings;
|
|
use IO::Compress::Gzip qw(gzip $GzipError) ;
|
|
use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
|
|
|
|
sub do_compress() {
|
|
my $input = shift;
|
|
my $output;
|
|
|
|
gzip \$input => \$output
|
|
or eval {
|
|
Kamailio::log(L_WARN, "GZIP failed: $GzipError\n");
|
|
$output = $input;
|
|
};
|
|
|
|
Kamailio::AVP::add("msg", $output);
|
|
}
|
|
|
|
sub do_uncompress() {
|
|
my $input = shift;
|
|
my $output;
|
|
|
|
gunzip \$input => \$output
|
|
or eval {
|
|
Kamailio::log(L_WARN, "GUNZIP failed: $GzipError\n");
|
|
$output = $input;
|
|
};
|
|
|
|
Kamailio::AVP::add("msg", $output);
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</chapter>
|
|
|