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.
353 lines
12 KiB
353 lines
12 KiB
Call Control Module
|
|
|
|
Dan Pascu
|
|
|
|
<dan@ag-projects.com>
|
|
|
|
Edited by
|
|
|
|
Dan Pascu
|
|
|
|
<dan@ag-projects.com>
|
|
|
|
Copyright © 2005-2008 Dan Pascu
|
|
__________________________________________________________________
|
|
|
|
Table of Contents
|
|
|
|
1. Admin Guide
|
|
|
|
1. Overview
|
|
2. Description
|
|
3. Features
|
|
4. Dependencies
|
|
|
|
4.1. Kamailio Modules
|
|
4.2. External Libraries or Applications
|
|
|
|
5. Exported parameters
|
|
|
|
5.1. disable (int)
|
|
5.2. socket_name (string)
|
|
5.3. socket_timeout (int)
|
|
5.4. signaling_ip_avp (string)
|
|
5.5. canonical_uri_avp (string)
|
|
5.6. diverter_avp_id (string)
|
|
|
|
6. Functions
|
|
|
|
6.1. call_control()
|
|
|
|
List of Examples
|
|
|
|
1.1. Setting the disable parameter
|
|
1.2. Setting the socket_name parameter
|
|
1.3. Setting the socket_timeout parameter
|
|
1.4. Setting the signaling_ip_avp parameter
|
|
1.5. Setting the canonical_uri_avp parameter
|
|
1.6. Setting the diverter_avp_id parameter
|
|
1.7. Using the call_control function
|
|
|
|
Chapter 1. Admin Guide
|
|
|
|
Table of Contents
|
|
|
|
1. Overview
|
|
2. Description
|
|
3. Features
|
|
4. Dependencies
|
|
|
|
4.1. Kamailio Modules
|
|
4.2. External Libraries or Applications
|
|
|
|
5. Exported parameters
|
|
|
|
5.1. disable (int)
|
|
5.2. socket_name (string)
|
|
5.3. socket_timeout (int)
|
|
5.4. signaling_ip_avp (string)
|
|
5.5. canonical_uri_avp (string)
|
|
5.6. diverter_avp_id (string)
|
|
|
|
6. Functions
|
|
|
|
6.1. call_control()
|
|
|
|
1. Overview
|
|
|
|
This module allows one to limit the duration of calls and automatically
|
|
end them when they exceed the imposed limit. Its main use case is to
|
|
implement a prepaid system, but it can also be used to impose a global
|
|
limit on all calls processed by the proxy.
|
|
|
|
2. Description
|
|
|
|
Callcontrol consists of 3 components:
|
|
* The Kamailio call_control module
|
|
* An external application called callcontrol which keeps track of the
|
|
calls that have a time limit and automatically ends them when they
|
|
exceed it. This application receives requests from Kamailio and
|
|
makes requests to a rating engine (see below) to find out if a call
|
|
needs to be limited or not. When a call ends (or is ended) it will
|
|
also instruct the rating engine to debit the balance for the caller
|
|
with the consumed amount. The callcontrol application is available
|
|
from http://callcontrol.ag-projects.com/
|
|
* A rating engine that is used to calculate the time limit based on
|
|
the caller's credit and the destination price and to debit the
|
|
caller's balance after a call ends. This is available as part of
|
|
CDRTool from http://cdrtool.ag-projects.com/
|
|
|
|
The callcontrol application runs on the same machine as Kamailio and
|
|
they communicate over a filesystem socket, while the rating engine can
|
|
run on a different host and communicates with the callcontrol
|
|
application using a TCP connection.
|
|
|
|
Callcontrol is invoked by calling the call_control() function for the
|
|
initial INVITE of every call we want to apply a limit to. This will end
|
|
up as a request to the callcontrol application, which will interogate
|
|
the rating engine for a time limit for the given caller and
|
|
destination. The rating engine will determine if the destination has
|
|
any associated cost and if the caller has any credit limit and if so
|
|
will return the amount of time he is allowed to call that destination.
|
|
Otherwise it will indicate that there is no limit associated with the
|
|
call. If there is a limit, the callcontrol application will retain the
|
|
session and attach a timer to it that will expire after the given time
|
|
causing it to call back to Kamailio with a request to end the dialog.
|
|
If the rating engine returns that there is no limit for the call, the
|
|
session is discarded by the callcontrol application and it will allow
|
|
it to go proceed any limit. An appropriate response is returned to the
|
|
call_control module that is then returned by the call_control()
|
|
function call and allows the script to make a decision based on the
|
|
answer.
|
|
|
|
3. Features
|
|
|
|
* Very simple API consisting of a single function that needs to be
|
|
called once for the first INVITE of every call. The rest is done
|
|
automatically in the background using dialog callbacks.
|
|
* Gracefully end dialogs when they exceed their time by triggering a
|
|
dlg_end_dlg request into the dialog module, that will generate two
|
|
BYE messages towards each endpoint, ending the call cleanly.
|
|
* Allow parallel sessions using one balance per subscriber
|
|
* Integrates with mediaproxy's ability to detect when a call does
|
|
timeout sending media and is closed. In this case the dlg_end_dlg
|
|
that is triggered by mediaproxy will end the callcontrol session
|
|
before it reaches the limit and consumes all the credit for a call
|
|
that died and didn't actually take place. For this mediaproxy has
|
|
to be used and it has to be started by engage_media_proxy() to be
|
|
able to keep track of the call's dialog and end it on timeout.
|
|
Even when mediaproxy is unable to end the dialog because it was not
|
|
started with engage_media_proxy(), the callcantrol application is
|
|
still able to detect calls that did timeout sending media, by
|
|
looking in the radius accounting records for entries recorded by
|
|
mediaproxy for calls that did timeout. These calls will also be
|
|
ended gracefully by the callcontrol application itself.
|
|
|
|
4. Dependencies
|
|
|
|
4.1. Kamailio Modules
|
|
4.2. External Libraries or Applications
|
|
|
|
4.1. Kamailio Modules
|
|
|
|
The following modules must be loaded before this module:
|
|
* pv module
|
|
* dialog module
|
|
|
|
4.2. External Libraries or Applications
|
|
|
|
The following libraries or applications must be installed before
|
|
running Kamailio with this module loaded:
|
|
* None.
|
|
|
|
5. Exported parameters
|
|
|
|
5.1. disable (int)
|
|
5.2. socket_name (string)
|
|
5.3. socket_timeout (int)
|
|
5.4. signaling_ip_avp (string)
|
|
5.5. canonical_uri_avp (string)
|
|
5.6. diverter_avp_id (string)
|
|
|
|
5.1. disable (int)
|
|
|
|
Boolean flag that specifies if callcontrol should be disabled. This is
|
|
useful when you want to use the same Kamailio configuration in two
|
|
different contexts, one using callcontrol, the other not. In the case
|
|
callcontrol is disabled, calls to the call_control() function will
|
|
return a code indicating that there is no limit associated with the
|
|
call, allowing the use of the same configuration without changes.
|
|
|
|
Default value is “0”.
|
|
|
|
Example 1.1. Setting the disable parameter
|
|
...
|
|
modparam("call_control", "disable", 1)
|
|
...
|
|
|
|
5.2. socket_name (string)
|
|
|
|
The path to the filesystem socket where the callcontrol application
|
|
listens for commands from the module.
|
|
|
|
Default value is “/var/run/callcontrol/socket”.
|
|
|
|
Example 1.2. Setting the socket_name parameter
|
|
...
|
|
modparam("call_control", "socket_name", "/var/run/callcontrol/socket")
|
|
...
|
|
|
|
5.3. socket_timeout (int)
|
|
|
|
How long time (in milliseconds) to wait for an answer from the
|
|
callcontrol application.
|
|
|
|
Default value is “500” ms.
|
|
|
|
Example 1.3. Setting the socket_timeout parameter
|
|
...
|
|
modparam("call_control", "socket_timeout", 500)
|
|
...
|
|
|
|
5.4. signaling_ip_avp (string)
|
|
|
|
Specification of the AVP which holds the IP address from where the SIP
|
|
signaling originated. If this AVP is set it will be used to get the
|
|
signaling IP address, else the source IP address from where the SIP
|
|
message was received will be used. This AVP is meant to be used in
|
|
cases where there are more than one proxy in the call setup path and
|
|
the proxy that actually starts callcontrol doesn't receive the SIP
|
|
messages directly from the UA and it cannot determine the NAT IP
|
|
address from where the signaling originated. In such a case attaching a
|
|
SIP header at the first proxy and then copying that header's value into
|
|
the signaling_ip_avp on the proxy that starts callcontrol will allow it
|
|
to get the correct NAT IP address from where the SIP signaling
|
|
originated.
|
|
|
|
This is used by the rating engine which finds the rates to apply to a
|
|
call based on caller's SIP URI, caller's SIP domain or caller's IP
|
|
address (whichever yields a rate forst, in this order).
|
|
|
|
Default value is “$avp(s:signaling_ip)”.
|
|
|
|
Example 1.4. Setting the signaling_ip_avp parameter
|
|
...
|
|
modparam("call_control", "signaling_ip_avp", "$avp(s:signaling_ip)")
|
|
...
|
|
|
|
5.5. canonical_uri_avp (string)
|
|
|
|
Specification of the AVP which holds an optional application defined
|
|
canonical request URI. When this is set, it will be used as the
|
|
destination when computing the call price, otherwise the request URI
|
|
will be used. This is useful when the username of the ruri needs to
|
|
have a different, canonical form in the rating engine computation than
|
|
it has in the ruri.
|
|
|
|
Default value is “$avp(s:can_uri)”.
|
|
|
|
Example 1.5. Setting the canonical_uri_avp parameter
|
|
...
|
|
modparam("call_control", "canonical_uri_avp", "$avp(s:can_uri)")
|
|
...
|
|
|
|
5.6. diverter_avp_id (string)
|
|
|
|
Specification of the id of an integer AVP which holds an optional
|
|
application defined diverter SIP URI. When this is set, it will be used
|
|
by the rating engine as the billing party when finding the rates to
|
|
apply to a given call, otherwise, the caller's URI taken from the From
|
|
field will be used. When set, this AVP should contain a value in the
|
|
form “user@domain” (no sip: prefix should be used).
|
|
|
|
This is useful when a destination diverts a call, thus becoming the new
|
|
caller. In this case the billing party is the diverter and this AVP
|
|
should be set to it, to allow the rating engine to pick the right rates
|
|
for the call. For example, if A calls B and B diverts all its calls
|
|
unconditionally to C, then the diverter AVP should the set to B's URI,
|
|
because B is the billing party in the call not A after the call was
|
|
diverted.
|
|
|
|
Default value is “805”.
|
|
|
|
Example 1.6. Setting the diverter_avp_id parameter
|
|
...
|
|
modparam("call_control", "diverter_avp_id", 805)
|
|
|
|
route {
|
|
...
|
|
# alice@example.com is paying for this call
|
|
$avp(i:805) = "sip:alice@example.com";
|
|
...
|
|
}
|
|
...
|
|
|
|
6. Functions
|
|
|
|
6.1. call_control()
|
|
|
|
6.1. call_control()
|
|
|
|
Trigger the use of callcontrol for the dialog started by the INVITE for
|
|
which this function is called (the function should only be called for
|
|
the first INVITE of a call). Further in-dialog requests will be
|
|
processed automatically using internal bindings into the dialog state
|
|
machine, allowing callcontrol to update its internal state as the
|
|
dialog progresses, without any other intervention from the script.
|
|
|
|
This function should be called right before the message is sent out
|
|
using t_relay(), when all the request uri modifications are over and a
|
|
final destination has been determined.
|
|
|
|
This function has the following return codes:
|
|
|
|
* +2 - call has no limit
|
|
* +1 - call has limit and is traced by callcontrol
|
|
* -1 - not enough credit to make the call
|
|
* -2 - call is locked by another call in progress
|
|
* -5 - internal error (message parsing, communication, ...)
|
|
|
|
This function can be used from REQUEST_ROUTE.
|
|
|
|
Example 1.7. Using the call_control function
|
|
...
|
|
if (is_avp_set("$avp(i:805)")) {
|
|
# the diverter AVP is set, use it as billing party
|
|
$avp(s:billing_party_domain) = $(avp(i:805){uri.domain});
|
|
} else {
|
|
$avp(s:billing_party_domain) = $fd;
|
|
}
|
|
|
|
if (method==INVITE && !has_totag() &&
|
|
is_domain_local("$avp(s:billing_party_domain)")) {
|
|
call_control();
|
|
switch ($retcode) {
|
|
case 2:
|
|
# Call with no limit
|
|
case 1:
|
|
# Call has limit and is under callcontrol management
|
|
break;
|
|
case -1:
|
|
# Not enough credit (prepaid call)
|
|
sl_send_reply("402", "Not enough credit");
|
|
exit;
|
|
break;
|
|
case -2:
|
|
# Locked by another call in progress (prepaid call)
|
|
sl_send_reply("403", "Call locked by another call in progress");
|
|
exit;
|
|
break;
|
|
default:
|
|
# Internal error (message parsing, communication, ...)
|
|
if (PREPAID_ACCOUNT) {
|
|
xlog("Call control: internal server error\n");
|
|
sl_send_reply("500", "Internal server error");
|
|
exit;
|
|
} else {
|
|
xlog("L_WARN", "Cannot set time limit for postpaid call\n");
|
|
}
|
|
}
|
|
}
|
|
t_relay();
|
|
...
|