mirror of https://github.com/sipwise/sems.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.
177 lines
6.3 KiB
177 lines
6.3 KiB
#######################################################################
|
|
#
|
|
# sw_prepaid_sip, the signalling-only prepaid engine
|
|
# Copyright (C) 2007 Sipwise GmbH
|
|
# Based on mycc, Copyright (C) 2002-2003 Fhg Fokus
|
|
#
|
|
# Author: Andreas Granig <agranig@sipwise.com>
|
|
#
|
|
########################################################################
|
|
|
|
How sw_prepaid_sip works
|
|
------------------------
|
|
|
|
The plugin extracts the headers "P-Caller-Uuid" and "P-Acc-Dest" as
|
|
caller and callee identifiers, respectively. Using these values,
|
|
it calls an accounting backend, which can defined in sw_prepaid_sip.conf,
|
|
and fetches the maximum call duration (per default, cc_acc is used as
|
|
billing backend, which is just a dummy plugin to show the most basic
|
|
concept of a billing backend).
|
|
|
|
If the credit is > 0, it uses the Request-Uri passed in the header "P-R-Uri"
|
|
and connects the callee using the outbound proxy passed in the header "P-Proxy".
|
|
|
|
When the call duration exceeds the credit, the call is terminated by SEMS.
|
|
|
|
|
|
A typical call flow would look like this, where (a) is the caller leg and
|
|
(b) the callee leg:
|
|
|
|
Caller Proxy SEMS Callee
|
|
| | | |
|
|
| INV(a) | | |
|
|
|--------->| | |
|
|
| 407(a) | | |
|
|
|<---------| | |
|
|
| INV(a) | | |
|
|
|--------->| | |
|
|
| 100(a) | | |
|
|
|<---------| | |
|
|
| | INV(a) | |
|
|
| |--------->| |
|
|
| | 101(a) | |
|
|
| |<---------| |
|
|
| | INV(b) | |
|
|
| |<---------| |
|
|
| | INV(b) | |
|
|
| |-------------------->|
|
|
| | | 180(b) |
|
|
| |<--------------------|
|
|
| | 180(b) | |
|
|
| |--------->| |
|
|
| | 180(a) | |
|
|
| |<---------| |
|
|
| 180(a) | | |
|
|
|<---------| | |
|
|
| | | 200(b) |
|
|
| |<--------------------|
|
|
| | 200(b) | |
|
|
| |--------->| |
|
|
| | 200(a) | |
|
|
| |<---------| |
|
|
| 200(a) | | |
|
|
|<---------| | |
|
|
| ACK(a) | | |
|
|
|--------->| | |
|
|
| | ACK(a) | |
|
|
| |--------->| |
|
|
| | ACK(b) | |
|
|
| |<---------| |
|
|
| | ACK(b) | |
|
|
| |-------------------->|
|
|
| | | |
|
|
| | | |
|
|
|
|
|
|
How to configure SEMS' sip proxy
|
|
--------------------------------
|
|
|
|
Modify the "tw_append" parameter of the "tm" option to pass the mandatory headers to
|
|
SEMS:
|
|
|
|
modparam("tm", "tw_append",
|
|
"prepaid_headers:hdr[P-Caller-Uuid];hdr[P-Proxy];hdr[P-R-Uri];hdr[P-Acc-Dest]")
|
|
|
|
Then add a proper block to pass prepaid calls to SEMS. In this example,
|
|
we assume that calls prefixed by "pre" are considered prepaid requests.
|
|
For ser-0.9.6 as SEMS' sip proxy, use something like:
|
|
|
|
if(uri =~ "sip:pre.+@")
|
|
{
|
|
strip(3);
|
|
if(!t_write_unix("/tmp/sems.sock","sw_prepaid_sip/prepaid_headers"))
|
|
{
|
|
xlog("L_ERR", "Error contacting SEMS - M=%rm R=%ru F=%fu T=%tu ID=%ci\n");
|
|
t_reply("500","Could not contact B2BUA server");
|
|
}
|
|
break;
|
|
}
|
|
|
|
If you need to pass other headers from leg (a) to leg (b), you can add them to "tw_append"
|
|
and they are copied to the other leg. This is for example necessary to pass the destination
|
|
URI to leg (b), which can then be extracted from the proxy and set accordingly.
|
|
|
|
How to configure a proxy to interact with sw_prepaid_sip
|
|
--------------------------------------------------------
|
|
|
|
If your proxy runs on IP 192.168.100.10:5060 and your SEMS' proxy on 192.168.100.10:5070, you
|
|
can pass leg (a) to the prepaid engine like this (assuming you use OpenSER >= 1.2.0 as
|
|
sip proxy):
|
|
|
|
if(/* caller is prepaid */)
|
|
{
|
|
/* use authentication user as caller uuid in prepaid engine */
|
|
append_hf("P-Caller-Uuid: $au\r\n");
|
|
|
|
/* use simplified R-URI as destination pattern in prepaid engine;
|
|
NOTE that cc_acc doesn't evaluate this field, but more
|
|
advanced backends might do, so sw_prepaid_sip requires
|
|
this header */
|
|
append_hf("P-Acc-Dest: $rU@$rd\r\n");
|
|
|
|
/* the URI which is to be used by SEMS as outbound proxy for
|
|
call leg (b) - use our own here */
|
|
append_hf("P-Proxy: sip:192.168.100.10:5060\r\n");
|
|
|
|
/* the R-URI to be used to connect call leg (b) */
|
|
append_hf("P-R-Uri: $ru\r\n");
|
|
|
|
if($du != null)
|
|
{
|
|
/* if there's a D-Uri set, also send it to SEMS to correctly contact
|
|
call leg (b). NOTE you have to add this header in SEMS's sip proxy
|
|
config as "tw_append" value. */
|
|
append_hf("P-D-Uri: $du\r\n");
|
|
}
|
|
|
|
/* point the R-Uri to SEMS' proxy and relay; this is just the most simple
|
|
example, but you can also use the LCR module for SEMS load balancing
|
|
and failover. */
|
|
rewriteuri("sip:192.168.100.10:5070");
|
|
t_relay();
|
|
}
|
|
|
|
In the above block, call leg (a) is passed to SEMS. Now we prepare a block to catch
|
|
call leg (b) coming from SEMS. Add this at the very beginning of your proxy configuration.
|
|
|
|
/* usual sanity checks like msg-size and max-fwd, then do something like: */
|
|
|
|
if(src_ip == 192.168.100.10 && src_port == 5070 /* check if from SEMS */
|
|
&& uri =~ ";sw_prepaid" /* this uri param is added by SEMS to detect prepaid calls */
|
|
&& method == "INVITE" && !has_totag()) /* only process initial invites here */
|
|
{
|
|
/* recover the R-Uri (maybe check for existence first!) */
|
|
$ru = $hdr(P-R-Uri);
|
|
|
|
/* recover destination Uri */
|
|
if(is_present_hf("P-D-Uri"))
|
|
{
|
|
$du = $hdr(P-D-Uri);
|
|
insert_hf("Route: <$hdr(P-D-Uri)>\r\n");
|
|
}
|
|
|
|
/* you might also consider removing the helper headers
|
|
by calling remove_hf(...) */
|
|
|
|
/* relay to callee */
|
|
t_relay();
|
|
}
|
|
|
|
Please note that the above example is a very basic one. For example, if you want to route
|
|
to PSTN gateways, you might want to add an informational header in leg (a) and evaluate
|
|
it in leg (b) to load a set of PSTN gateways instead of relaying to the R-Uri.
|
|
|
|
IMPORTANT: make sure to prevent black-hats from spoofing the SEMS proxy address to place
|
|
unauthenticated calls by using a private address for SEMS' sip proxy and by adding
|
|
proper firewall rules on your ingress router.
|