### Description
I noticed an issue regarding loose_route() when using Topos module.
My architecture is the following:
``` Client (behind NAT or not) ------> Kamailio (Access SBC) -----------> Kamailio (Interconnect SBC) -----------> Carrier
```
Kamailio Access SBC is listening on 2 interfaces:
``` Public interface : udp:A.A.A.A:5060 Core interface : udp:B.B.B.B:5060
```
Kamailio Interconnect SBC is listening on 2 interfaces:
``` Core interface : udp:C.C.C.C:5060 Carrier-side interface : udp:D.D.D.D:5060
```
TOPOS is configured only on second kamailio box (Interconnect SBC). Record routing is used on both kamailios.
TOPOS module is configured as follows:
``` 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)
```
RR module is configured as follows:
``` modparam("rr", "enable_full_lr", 1) modparam("rr", "append_fromtag", 1) modparam("rr", "enable_double_rr", 1)
```
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.
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)
``` 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
```
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:
``` 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
```
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.
Or what I expect to receive in C.C.C.C interface is the following :
``` 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
```
I could work around this issue by doing the following :
1. 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 2. I update the ru with the contact uri which I stored in a htable when the initial INVITE was received
``` # 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; }
```
Could you please tell if this is a normal behavior by TOPOS module or is it a bug?
Thank you.