[SR-Users] [sr-dev] recursive calls to failure_route strange behavior

Andres Moya andres.moya.i at gmail.com
Fri Nov 20 23:07:02 CET 2009


Hmmm...

Thank you very much for support

I use 
subst('/^From:(.*)sip:[^@]*@[a-zA-Z0-9\.]+(.*)$/From:\1sip:$avp(i:21)@$avp(i:24)\2/i');

now replace work strange i can see first time it said correct to:
From: <sip:andres.moya4 at sipdiscount.com;transport=UDP>;tag=19790648.
for both - first INVITE and second with auth header

Second time i am sending to provider:
From: 
<sip:andres.moya4 at sipdiscount.com;transport=UDP>;tag=19790648.From: 
<sip:21100036838 at terrasip.net;transport=UDP>;tag=19790648.
and then with auth header:
From: <sip:andres.moya4 at sipdiscount.com;transport=UDP>;tag=19790648.

something is wrong again :( 

You can see i used flags to split first  subst call from second one.
Second time it is not doing  substitution, it is adding to From header 
:) But then looks like uac_auth removes one :)

I don't care to restore From field, i need it just work.

uac_replace_from do nothing then caller in failure_route via sub route 
second time. maybe it set From for first branch?

I want it go on list of providers and authenticate then asked.

I have branch_route, i tried to arm t_on_branch , but xlog in this route 
never write anything in log. I don't know how to use branches. I just 
know that if i want to call t_relay(), i should always say - 
append_branch() ;) Any one can explain briefly how branches supposed to 
work? Especially how to use branch_route. I feel i am nearly there. I 
guess author of auc module can maybe be interested to add loading of 
authentication data from database.

my number is sip:andres.moya at riki.ru (not email), anyone welcome to 
call... testing



ok my logic is

if (number PSTN)  {
route (PSTN_RELAY);
}

route[PSTN_RELAY]{

do first stage cr_route.....

route(LOAD_AUTH);

t_relay();

}

#####  LOAD_AUTH ##########
# loading authentication information from carrierauth table
# set From field according to carrierauth information
# arguments:
# $rd - request uri doamin, sip provider carrier
# returns:
# avp(i:20) - rewrited host = $rd
# avp(i:21) - auth user
# avp(i:22) - auth pass
# avp(i:23) - auth realm
# avp(i:24) - auth domain

