[SR-Users] Accounting only the 2nd branch of missed serial forked call

Daniel-Constantin Mierla miconda at gmail.com
Tue Sep 6 14:18:18 CEST 2011


Hello,

can you use t_flush_flags() after setting the accounting flag in 
falure_route? Automatic update was missing so far, reported by Alex 
Hermann as well. I just did a patch, so if you want to try it, see the 
commit:

http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c589ca35b2aa3097a3c9e2a5a050514337300c05

Actually, reporting if all goes fine with this patch, will help in 
backporting it to 3.1 branch.

Thanks,
Daniel

On 9/5/11 2:41 PM, Ozren Lapcevic wrote:
> Hi,
>
> I'm having some problems accounting missed serial forked calls to 
> mysql database.
>
> I have following setup. Each user can have up to two contacts: 
> telephone number (routed to asterisk) and SIP URI. Users can specify 
> which contact has higher priority - which one should ring first. There 
> is also SEMS voicemail which is forked as 3rd serial call leg if there 
> is no answer at first two contacts.
>
> For example, I have two users: oz at abc.hr <mailto:oz at abc.hr> and 
> pero at abc.hr <mailto:pero at abc.hr>. pero at abc.hr <mailto:pero at abc.hr> 
> also has set telephone number as alternative number if he is not 
> reachable at sip:pero at abc.hr <mailto:sip%3Apero at abc.hr>. Moreover, 
> pero at abc.hr <mailto:pero at abc.hr> has voicemail turned on. When 
> oz at abc.hr <mailto:oz at abc.hr> calls pero at abc.hr <mailto:pero at abc.hr>, 
> first pero at abc.hr <mailto:pero at abc.hr>'s SIP client rings, then if 
> there is no answer and after the timeout telephone number rings and 
> finally, if there is no answer at telephone and after the timeout 
> INVITE is forked to SEMS.
>
> There are two interesting scenarios accounting-wise which can happened:
> 1. oz at abc.hr <mailto:oz at abc.hr> calls pero at abc.hr 
> <mailto:pero at abc.hr>, there are no answers and call is forked to 
> voicemail.
> 2. oz at abc.hr <mailto:oz at abc.hr> calls pero at abc.hr 
> <mailto:pero at abc.hr>, there is no answer at SIP client, but pero 
> answers call at telephone.
>
> When scenario 1 happens, I want to have only one log (row) in 
> missed_calls table.
>
> When scenario 2 happens, I don't want to have a log in missed_calls table.
>
> To accomplish this,*I want to log only the 2nd branch of the forked 
> call. However, there is either a bug in acc module or I'm doing 
> something wrong, and I can't get Kamailio to log only the 2nd branch*. 
> I think that I am setting the FLT_ACCMISSED flag correctly - after the 
> 2nd branch is handled and prior to calling the RELAY route. Logs show 
> that FLT_ACCMISSED flag is set prior to calling t_relay(), and there 
> are no errors in debug log. I am using $ru = "something" to rewrite 
> URI prior to forking request.
>
> I can easily set up logging of every call (two missed calls for 
> serially forked call to two locations) by setting FLT_ACCMISSED flag 
> for each INVITE. I can set up logging of every call's 1st branch, by 
> reseting FLT_ACCMISSED flag when handling 2nd branch of the call. 
> Interestingly, logging of only the 2nd branch of the serial forked 
> call works when there is no forking to voicemail!
>
> Any ideas how to solve this problem?
>
> Bellow are important parts of my config file. I'm running kamailio 3.1.4.
>
> Cheers
> Ozren
>
>
> # ----- acc params -----
> /* what special events should be accounted ? */
> modparam("acc", "early_media", 0)
> modparam("acc", "report_ack", 1)
> modparam("acc", "report_cancels", 0)
> modparam("acc", "detect_direction", 0)
> /* account triggers (flags) */
> modparam("acc", "log_flag", FLT_ACC)
> modparam("acc", "log_missed_flag", FLT_ACCMISSED)
> modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
> modparam("acc", 
> "log_extra","src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
> /* enhanced DB accounting */
> #!ifdef WITH_ACCDB
> modparam("acc", "db_flag", FLT_ACC)
> modparam("acc", "db_missed_flag", FLT_ACCMISSED)
> modparam("acc", "db_url", DBURL)
> modparam("acc", "db_extra", 
> "src_user=$fU;src_domain=$fd;dst_user=$tU;dst_domain=$td;src_ip=$si")
> #!endif
>
> ...
>
>
> # Main SIP request routing logic
> # - processing of any incoming SIP request starts with this route
> route {
>
>         # per request initial checks
>         route(REQINIT);
>
>         if (src_ip != ****) {
>                 # NAT detection
>                 route(NAT);
>         }
>
>         # handle requests within SIP dialogs
>         route(WITHINDLG);
>
>         ### only initial requests (no To tag)
>
>         # CANCEL processing
>         if (is_method("CANCEL"))
>         {
>                 if (t_check_trans())
>                         t_relay();
>                 exit;
>         }
>
>         t_check_trans();
>
>         # authentication
>         route(AUTH);
>
>         # record routing for dialog forming requests (in case they are 
> routed)
>         # - remove preloaded route headers
>         remove_hf("Route");
>         if (is_method("INVITE|SUBSCRIBE"))
>                 record_route();
>
>         # account only INVITEs
>         if (is_method("INVITE"))
>         {
>                 setflag(FLT_ACC); # do accounting
>         }
>
>         # dispatch requests to foreign domains
>         route(SIPOUT);
>
>         ### requests for my local domains
>
>         # handle presence related requests
>         route(PRESENCE);
>
>         # handle registrations
>         route(REGISTRAR);
>
>         if ($rU==$null)
>         {
>                 # request with no Username in RURI
>                 sl_send_reply("484","Address Incomplete");
>                 exit;
>         }
>
>         # dispatch destinations to PSTN
>         route(PSTN);
>
>         if ( is_method("INVITE") ) {
>                 route(DBALIASES);
>                 #check for user defined forking priorities and timers
>                 route(FORK);
>         }
>
>         # user location service
>         route(LOCATION);
>
>         route(RELAY);
> }
>
>
>
> #check for user defined forking priorities and timers
> route[FORK]{
>         sql_query("con", "select * from usr_pref_custom where 
> uuid='$tu'", "pref");
>
>         $avp(uuid)=$dbr(pref=>[0,0]);
>         $avp(email)=$dbr(pref=>[0,1]);
>         $avp(prio1)=$dbr(pref=>[0,2]);
>         $avp(prio2)=$dbr(pref=>[0,3]);
>         $avp(timer1)=$dbr(pref=>[0,5]);
>         $avp(timer2)=$dbr(pref=>[0,6]);
>
>         if (strlen($avp(prio1))>5) {
>
>                 # user has multiple contacts, do serial forking
>                 setflag(FLT_USRPREF);
>
>                 # set counter
>                 if (!$avp(prio)) {
>                         $avp(prio) = 1;
>                 }
>
>                 # overwrite request URI with highest priority contact
>                 if ($avp(prio1) =~ "^sip:00") {
>                         $ru = $avp(prio1) + "@host";
>                         xlog("L_INFO","PRIO 1 is tel number, RURI set: 
> $ru");
>                 }
>                 else {
>                         $ru = $avp(prio1);
>                         xlog("L_INFO","PRIO 1 is SIP URI, RURI set: $ru");
>                 }
>         }
> }
>
>
> route[RELAY] {
> #!ifdef WITH_NAT
>         if (check_route_param("nat=yes")) {
>                 setbflag(FLB_NATB);
>         }
>         if (isflagset(FLT_NATS) || isbflagset(FLB_NATB)) {
>                 route(RTPPROXY);
>         }
> #!endif
>
>         /* example how to enable some additional event routes */
>         if (is_method("INVITE")) {
>
>                 t_on_reply("REPLY_ONE");
>                 t_on_failure("FAIL_ONE");
>
>                 #if users have priorities set, use FAIL_FORK failure route
>                 if ( isflagset(FLT_USRPREF) ) {
>                         t_on_failure("FAIL_FORK");
>                 }
>         }
>
>         if (isflagset(FLT_ACCMISSED)) xlog("L_INFO","RELAY, $rm $ru, 
> ACCMISSED FLAG IS SET");
>         else xlog("L_INFO","RELAY, $rm $ru, ACCMISSED FLAG IS NOT SET");
>         if (!t_relay()) {
>                 sl_reply_error();
>         }
>         exit;
> }
>
>
> # Handle requests within SIP dialogs
> route[WITHINDLG] {
>         if (has_totag()) {
>                 # sequential request withing a dialog should
>                 # take the path determined by record-routing
>                 if (loose_route()) {
>                         xlog("L_INFO","WITHINDLG, loose_route()");
>                         if (is_method("BYE")) {
>                                 xlog("L_INFO","WITHINDLG, BYE, DO 
> ACCOUNTING");
>                                 setflag(FLT_ACC); # do accounting ...
>                                 setflag(FLT_ACCFAILED); # ... even if 
> the transaction fails
>                         }
>                         route(RELAY);
>                 } else {
>                         if (is_method("SUBSCRIBE") && uri == myself) {
>                                 # in-dialog subscribe requests
>                                 route(PRESENCE);
>                                 exit;
>                         }
>                         if ( is_method("ACK") ) {
>                                 if ( t_check_trans() ) {
>                                         # no loose-route, but stateful 
> ACK;
>                                         # must be an ACK after a 487
>                                         # or e.g. 404 from upstream server
>                                         t_relay();
>                                         exit;
>                                 } else {
>                                         # ACK without matching 
> transaction ... ignore and discard
>                                         exit;
>                                 }
>                         }
>                         sl_send_reply("404","Not here");
>                 }
>                 exit;
>         }
> }
>
>
> # USER location service
> route[LOCATION] {
>
>   #skip if $ru is telephone number
>         if ($ru =~ "^sip:00") {
>                 xlog("L_INFO","SKIP lookup...");
>         }
>         else {
>                 if (!lookup("location")) {
>                         switch ($rc) {
>                                 case -1:
>                                 case -3:
>                                         t_newtran();
>                                         t_reply("404", "Not Found");
>                                         exit;
>                                 case -2:
>                                         sl_send_reply("405", "Method 
> Not Allowed");
>                                         exit;
>                         }
>                 }
>         }
>
>         # when routing via usrloc, log the missed calls also, but only 
> if user doesn't have prios set
>         if ( is_method("INVITE") && !(isflagset(FLT_USRPREF))) {
>                 setflag(FLT_ACCMISSED);
>         }
> }
>
>
> # Failure route for forked calls
> failure_route[FAIL_FORK] {
> #!ifdef WITH_NAT
>         if (is_method("INVITE") && (isbflagset(FLB_NATB) || 
> isflagset(FLT_NATS))) {
>                 unforce_rtp_proxy();
>         }
> #!endif
>
>         if ($avp(prio) >= 1) {
>                 $avp(prio) = $avp(prio) + 1;
>
>                 # handle 2nd branch
>                 if ( ($avp(prio) == 2) && ( isflagset(FLT_USRPREF) )) {
>                         t_on_failure("FAIL_FORK");
>
>                         if ($avp(prio2) =~ "^sip:00") {
>                                 xlog("L_INFO","FAIL FORK, PRIO 2 is 
> tel number");
>                                 $ru = $avp(prio2) + "@host";
>                         }
>                         else {
>                                 xlog("L_INFO","FAIL FORK, PRIO 2 is 
> SIP URI");
>                                 $ru = $avp(prio2);
>                                 route(LOCATION);
>                         }
>                         setflag(FLT_ACCMISSED);
>                 }
>
>                 else {
>                         $avp(prio) = 0;
>                         $ru = $(avp(uuid));
>                         rewritehostport("host:port");
>                         xlog("L_INFO","FAIL FORK, VOICEMAIL 
> email:$avp(email), ru:$ru, br: $br");
>                         append_hf("P-App-Name: voicemail\r\n");
>                         append_hf("P-App-Param: 
> Email-Address=$avp(email)\r\n");
>                 }
>                 route(RELAY);
>         }
>
>         if (t_is_canceled()) {
>                 exit;
>         }
> }
>
>
> _______________________________________________
> SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
> sr-users at lists.sip-router.org
> http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users

-- 
Daniel-Constantin Mierla -- http://www.asipto.com
Kamailio Advanced Training, Oct 10-13, Berlin: http://asipto.com/u/kat
http://linkedin.com/in/miconda -- http://twitter.com/miconda

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sip-router.org/pipermail/sr-users/attachments/20110906/72ebb775/attachment-0001.htm>


More information about the sr-users mailing list