<p></p>
<h3>Description</h3>
<p>I noticed an issue regarding loose_route() when using Topos module.</p>
<p>My architecture is the following:</p>
<pre><code>Client (behind NAT or not) ------>   Kamailio (Access SBC) -----------> Kamailio (Interconnect SBC) -----------> Carrier

</code></pre>
<p>Kamailio Access SBC is listening on 2 interfaces:</p>
<pre><code>Public interface : udp:A.A.A.A:5060
Core interface   : udp:B.B.B.B:5060

</code></pre>
<p>Kamailio Interconnect SBC is listening on 2 interfaces:</p>
<pre><code>Core interface           : udp:C.C.C.C:5060
Carrier-side interface   : udp:D.D.D.D:5060

</code></pre>
<p>TOPOS is configured only on second kamailio box (Interconnect SBC).<br>
Record routing is used on both kamailios.</p>
<p>TOPOS module is configured as follows:</p>
<pre><code>modparam("ndb_redis", "server", "name=srv1;addr=127.0.0.1;port=6379")
modparam("topos_redis", "serverid", "srv1")

modparam("topos", "storage", "redis")
modparam("topos", "contact_mode", 1)
modparam("topos", "cparam_name", "id")
modparam("topos", "rr_update", 1)

</code></pre>
<p>RR module is configured as follows:</p>
<pre><code>modparam("rr", "enable_full_lr", 1)
modparam("rr", "append_fromtag", 1)
modparam("rr", "enable_double_rr", 1)

</code></pre>
<p>For an incomoing INVITE (direction: client to carrier) all is fine and topos can strip headers on bleg and insert the cookie on bleg contact as a param.</p>
<p>When Callee sends a BYE or re-INVITE, topos inserts route headers in aleg as shown in the next trace: (BYE as received from the carrier on the carrier-side interface D.D.D.D)</p>
<pre><code>BYE sip:D.D.D.D:5060 SIP/2.0
Via: SIP/2.0/UDP x.x.x.x:5060;branch=z9hG4bKrdhsvc001omkvssqvfk0sd0185mt1.1
From: <sip:+33123456789@my-carrier-domain;transport=UDP;user=phone>;tag=SD69ao497-1472568650-1635329820043
To: <sip:+33987654321@my-own-domain;transport=UDP;user=phone>;tag=3ab10616
Call-ID: NjZjMDgyMGMxNzdkN2FhYmJlYzQyYjA5YWIzZThmZmI.
CSeq: 547381883 BYE
Max-Forwards: 64
Content-Length: 0
Route: <sip:D.D.D.D;r2=on;lr=on;ftag=3ab10616>,<sip:C.C.C.C;r2=on;lr=on;ftag=3ab10616>
Route: <sip:B.B.B.B;r2=on;lr=on;ftag=3ab10616;dlg_id=426.26c2>,<sip:A.A.A.A;r2=on;lr=on;ftag=3ab10616;dlg_id=426.26c2>
P-SR-XUID: atpsh-617925e5-82a5-1

</code></pre>
<p>Topos on the kamailio interconnect handles the BYE/re-INVITE and forward it to the second interface C.C.C.C as shown in the following trace:</p>
<pre><code>BYE sip:A.A.A.A;r2=on;lr=on;ftag=3ab10616;dlg_id=426.26c2 SIP/2.0
Via: SIP/2.0/UDP 185.164.213.110;branch=z9hG4bKbd7.ab692eeb60369aa3a5e07f6b63cc9dd7.0
From: <sip:+33123456789@my-carrier-domain;transport=UDP;user=phone>;tag=SD69ao497-1472568650-1635329820043
To: <sip:+33987654321@my-own-domain;transport=UDP;user=phone>;tag=3ab10616
Call-ID: NjZjMDgyMGMxNzdkN2FhYmJlYzQyYjA5YWIzZThmZmI.
CSeq: 547381883 BYE
Max-Forwards: 63
Content-Length: 0
Route: <sip:C.C.C.C;r2=on;lr=on;ftag=3ab10616>
Route: <sip:B.B.B.B;r2=on;lr=on;ftag=3ab10616;dlg_id=426.26c2>
Contact: <sip:+33123456789@10.3.60.45;id=atpsh-617925e5-82a5-1>

