New in v3.0.0
Release of 3.0.0: January 11, 2010
IMPORTANT: Source code for Kamailio 3.0 is hosted on GIT repository at http://sip-router.org
IMPORTANT: SVN trunk on SourceForge.net is updated only for branches 1.5 or lower.
Being far from a complete listing of the new features, this page tries to give a fair overview of astonishing number of new functionalities and improvements available in Kamailio (OpenSER) 3.0.0.
This is first release based on http://sip-router.org project, meaning that you can have all Kamailio (OpenSER) and SIP Express Router (SER) extensions and functionalities mixed in same configuration file.
!!! New in core
Transport layer
UDP
mili-second base retransmission
integration with internal
DNS cache system and auto black-listing
fallback to TCP, TLS or SCTP if the UDP packet is too big
management of UDP cfg parameters at runtime via RPC control interface
Example config to fallback to TCP is size of SIP request is bigger than 1024 bytes:
udp_mtu = 1024
udp_mtu_try_proto = TCP
TCP
asynchronous TCP sending
many new parameters to tune TCP connection behaviour
TCP keepalive support
TCP CRLF ping support
support many pooling methods: none, poll, epoll_lt, epoll_et, sigio_rt, select, kqueue, /dev/poll
TCP file descriptions cache - speed improvement in TCP sending
management of TCP cfg parameters at runtime via RPC control interface
$sercmd> core.tcp_options
{
connect_timeout: 10
send_timeout: 10
connection_lifetime: 120
max_connections(soft): 2048
no_connect: 0
fd_cache: 1
async: 1
connect_wait: 1
conn_wq_max: 32768
wq_max: 10485760
defer_accept: 0
delayed_ack: 1
syncnt: 0
linger2: 0
keepalive: 1
keepidle: 0
keepintvl: 0
keepcnt: 0
crlf_ping: 1
accept_aliases: 0
alias_flags: 1
new_conn_alias_flags: 2
}
TLS
completely new TLS architecture
TLS hooks in core and functionality provided by TLS module
no more re-compilation of all sources to enable TLS, just load tls module
dedicated config file to deal easily within multi-homed environment
management of TLS cfg parameters at runtime via RPC control interface
Sample config file for TLS:
[server:default]
method = TLSv1
verify_certificate = no
require_certificate = no
private_key = kamailio_key.pem
certificate = kamailio_cert.pem
ca_list = kamailio_ca.pem
[client:default]
verify_certificate = yes
require_certificate = yes
[server:10.0.0.10:5061]
method = SSLv23
verify_certificate = yes
require_certificate = no
private_key = privatenet_key.pem
certificate = privatenet_cert.pem
verify_depth = 3
ca_list = privatenet_ca.pem
[client:10.0.0.11:5061]
verify_certificate = no
certificate = peer_11_client.pem
private_key = peer_11_key.pem
ca_list = peer_11_ca.pem
SCTP
completely new SCTP architecture
advancced SCTP implementation
multi-homing and multi-streaming (connections association)
macros for sctp statistics
blacklist support at the sctp level. If sctp_send_retries are used, the blacklist will work only for send (using SCTP_SEND_FAILED notifications). If sctp_send_retries is not used (default), there are 2 possible blacklist reasons: SEND or CONNECT (assoc. failed to be opened).
connection reuse & connection tracking
management of SCTP cfg parameters at runtime via RPC control interface
$sercmd core.sctp_info
{
opened_connections: 4
tracked_connections: 0
total_connections: 40010
}
$ sercmd core.sctp_options
{
sctp_socket_rcvbuf: 54784
sctp_socket_sndbuf: 54784
sctp_autoclose: 180
sctp_send_ttl: 32000
sctp_send_retries: 0
sctp_srto_initial: 3000
sctp_srto_max: 60000
sctp_srto_min: 1000
sctp_asocmaxrxt: 10
sctp_init_max_attempts: 8
sctp_init_max_timeo: 60000
sctp_hbinterval: 30000
sctp_pathmaxrxt: 5
sctp_sack_delay: 200
sctp_sack_freq: 0
sctp_max_burst: 4
}
Memory manager
new Doug Lea (DL) malloc manager
new lockless malloc (LL) manager
print memory status summary in debug mode
Locking and synchronisation
Timers
3 level hierarchical timing wheel
G. Varghese, T. Lauck, Hashed and Hierarchical Timing Wheels: Efficient Data Structures for Implementing a Timer Facility, 1996
support for dynamic adding timers
one shot and periodic timers
“fast” and “slow” timers
DNS
Select framework
new system of config variables
over one hundred classes of selects
fine access to attributes of header by header index and attributes name (e.g., Via, Auth headers)
access to SIP message parts and environment attributes
supported by Pseudo-Variables framework via PV module
if(@cseg.method == "INVITE")
{
...
}
if($sel(cseg.method) == "INVITE")
{
...
}
Library framework
internal library support – better modularity and less code duplication – shared code among several module can be organised now as a library
DB interface became libsrdb1 library
new (alternative) DB interface via libsrdb2 library with support for prepared statements
Management Interface (MI) became libmi library
several Kamailio 1.5 core extensions are now in libkcore library - slimmer core
libraries are located in “lib/”
ensure smaller footprint to core - the core is less exposed to bugs and no longer under the threat of becoming fat
RPC Interface
CFG framework
ability to get and set global or module parameters values at runtime
get and set internal variables on-the-fly
can be controlled via RPC interface
eliminate Kamailio restarts whenever possible
CFG Include support
include_file "name_of_file"
can be used in any part of config file, for example:
you can include a file defining global parameters
you can include a file defining module loading and its parameter
you can include a file defining routing rules
error reporting prints name of file and line number
included file may include another file
Example:
- file kamailio-sanity.cfg:
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if ( msg:len >= 8192 ) {
sl_send_reply("513", "Message too big");
exit;
}
if ( is_method("NOTIFY") && uri==myself
&& $hdr(Event) =~ "keep-alive" )
{
sl_send_reply("200", "OK - keepalive");
exit;
}
Now, at the top of main route block in each config, I include the 'kamailio-sanity.cfg' file:
- file kamailio.cfg:
...
route {
include_file "kamailio-sanity.cfg"
...
}
...
CFG Define support
Control in C-style what parts of the config file are executed. The parts in non-defined zones are not loaded, ensuring lower memory usage and faster execution.
Available directives:
#!define NAME - define a keyword
#!ifdef NAME - check if a keyword is defined
#!ifndef - check if a keyword is not defined
#!else - swtich to false branch of ifdef/ifndef region
#!endif - end ifdef/ifndef region
Among benefits:
easy way to enable/disable features (e.g., see default cfg for 3.0.0 – controlling support of nat traversal, presence, etc…)
switch control for parts where conditional statements were not possible (e.g., global parameters, module settings)
faster by not using conditional statements inside routing blocks when switching between running environments
Example: how to make config to be used in two environments, say testbed and production, controlled just by one define to switch between the two modes:
...
#!define TESTBED_MODE
#!ifdef TESTBED_MODE
debug=5
log_stderror=yes
listen=192.168.1.1
#!else
debug=2
log_stderror=no
listen=10.0.0.1
#!endif
...
#!ifdef TESTBED_MODE
modparam("acc|auth_db|usrloc", "db_url",
"mysql://openser:openserrw@localhost/openser_testbed")
#!else
modparam("acc|auth_db|usrloc", "db_url",
"mysql://openser:openserrw@10.0.0.2/openser_production")
#!endif
...
#!ifdef TESTBED_MODE
route[DEBUG] {
xlog("SCRIPT: SIP $rm from: $fu to: $ru - srcip: $si"\n);
}
#!endif
...
route {
#!ifdef TESTBED_MODE
route(DEBUG);
#!endif
...
}
...
onsend_route
executed just before sending the SIP message to the network
shows the final content (headers and body updated)
more flexibility in handling
DNS blacklists and filters
you can drop requestss just to be sent using own logic in onsend_route
details of destination are available and can be used in route via
cfg keywords
snd_ip
snd_port
snd_proto
snd_af
pseudo-variables
$snd(ip)
$snd(port)
$snd(proto)
$snd(af)
you can access the content of the buffer to be sent to network via:
onsend_route {
if(isflagset(2) && $snd(ip)=="10.10.10.10") {
drop;
}
}
event_route
framework exported by core to execute a set of actions when a specific event happens
no longer needed to extend cfg file grammar for each new type of event that needs to execute a route block in cfg
an event route can be triggered by core or any of the modules
implemented event routes
event_route[htable:mod-init] - executed by htable module after module has been initialised
event_route[tm:local-request] - executed by tm modules when a local SIP request is generated (former local_route in 1.5.x)
event_route[htable:mod-init] {
$shv(start_time) = $Tf;
sql_query("insert into restarts (start_time) values ('$Tf')");
}
Names for route blocks and flags
...
flags
FLAG_ONE : 1,
FLAG_TWO : 2;
...
route {
...
if($rU=~"^\+[1-9][0-9]+$")
{
# route to gateway
$du = "sip:10.0.0.11";
route(RELAY);
}
...
if(isflagset(FLAG_ONE))
{
...
}
...
}
route[RELAY] {
t_relay();
exit;
}
switch statement
support for regular expression matching for string
optimisation for integer matching
break can be used inside actions of a case block (previously was allowed only at the end of block)
switch($rU) {
case /"^123":
if($fU=="345") {
break;
} else {
...
}
break;
case /"^456":
...
break;
}
while statement
$var(i) = 0;
while($var(i)<10) {
if($var(i)==5 && $rU=="123")
break;
$var(i) = $var(i) + 1;
}
</code>
Config file interpreter
type casts operators
(int) - cast to integer
(str) - cast to string
$var(expires) = (int)$hdr(expires);
new comparison operators
eq, ne for string comparisons
ieq, ine for integer comparisons
if($ua eq "Snom") {
...
}
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 optimisations.
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).
try 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 !=.
int(undef)==0, int("")==0, int("123")==123, int("abc")==0
str(undef)=="", str(123)=="123".
new script operators
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 length of expr evaluated as string.
strempty(expr) - returns true if expr evaluates to the empty string (equivalent to expr==“”)
if (defined $v && !strempty($v))
$len=strlen($v);
Module search path
loadpath (alias to mpath) can take now a list of directories separated by ':'
modules can be located in many directories
you can omit the extension “.so” in module name for loadmodule
the list is searched in-order
loadpath "/usr/local/lib/kamailio/modules:/usr/local/lib/kamailio/modules_k"
loadmodule "db_mysql.so"
loadmodule "uri"
Dual module interfaces
modules can implement any of the interfaces specific so far to:
core can deal at the same time with modules implementing different interfaces
straightforward migration and run on the same Kamailio instance of modules developed so far for:
Kamailio (OpenSER)
SIP Express Router (SER)
OpenIMSCore
Script compatibility mode
option to offer best compatibility with expected behaviour had by older versions
as now we integrate functionalities from Kamailio and SER all together, this directive offer the possibility to choose between. For example:
in Kamailio, processing of failure route uses selected reply code from branches of the last step of serial forking
in SER, processing of failure route uses selected reply code from all branches, offering the option to drop replies for branches of the last step of serial forking via a module function
you can choose between ser compatible, kamailio compatible and max compatibility (compatible with both as much as possible), using:
#!SER
#!KAMAILIO
#!OPENSER
#!ALL
#!MAXCOMPAT
where #!KAMAILIO is equivalent with #!OPENSER and #!ALL with #!MAXCOMPAT
IMPORTANT - set #!KAMAILIO as first line in your config file if you update from 1.5.x or older version of Kamailio (OpenSER), otherwise you may experience new behaviour for some old functions.
#!KAMAILIO
...
extended avps
XAVP
new class of variables
structure-like access to variables bind to SIP transactions
ability to store more value types, not only integer and string
simplify addressing by using only string name for attributes
possibility to optimise the search by creating lists of xavp lists
availability in config file for xavp with string or integer value (expression interpreter supports only these values) via PV module
availability in stateful processing, during the lifetime of transaction
$xavp(sf=>uri)="sip:10.10.10.10";
$xavp(sf[0]=>fr_timer)=10;
$xavp(sf[0]=>fr_inv_timer)=15;
$xavp(sf[0]=>headers)="X-CustomerID: 1234\r\n";
$xavp(sf=>uri)="sip:10.10.10.11";
$xavp(sf[0]=>fr_timer)=20;
$xavp(sf[0]=>fr_inv_timer)=35;
$xavp(sf=>uri)="sip:10.10.10.12";
$xavp(sf[0]=>fr_timer)=10;
$xavp(sf[0]=>fr_inv_timer)=15;
$xavp(sf[0]=>headers)="X-CustomerID: pw45\r\n";
xlog("uri attribute in first sf xavp: $xavp(sf=>uri)\n");
New cfg file elements
lot of new parameters, functions and keywords
allow fine tuning of transport layers, real-time timers, dns, a.s.o.
visit:
Custom cfg file parameters
Format: group.id = value 'desc' description
...
pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address"
...
route[PSTN] {
# check if PSTN GW IP is defined
if (strempty($sel(cfg_get.pstn.gw_ip))) {
xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n");
return;
}
# route to PSTN dialed numbers starting with '+' or '00'
if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
return;
# only local users allowed to call
if(from_uri!=myself) {
sl_send_reply("403", "Not Allowed");
exit;
}
$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);
route(RELAY);
exit;
}
!!! New modules
auth identity
call_control
cfg_db
Load core and module parameters from database
automate the configuration by having the values in database, even for global parameters
-
cfg_rpc
ctl
drouting
iptrtpproxy
kex
memcached
hash table access for the popular memcached server
get/set integer or string values from/to memcached server
atomic increment or decrement integer values from memcached server
key can be static string or dynamic value build from other config variables
set expire time for memcached values
operations are done via pseudo-variables, therefore memcached values can be used by other modules, can be printed via xlog, a.s.o.
mi_rpc
pdb
tmx
topoh
topology hiding module
mask callid, via, route, record-route and contact headers
protect your infrastructure topology
hide the addresses of one party in the call from the other
transparent for config file writer
config always access the message in clear, so nothing special has to be done when using the module
no need to execute special functions in the config, topoh does his job in pre and post config hooks
independent of statless/stateful mode
packets can be routed via different servers configured in the same way
restarting the server does not affect ongoing calls (e.g., BYE are encoded/decoded properly)
-
xmlrpc
XMLRPC connector for RPC interface
offers high-scalability XMLRPC communication with SIP server
reuses the transport layer from the core
communication can be done therefore via TCP or TLS
all TCP/TLS SIP processing workers can handle XMLRPC, therefore the server can process lot of XMLRPC traffic at same time
access to XMLRPC packets in a dedicated route of the config file
-
#...
modparam("xmlrpc", "route", "XMLRPC");
#...
route[XMLRPC]{
# allow XMLRPC requests only on TLS and only if the client
# certificate is valid
if (proto!=TLS){
xmlrpc_reply("400", "xmlrpc allowed only over TLS");
return;
}
if (@tls.peer.verified!=""){
xmlrpc_reply("400", "Unauthorized");
return;
}
if (search("^User-Agent:.*xmlrpclib"))
set_reply_close();
set_reply_no_connect(); # optional
dispatch_rpc();
}
!!! New in old modules
carrierroute
htable
ability to count items matching name by a regular expression
ability to count items matching value by a regular expression
execute event_route[htable:mod-init] if it is defined, after module has been initialised
dump content of a hash table via MI control interface
dump content of a hash table via RPC control interface
/* print number of items in htable 'a' */
xlog("htable a has $shtcn(a= >.*) items\n");
imc
...
modparam("imc", "extra_hdrs", "P-Hint: imc\r\n")
...
lcr
msilo
nathelper
presence_xml
new PV class: $xml(…)
get input from static string or variables (e.g., body of SIP message)
can handle many XML documents at the same time
easier routing decisions based on XML content
$xml(x=>doc) = '<?xml version="1.0" encoding="UTF-8"?><proxy><name>Kamailio</name></proxy>';
xlog("content of node b: $xml(x=>xpath:/proxy/name/text())\n");
$xml(x=>xpath:/proxy/name) = "Kamailio 3.0.0";
pv
registrar
seas
textops
tm
module was overhauled
faster and more lightweight timer implementations for retransmissions
removed lot of locking by a better design
more internal hooks to develop applications on top of module
asynchronous message processing support
option to decide what replies to drop in serial forking steps
load of new functions to access transactions
new parameters to tune transaction management
-
usrloc
utils
userblacklist
sercmd
command line application (similar to Asterisk cli)
connection or one-command mode
tab completion
execute RPC commands
execute MI commands
connect to Kamailio via FIFO, unix file sockets, UDP or TCP - you have to load the new ctl module
siremis
web2.0 admin interface (mysql, php, apache)
added support for XMLRPC communication with Kamailio server
-
External Links
Project resources:
A series of blog posts highlighting the best of new in Kamailio (OpenSER) 3.0.0: