Hi all
Is there a way to skip a branch in branch route?
Situation: Two registrar server with DMQ synced location database.
CPE register via TCP or TLS. To properly work, message have to be sent over the existing TCP connection.
Multiple CPE register to one AOR.
CPE1 and CPE2 register to Registrar 1 CPE3 registers to Registrar 2
On Registrar 1 there is an established TCP connection to CPE1 and CPE2 but not to CPE3.
Within the Branch Route to the CPE I can check if there is a TCP as the Branch Route is executed for every contact in that AOR:
branch_route[BR_TO_CPE] { [...] $var(reg_contact_addr) = $(ulc(aor=>addr)[$T_branch_idx]{uri.host}); $var(socket) = $(ulc(aor=>socket)[$T_branch_idx]); if ($var(socket) == 0) { xlog("L_ERROR", "$cfg(route): No Socket for: $var(reg_contact_addr)"); } [...] }
This log an error if the socket is not present on the local registrar. But is there a way to tell kamailio to skip/discard that contact?
My intention is to parallel branch from the core to both registrars, that way all contacts would still get the call but via established TCP socket (and in case of UDP and NAT via correct know ip for ALG port-forwarding).
Hi
https://www.kamailio.org/wiki/cookbooks/devel/pseudovariables#branch_name_-_...
Assigning $null to uri attribute will drop the branch, for the rest of attributes will just set the value to null.
I fear this does not work within branch_route
if ($var(socket) == 0) { if ($avp(debug) > 0) { xlog("L_INFO", "$cfg(route): $(branch(uri)[$T_branch_idx]) via Socket: $var(socket) is NOT LOCAL to this Registrar - dropping!\n"); } $(branch(uri)[$T_branch_idx]) = $null; }
Result:
* Call is still branched to CPE * $(branch(uri)[$T_branch_idx]) is null on all subsequent branches after the first one.
You also can filter it in the request route and not create branch wich doesn't belong this server ( you can achieve that by verifying ucl variable details), or making it UDP branch being forwarded to proper server which handles the particular connection.
On Fri, 8 Sept 2023, 11:29 Benoît Panizzon, benoit.panizzon@imp.ch wrote:
Hi
https://www.kamailio.org/wiki/cookbooks/devel/pseudovariables#branch_name_-_...
Assigning $null to uri attribute will drop the branch, for the rest of attributes will just set the value to null.
I fear this does not work within branch_route
if ($var(socket) == 0) { if ($avp(debug) > 0) { xlog("L_INFO", "$cfg(route):
$(branch(uri)[$T_branch_idx]) via Socket: $var(socket) is NOT LOCAL to this Registrar - dropping!\n"); } $(branch(uri)[$T_branch_idx]) = $null; }
Result:
- Call is still branched to CPE
- $(branch(uri)[$T_branch_idx]) is null on all subsequent branches after
the first one.
-- Mit freundlichen Grüssen
-Benoît Panizzon- @ HomeOffice und normal erreichbar
I m p r o W a r e A G - Leiter Commerce Kunden ______________________________________________________
Zurlindenstrasse 29 Tel +41 61 826 93 00 CH-4133 Pratteln Fax +41 61 826 93 01 Schweiz Web http://www.imp.ch ______________________________________________________ __________________________________________________________ Kamailio - Users Mailing List - Non Commercial Discussions To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender! Edit mailing list options or unsubscribe:
Hi Yuriy
You also can filter it in the request route and not create branch wich doesn't belong this server ( you can achieve that by verifying ucl variable details), or making it UDP branch being forwarded to proper server which handles the particular connection.
I have started trying to solve this in request route.
I'm still truggling on how to distinguish local and non local registrations.
I have 4 CPE registered to the same AOR.
kamclt ul show [AOR] does show they are registered. 3 on the local registrar (with a socket) and one with socket [not set].
If I repeat on the other registrar I get matching information. One with a socket, the other three are [not set].
So trying to understand the hard way, what happens:
$var(i)=0; while($var(i)<=$branch(count)) { $var(socket) = $(ulc(aor=>socket)[$var(i)]); xlog("L_INFO", "$cfg(route): DEBUG BEFORE: IDX: $var(i) TOTAL: $branch(count) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); $var(i) = $var(i) + 1; }
$var(i)=0; while($var(i)<=$branch(count)) { $var(socket) = $(ulc(aor=>socket)[$var(i)]); xlog("L_INFO", "$cfg(route): DEBUG REMOVE: IDX: $var(i) TOTAL: $branch(count) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); if ($var(socket) == 0) { xlog("L_INFO", "$cfg(route): Dropping Branch IDX $var(i) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); $(branch(uri)[$var(i)]) = $null; } else { $var(i) = $var(i) + 1; # do NOT increment index as the branches got renumbered. } }
$var(i)=0; while($var(i)<=$branch(count)) { $var(socket) = $(ulc(aor=>socket)[$var(i)]); xlog("L_INFO", "$cfg(route): DEBUG AFTER: IDX: $var(i) TOTAL: $branch(count) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); $var(i) = $var(i) + 1; }
What I did not yet understand.
$branch(count) is 3 !
So, does kamailio only consider the 3 registrations WITH a socket? Or is this the index starting with 0, thus 4 contacts?
When I do $(branch(uri)[$var(i)]) = $null; then $branch(count) is decremented. I suppose because the next contact takes that index, this is why I do NOT increment $var(i).
But I then get no $(branch(uri)[$var(i)]) on the highest index, suggesting that I only see 3 contacts, not all 4 of them.
Indeed, my 'BEFORE' loop did not output the contact registered on the other registrar.
So WHY is there still the INVITE being sent to the fourth, non local contact?
=> Confused!
Main request is the first branch. So consider changed $ru after lookup as the first (0) branch. Other branches will be appended as addition.
On Fri, 8 Sept 2023, 14:03 Benoît Panizzon, benoit.panizzon@imp.ch wrote:
Hi Yuriy
You also can filter it in the request route and not create branch wich doesn't belong this server ( you can achieve that by verifying ucl variable details), or making it UDP branch being forwarded to proper server which handles the particular connection.
I have started trying to solve this in request route.
I'm still truggling on how to distinguish local and non local registrations.
I have 4 CPE registered to the same AOR.
kamclt ul show [AOR] does show they are registered. 3 on the local registrar (with a socket) and one with socket [not set].
If I repeat on the other registrar I get matching information. One with a socket, the other three are [not set].
So trying to understand the hard way, what happens:
$var(i)=0; while($var(i)<=$branch(count)) { $var(socket) = $(ulc(aor=>socket)[$var(i)]); xlog("L_INFO", "$cfg(route): DEBUG BEFORE: IDX: $var(i)
TOTAL: $branch(count) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); $var(i) = $var(i) + 1; }
$var(i)=0; while($var(i)<=$branch(count)) { $var(socket) = $(ulc(aor=>socket)[$var(i)]); xlog("L_INFO", "$cfg(route): DEBUG REMOVE: IDX: $var(i)
TOTAL: $branch(count) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); if ($var(socket) == 0) { xlog("L_INFO", "$cfg(route): Dropping Branch IDX $var(i) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); $(branch(uri)[$var(i)]) = $null; } else { $var(i) = $var(i) + 1; # do NOT increment index as the branches got renumbered. } }
$var(i)=0; while($var(i)<=$branch(count)) { $var(socket) = $(ulc(aor=>socket)[$var(i)]); xlog("L_INFO", "$cfg(route): DEBUG AFTER: IDX: $var(i)
TOTAL: $branch(count) URI: $(branch(uri)[$var(i)]) Socket: $var(socket)\n"); $var(i) = $var(i) + 1; }
What I did not yet understand.
$branch(count) is 3 !
So, does kamailio only consider the 3 registrations WITH a socket? Or is this the index starting with 0, thus 4 contacts?
When I do $(branch(uri)[$var(i)]) = $null; then $branch(count) is decremented. I suppose because the next contact takes that index, this is why I do NOT increment $var(i).
But I then get no $(branch(uri)[$var(i)]) on the highest index, suggesting that I only see 3 contacts, not all 4 of them.
Indeed, my 'BEFORE' loop did not output the contact registered on the other registrar.
So WHY is there still the INVITE being sent to the fourth, non local contact?
=> Confused!
-- Mit freundlichen Grüssen
-Benoît Panizzon- @ HomeOffice und normal erreichbar
I m p r o W a r e A G - Leiter Commerce Kunden ______________________________________________________
Zurlindenstrasse 29 Tel +41 61 826 93 00 CH-4133 Pratteln Fax +41 61 826 93 01 Schweiz Web http://www.imp.ch ______________________________________________________
Hi Yuriy
Main request is the first branch. So consider changed $ru after lookup as the first (0) branch. Other branches will be appended as addition.
Not sure if I understood that correctly...
while in request route... the four URI of the branches are:
$branch(uri) $(branch(uri)[0]) $(branch(uri)[1]) $(branch(uri)[2])
and $branch(count) is 3 because there are 3 'additional' branches?
How do I geht the sockets of those four branches?
$branch(uri) => $(ulc(aor=>socket)[0]) $(branch(uri)[0]) => $(ulc(aor=>socket)[1])
and so on? Indexes offset by 1?
And, what happens if I set:
$branch(uri) = $null will $(branch(uri)[0]) become $branch(uri) and eveything shift one index down?
$branch(uri) $(branch(uri)[0])
Nah, just tested, both contain the same branch...
I discovered $branch(send_socket)...
Still not understanding, why I clearly have 4 contacts registerd on the AOR but only finding 3 of them when looping through the branches but when route(RELAY) is called, all 4 get traffic.
In your case, I would use https://www.kamailio.org/docs/modules/5.6.x/modules/registrar#registrar.f.re... See example: https://www.kamailio.org/docs/modules/5.6.x/modules/registrar#idm871
You can iterate over it Then for the first entry, you can set $ru and $du variables and it will become the main branch For the other do append_branch and set parameters of the branch[-1] accordingly. So you can control branch creation instead of automatically doing it by Kamailio and filter all needed.
Hi Yuriy
Then for the first entry, you can set $ru and $du variables and it will become the main branch For the other do append_branch and set parameters of the branch[-1] accordingly. So you can control branch creation instead of automatically doing it by Kamailio and filter all needed.
Thank you, I think you pointed me in the right direction.
So going to replace:
if (lookup("location", "$var(lookupuri)")) {
by
if (reg_fetch_contacts("location", "$var(lookupuri)", "aor")) {
Then iterate the contacts and only add the ones having a socket set.
Hi Yuriy
This looks promising. I was able to set $ru and then add branches to only send the calls from the registrar with a valid socket.
But I fear: append_branch($(ulc(aor=>addr)[$var(i)])) is not correct in NAT situation.
aor=>received is probably the one to use, but does not contain the username part. And also I probably lost that full NAT automation.
I also observed that the sending socket is not preserved. In my case I have to tcp sockets: 8080 where I run the xhttp api, not used for sip, and 5060. The outgoing call originates from 8080. So it is definitely not reusing the existing TCP connection.
Do I have to set $fs? But how do I set this only for a specific branch? Assume I have multiple contacts, some using TCP other UDP or TLS.
The branch RURI is quite clear I suppose but For the NAT solving you should pass received set into $(branch(dst_uri)[-1]) or $du for main brach Send socket also can be set via $(branch(send_socket)[-1]) or $fs respectively.
TCP can create new transactions, as UA can wait for incoming requests on different ports, which is announced in the Contact Header, However, you may try to use the tcp_keepalive_enable() and tcp_set_alias() functions when a TCP connection is established to mediate over it if UA supports this way of interaction.
пт, 8 сент. 2023 г. в 17:32, Benoît Panizzon benoit.panizzon@imp.ch:
Hi Yuriy
This looks promising. I was able to set $ru and then add branches to only send the calls from the registrar with a valid socket.
But I fear: append_branch($(ulc(aor=>addr)[$var(i)])) is not correct in NAT situation.
aor=>received is probably the one to use, but does not contain the username part. And also I probably lost that full NAT automation.
I also observed that the sending socket is not preserved. In my case I have to tcp sockets: 8080 where I run the xhttp api, not used for sip, and 5060. The outgoing call originates from 8080. So it is definitely not reusing the existing TCP connection.
Do I have to set $fs? But how do I set this only for a specific branch? Assume I have multiple contacts, some using TCP other UDP or TLS.
-- Mit freundlichen Grüssen
-Benoît Panizzon- @ HomeOffice und normal erreichbar
I m p r o W a r e A G - Leiter Commerce Kunden ______________________________________________________
Zurlindenstrasse 29 Tel +41 61 826 93 00 CH-4133 Pratteln Fax +41 61 826 93 01 Schweiz Web http://www.imp.ch ______________________________________________________
Hi Yuriy
I fear I still need some help
What I am doing now is:
if(reg_fetch_contacts("location", "$var(lookupuri)", "aor")) { t_newtran(); xlog("L_INFO","$cfg(route): Existing registration contacts count: $(ulc(aor=>count))\n"); $var(i) = 0; # Location Contact Index $var(c) = 0; # Valid Contact count while($var(i) < $(ulc(aor=>count))) { xlog("L_INFO","$cfg(route): $var(i): Contact-Address: $(ulc(aor=>addr)[$var(i)]) Socket: $(ulc(aor=>socket)[$var(i)]) RU: $ru\n"); if ($(ulc(aor=>socket)[$var(i)]) == 0) { xlog("L_INFO","$cfg(route): $var(i): NO SOCKET\n"); } else { if ($var(c) == 0) { $ru = $(ulc(aor=>addr)[$var(i)]); $du = $(ulc(aor=>received)[$var(i)]); # NAT $fs = $(ulc(aor=>socket)[$var(i)]); $var(c) = $var(c) + 1; } else { append_branch($(ulc(aor=>addr)[$var(i)])); $(branch(uri)[-1]) = $(ulc(aor=>received)[$var(i)]); # NAT? $(branch(send_socket)[-1]) = $(ulc(aor=>socket)[$var(i)]); $var(c) = $var(c) + 1; } } $var(i) = $var(i) + 1; } if ($var(c) == 0) { xlog("L_INFO","$cfg(route): We have $var(c) local contacts! Reject\n"); send_reply("480", "Not local contact found"); exit; } xlog("L_INFO","$cfg(route): We have $var(c) local contacts!\n"); } else { xlog("L_INFO","$cfg(route): We have contact at all!\n"); send_reply("480", "No registered"); exit; } t_on_branch("BR_TO_CPE"); t_on_failure("LOCATION_MANAGE_FAILURE"); route(RELAY); exit;
When I look at the trace:
R-URI contains the user@ip:port from the location record. So each device different. But all requests are sent to only one device! (probably $du as set on the first match)
branch_route[BR_TO_CPE] { if ($avp(debug) > 0) { xlog("L_INFO", "$cfg(route): BR_idx: $T_branch_idx $avp(from_in) => $avp(destination) (Contact: $rU)\n"); } $var(useragent) = $(ulc(aor=>user_agent)[$T_branch_idx]); $var(reg_contact_addr) = $(ulc(aor=>addr)[$T_branch_idx]{uri.host}); $var(socket) = $(ulc(aor=>socket)[$T_branch_idx]); if ($avp(debug) > 1) { xlog("L_INFO", "$cfg(route): $(branch(uri)[$T_branch_idx]) via socket: $var(socket)\n"); } }
On $T_branch_idx == 0 everything looks fine.
R-URI is correct, INVITE is sent to correct distination ip and port previsouly set.
On $T_branch_idx == 1 things stuff is wrong.
$(branch(uri)[$T_branch_idx]) returns <null>
R-URI contains the received URI without Username (which is what I set above) But the request is sent to the same ip and destination as branch 0.
So I guess I mixed up $du and received.
Does $branch(dst_uri) correspond to $du?
Mit freundlichen Grüssen
-Benoît Panizzon-
$(branch(dst_uri)[-1]) = $(ulc(aor=>received)[$var(i)]);
seems to be correct.
Mit freundlichen Grüssen
-Benoît Panizzon-