Hi Andrew
well, the RURI
of remote ACK has proxy IP address 10.200.70.100 so proxy
thinks that previous hop was a strict router.
Aha, that makes sense. But why would that make Kamailio apply strict routing?
Now I understand this! Kamailio is not copying the *next* Route URI
into the R-URI because it is strict routing itself, but copying the
*last* Route URI into the R-URI because it thinks the previous hop is
a strict router. The fact that the next Route URI is the last one is
what confused me. Thanks for helping me get to the bottom of it!
Interestingly the previous hop is not really a strict router, it's
just badly behaved in that it takes the user part of the R-URI from
the Contact header and the domain part from the next hop. I won't name
the vendor but I am very surprised by this. I can only assume it's
some type of NAT traversal that is tuned on.
W.r.t. the Kamailio's strict routing behaviour, I wanted to point
something out. Here's the relevant bit from the RFC:
The proxy MUST inspect the Request-URI of the request. If the
Request-URI of the request contains a value this proxy previously
placed into a Record-Route header field (see Section 16.6 item 4),
the proxy MUST replace the Request-URI in the request with the last
value from the Route header field, and remove that value from the
Route header field.
So what is meant here by "a value"? In my case this R-URI has the same
IP as the proxy but contains a user part and parameters which were not
inserted by the proxy into a Record-Route header so I don't think this
test should pass, but because is_myself() is being used in
loose_route() it does.
I can't
think of any
workaround that would not be an ugly hack at the moment, though.
I thought encode_contact() and decode() contact were designed exactly
for this? Except I can't get them to work so I believe you!
The main issue with these is that loose_route() and decode_contact()
do not play nicely together. Ideally you would want to call
decode_contact() and then loose_route() which could look $ru /
new_uri, but it will only ever inspect $ou /parsed_uri. So you can't
put decode_contact() before loose_route().
Then on the other hand decode_contact() will only read from $ou if $ru
is not set, and because loos_route() sets $ru in after_strict(), you
also can't put decode_contact() after loose_route().
Unless you reset some of what loose_route() set, which is what I did
get this working:
if (loose_route()) {
if($ou =~ "^sip:natted_contact") {
$ru = $ou;
decode_contact();
$du = $ru;
$fs = $null;
}
...
}
What would be really useful would be if loose_route() used new_uri
where available or, to preserve backward compatibility, you could call
loose_route($ru).
Richard