route[LOAD_AUTH]{
    xlog ("L_INFO","LOAD_AUTH: searching authentication for host host: 
$rd");
    $avp(i:20)=$rd;

    if ( avp_db_query(
        "SELECT username, password, realm, domain FROM carrierauth WHERE 
hostname='$rd'",
        "$avp(i:21);$avp(i:22);$avp(i:23);$avp(i:24)") > 0 ) {
        xlog ("L_INFO","LOAD_AUTH: for $rd loaded data user: $avp(i:21) 
pass: $avp(i:22) realm: $avp(i:23) domain: $avp(i:24)");

        # replace from_user at from_domain
        xlog("L_INFO","LOAD_AUTH: changing From: -> 
sip:$avp(i:21)@$avp(i:24)");

        #uac_replace_from("sip:$avp(i:21)@$avp(i:24)");
        #uac_replace_from  doesnt work in failure route.
        if (!isflagset(30)) {
        
subst('/^From:(.*)sip:[^@]*@[a-zA-Z0-9\.]+(.*)$/From:\1sip:$avp(i:21)@$avp(i:24)\2/i');
        } else {
        
subst('/^From:(.*)sip:[^@]*@[a-zA-Z0-9\.]+(.*)$/From:\1sip:$avp(i:21)@$avp(i:24)\2/i');    
   
        }
        setflag(30);
    }

    # we are not relaying authentications :)
    remove_hf("Authorization"); # remove client authentication

    # reset flag to mark no authentication yet performed
    resetflag(10); # let's use 10 to know uac authentication was not 
sent yet

    xlog("L_INFO","LOAD_AUTH: flag 10 reset and Authorization header 
clered. returning\n");

    return(1);

}

failure_route[FAIL_ONE] {
xlog("L_INFO","entering failure route with code: $T_reply_code \n");
#if (t_grep_status("415")) xlog("L_INFO","415! \n");

    if ( t_check_status("401|407") ) # Unathorised reply
    { xlog("L_INFO","Authentication required \n");
        # have we already tried to authenticate? do we have auth 
information loaded?
        if (isflagset(10) || $avp(i:21)==$null ) # auth was already sent 
or we don't have auth info
        {
            xlog("Authentication to $avp(i:20) provider as 
$avp(i:21)@$avp(i:24) failed\n");
            t_reply("503","Authentication failed");
            avp_delete("$avp(i:20)");
            avp_delete("$avp(i:21)");
            avp_delete("$avp(i:22)");
            avp_delete("$avp(i:23)");
            avp_delete("$avp(i:24)");
            exit(); # :(

        }

        # if call from here LOAD_AUTH will look for original uri, not 
rewriten before
        if( !is_avp_set("$avp(i:20)") || $avp(i:20)=='') { # if 
LAOD_AUTH was not done yet
            route (LOAD_AUTH); # loads auth avps and rewrite 'from' field
        }

        # this avps loaded before by LOAD_AUTH
        # avp(i:20) - rewrited host
        # avp(i:21) - auth user
        # avp(i:22) - auth pass
        # avp(i:23) - auth realm
        # avp(i:24) - auth domain

xlog ("L_INFO","for $rd using: $avp(i:21) pass: $avp(i:22) realm: 
$avp(i:23) domain: $avp(i:24)");

        remove_hf("Authorization"); # remove client authentication
        if (uac_auth()) # adding auth header
        {xlog ("\nMessage:\n$mb\n\n");
            xlog("L_INFO","Authorization header set, sending...\n");
            # mark that auth was performed
            setflag(10);

            # next time i want t_check_status look at some other errstatus
            t_drop_replies();

            t_on_failure("FAIL_ONE");
            # repeat the request with auth response this time
            append_branch(); # ???
            t_relay();

            exit;
        }
    }

    # In case of failure on PSTN provider, send it to an alternative route:
#    if ( t_check_status("415|480|408|5[0-9][0-9]")) {
    if ( isflagset(11) && t_check_status("415|480|408|5[0-9][0-9]")) {

        # next time i want t_check_status look at some other errstatus
        t_drop_replies();

        xlog("L_INFO", "FAIL_ONE: got code $T_reply_code will try next 
carrier domain\n");
        revert_uri();
        if (!cr_next_domain("$avp(s:carrier)", "$avp(s:domain)", 
"$avp(s:rc_pstn_num)",
                "$avp(s:rc_host)", "$T_reply_code", "$avp(s:domain)")) {
            xlog("L_ERR", "cr_next_domain failed\n");
            exit;
        }
        if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", 
"$avp(s:rc_pstn_num)", "$avp(s:rc_pstn_num)",
                "call_id")) {
            xlog("L_ERR", "cr_route failed\n");
            exit;
        }

        route(LOAD_AUTH);

        xlog("L_INFO", "FAIL_ONE: done LOAD_AUTH, relaying to next 
provider: $rd\n");
        t_on_failure("FAIL_ONE");
        append_branch();
        if (!t_relay()) {
            xlog("L_ERR", "t_relay to $rd failed\n");
            exit;
        }
    exit;

    }

#!ifdef WITH_NAT
    if (is_method("INVITE")
            && (isbflagset("6") || isflagset(5))) {
        unforce_rtp_proxy();
    }
#!endif

    if (t_is_canceled()) {
        exit;
    }


t_reply("404","Not found");

}



Miklos Tirpak wrote:
> [please keep the list CC-d because others may also be interested in 
> the solution or may know the answer better.]
>
> On 11/20/2009 07:06 PM, Andres Moya wrote:
>> Can i ask one more question here. It is complicated, i am using 
>> uac_replace_from and uac_auth.
>> I am using failure route to process authentication if necessary and 
>> redirect on next carrier.
>>
>> If i authenticated with one provider, then fot let say 415 ( i set 
>> only speex in UAC to get it ;) ). Ok SER send request to second 
>> provider, i use
>> uac_replace_from once again in my LOAD_AUTH route
>> then uac_auth again.
>>
>> Ok. now i see from ngrep that uac_replace_from did nothing in from 
>> field and use user at domain for first provider, authentication failed :(
>
> Which authentication fails? The first or the second one?
> The first should work, at least the from header should be rewritten by 
> the function.
>
> The second authentication will not work this way (if it requires a 
> different from header) because the proxy "remembers" for the header 
> changes done before the first t_relay() function call and applies the 
> same header modifications also for any other branch added from failure 
> route. Hence, the outgoing SIP request to the second provider will 
> contain the same from HF as the request to the first provider.
>
> The easiest way is to apply the header modifications in branch route 
> if you do not need to reuse them later from failure route. 
> Modifications done in branch routes are valid only within that branch.
>
>>
>> I moved uac_replace_from to my failure route to call once again 
>> before uac_auth, but got config error as i can't use uac_replace_from 
>> in failure_route.
>
> I think you already use this function from failure route because it is 
> in a route block that is included from failure route. The only 
> difference is that the syntax checker does not recognize the issue. I 
> am not familiar with uac_replace_from() but after having a quick look 
> at the function I think it is safe to use it from here.
>
>> Ok i will use textops to rewrite, but it is ugly? 
>
> The main difference is that uac_replace_from() restores the original 
> From HF when the response if forwarded. If you use textops module then 
> you need to restore the header manually.
>
>> no. Maybe i should call uac_replace_from in branch route?
>
> I would suggest this way. Both for the first and for the second provider.
>
> Miklos
>
>>
>> Thanks




More information about the sr-users mailing list