</code></pre>
<p>When the BYE/re-INVITE request reaches the C.C.C.C interface, it is then forwarded directly to the ruri sip:A.A.A.A.</p>
<p>Or what I expect to receive in C.C.C.C interface is the following :</p>
<pre><code>BYE <HERE SHOULD BE THE CALLER CONTACT URI> SIP/2.0
Via: SIP/2.0/UDP 80.10.231.173:5060;branch=z9hG4bKrdhsvc001omkvssqvfk0sd0185mt1.1
From: <sip:+33123456789@my-carrier-domain;transport=UDP;user=phone>;tag=SD69ao497-1472568650-1635329820043
To: <sip:+33987654321@my-own-domain;transport=UDP;user=phone>;tag=3ab10616
Call-ID: NjZjMDgyMGMxNzdkN2FhYmJlYzQyYjA5YWIzZThmZmI.
CSeq: 547381883 BYE
Max-Forwards: 64
Content-Length: 0
Route: <sip:D.D.D.D;r2=on;lr=on;ftag=3ab10616>
Route: <sip:C.C.C.C;r2=on;lr=on;ftag=3ab10616>
Route: <sip:B.B.B.B;r2=on;lr=on;ftag=3ab10616;dlg_id=426.26c2>
Route: <sip:A.A.A.A;r2=on;lr=on;ftag=3ab10616;dlg_id=426.26c2>
Contact: <sip:+33123456789@10.3.60.45;id=atpsh-617925e5-82a5-1>

</code></pre>
<p>I could work around this issue by doing the following :</p>
<ol>
<li>When receiving the BYE/re-INVITE on interface D.D.D.D, I explode the Route headers, delete old route headers and create new ones in order from the result of explode</li>
<li>I update the ru with the contact uri which I stored in a htable when the initial INVITE was received</li>
</ol>
<pre><code># Manage outgoing branches
branch_route[MANAGE_BRANCH] {
        xdbg("new branch [$T_branch_idx] to $ru\n");

        # TOPOS FIX
        if (is_method("INVITE")) {
                $sht(tpsindlg=>$ci) = $ci;
                $sht(tpsindlg=>$ci:ft) = $ft;
                $sht(tpsindlg=>$ci:ct) = $ct;
        }
}


route[WITHINDLG] {
        if (!has_totag()) return;

        # Fix bad Route Headers caused by TOPOS module
        if ($Ri == "D.D.D.D") {
                $var(rh0) = $(hdr(Route)[0]{s.select,0,,});
                $var(rh1) = $(hdr(Route)[0]{s.select,1,,});
                $var(rh2) = $(hdr(Route)[1]{s.select,0,,});
                $var(rh3) = $(hdr(Route)[1]{s.select,1,,});

                remove_hf_re("^Route$");

                append_hf("Route: $var(rh0)\r\n");
                append_hf("Route: $var(rh1)\r\n");
                append_hf("Route: $var(rh2)\r\n");
                append_hf("Route: $var(rh3)\r\n");
        }

        # sequential request within a dialog should
        # take the path determined by record-routing
        if (loose_route()) {

          # Fix R-URI caused by TOPOS module
                if ($Ri == "D.D.D.D") {
                        if ($ci == $sht(tpsindlg=>$ci) && $tt == $sht(tpsindlg=>$ci:ft)) {
                                $ru = $(sht(tpsindlg=>$ci:ct){s.strip,1}{s.striptail,1});

                                if (is_method("BYE")) {
                                        $sht(tpsindlg=>$ci) = $null;
                                        $sht(tpsindlg=>$ci:ft) = $null;
                                        $sht(tpsindlg=>$ci:ct) = $null;
                                }
                        }
                }

                route(RELAY);
                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
                        route(RELAY);
                        exit;
                } else {
                        # ACK without matching transaction ... ignore and discard
                        exit;
                }
        }

        sl_send_reply("404","Not here");
        exit;
}

</code></pre>
<p>Could you please tell if this is a normal behavior by TOPOS module or is it a bug?</p>
<p>Thank you.</p>

<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br />You are receiving this because you are subscribed to this thread.<br />Reply to this email directly, <a href="https://github.com/kamailio/kamailio/issues/2905">view it on GitHub</a>, or <a href="https://github.com/notifications/unsubscribe-auth/ABO7UZMDECRTYH35JVRQ6H3UJAHLBANCNFSM5G2NSWGA">unsubscribe</a>.<br />Triage notifications on the go with GitHub Mobile for <a href="https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675">iOS</a> or <a href="https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub">Android</a>.
<img src="https://github.com/notifications/beacon/ABO7UZP5P7TFEXJWTW55DRLUJAHLBA5CNFSM5G2NSWGKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4POWK4JQ.gif" height="1" width="1" alt="" /></p>
<script type="application/ld+json">[
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ViewAction",
"target": "https://github.com/kamailio/kamailio/issues/2905",
"url": "https://github.com/kamailio/kamailio/issues/2905",
"name": "View Issue"
},
"description": "View this Issue on GitHub",
"publisher": {
"@type": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]</script>