Hello Daniel,
Thanks for the input. That clears it up.
@Ben Merrills: Glad to hear my rants are useful to other people as well
:-). Branches are indeed among the more complicated concepts in kamailio
scripting. I've always found resources that explain how things work much
more useful than "how-to/examples" approaches to documentation when it
comes to producing real-world configurations (Daniel and Ramona's kamailio
ebook is a good starting point if you're struggling with grasping the
larger picture). Maybe in part because I can't settle with something just
working the way a set of requirements expect it to unless I also understand
the why.
BR,
George
On Wed, 22 Jan 2020 at 10:35, Daniel-Constantin Mierla <miconda(a)gmail.com>
wrote:
Hello,
a new branch is created every time a request is sent out to a new
destination or resent to same destination after additional processing in a
failure route. append_branch() should not be needed, unless you want to
create more branches for parallel forking. Updating $ru or $du and doing
t_relay() in failure route should be all what is needed to send to a new
branch.
To have branch route execution, be sure you set it before t_relay(), also
in failure route, even if you set it previously in request_route for first
branch -- in other words, t_on_branch() must be used for each step of
serial forking.
The branch route block is executed inside t_relay(), so it is in the same
process that sends out the request, but in case of failure routing, further
branches are not created in the same process as the first branch. The best
is to use $xavp/$avp if you are not sure where and when those branch
processing happen.
Cheers,
Daniel
On 21.01.20 23:22, George Diamantopoulos wrote:
Hello all,
Some keyboard shortcut resulted in gmail previously sending the message
out before I had finished writing it, sorry about that. This is the
complete message.
I'm trying to accomplish the following scenario, and some questions have
arisen during testing: I'd like to be able to fork serially to a number of
downstream destinations in case of failure, but also try several hosts
which are available per destination network (via dispatcher module) before
failing over to the next one (e.g. try two gateways for provider A and if
both fail, then try two more gateways for provider B etc). I also need to
perform some network-specific handling per destination group (=provider),
which I thought I'd perform in respective branch routes. To that end, I'm
using something similar to the config pasted toward the end of the message.
Here's some points that have troubled me, if anyone can provide some
insight:
1. After exhausting dispatcher group entries for first_provider, the
request is indeed forwarded to last_provider with this configuration. I've
noticed a new branch is created. I'm assuming this happens because there's
some RURI manipulation taking place in branch_route? I recall reading
somewhere that even doing $ru = $ru will result in a new branch being
created. Is my assumption correct here, or is the new branch created for
some other reason? I mean if I did t_on_branch in a failure route following
a t_relay which failed, but without manipulating the RURI in the new
branch_route, would that still create an implicit new branch or would one
have to use append_branch() or similar in this case?
- I'm asking because several implicit or explicit branch creation
mechanisms are documented in various places (e.g. usrloc, lcr, alias_db,
corex) but it's there's no comprehensive list for reference.
2. If there are two destinations in the destination group for
first_provider, and the first one fails, then the second destination will
be tried out in tm:branch-failure:DISPATCH_FIRST_PROV_FAILOVER. Now the Via
branch parameter for this INVITE is different than the original (.1 instead
of .0), which one can verify by capturing the traffic on-net. However, in
the logs, the respective branch route is only run once, and there's no
reference to the ".1" Via, even with cfg script debugging enabled. I'm
assuming this means that kamailio's definition of "branch" in the
context
of the configuration file is different to the notion of branch as a
transaction identifier in SIP signalling in general? In simpler language,
distinct branch identifiers in Via headers between two requests does not
mean that these two requests were treated as separate branches in kamailio
config: true or false?
3. This is causing the most problems for me right now: the $vn PVs
seem to be available for the first (main?) branch, but not for subsequent
branches which are generated if the first branch fails. I was under the
impression that branch_routes are handled by the same process as the
request_route for a message, and as a consequence I was expecting private
variables to be available there. This doesn't seem to be the case with the
example configuration below. $vn(some_var) in
branch_route[LAST_PROV_BRANCH] evaluates to NULL. Any insight as to why
this happens? And if I need these vars to be available in serial forking,
is the recommended solution to use shared variables or is my approach here
problematic in other ways?
Thanks!
George
request_route {
...
$vn(some_var) = "some_value";
$vn(some_other_var) = "some_other_value";
...
$avp(provider_order) = "last_provider";
$avp(provider_order) = "first_provider";
...
t_set_fr(120000, 2000);
route(PROVIDER_SELECTION);
}
route[PROVIDER_SELECTION] {
if ( is_avp_set("$avp(provider_order)") ) {
t_on_failure("PROVIDER_SERIAL");
if ( $avp(provider_order) == "first_provider" ) {
$avp(provider_order) = $null;
route(DISPATCH_FIRST_PROV);
} else if ( $avp(provider_order) == "last_provider" ) {
$avp(provider_order) = $null;
route(DISPATCH_LAST_PROV);
}
}
}
route[DISPATCH_FIRST_PROV] {
if ( !ds_select_dst("1", "4") ) {
if ( is_avp_set("$avp(provider_order)") ) {
route(PROVIDER_SELECTION);
} else {
t_send_reply("503", "Downstream carrier unavailable");
}
}
t_on_branch_failure("DISPATCH_FIRST_PROV_FAILOVER");
t_on_branch("FIRST_PROV_BRANCH");
route(RELAY);
exit;
}
route[DISPATCH_LAST_PROV] {
//Similar to First Prov
}
event_route[tm:branch-failure:DISPATCH_FIRST_PROV_FAILOVER] {
if (t_is_canceled()) exit;
# next DST - only for 5xx or local timeout
if ( t_check_status("5[[:digit:]]+") || (t_branch_timeout() &&
!t_branch_replied()) ) {
if ( ds_next_dst() ) {
t_on_branch_failure("DISPATCH_FIRST_PROV_FAILOVER");
route(RELAY);
exit;
} else {
xlog("L_ERR", "--- SCRIPT_DISPATCH_FIRST_PROV_FAILOVER: Failed to route
request to first prov.\n");
}
}
}
event_route[tm:branch-failure:DISPATCH_LAST_PROV_FAILOVER] {
//Similar to First Prov
}
branch_route[FIRST_PROV_BRANCH] {
uac_replace_to("$vn(some_var)");
$ru = $vn(some_other_var);
}
branch_route[LAST_PROV_BRANCH] {
uac_replace_to("$vn(some_var)");
$ru = $vn(some_other_var);
}
failure_route[PROVIDER_SERIAL] {
if (t_is_canceled()) exit;
# next Provider - only for 5xx or local timeout
if ( (t_check_status("5[[:digit:]]+") || (t_branch_timeout() &&
!t_branch_replied())) && is_avp_set("$avp(provider_order)") ) {
xlog("L_NOTICE", "--- SCRIPT_PROVIDER_SERIAL: A failover provider was
selected: Forwarding to $avp(provider_order)\n");
route(PROVIDER_SELECTION);
route(RELAY);
exit;
} else if ( t_check_status("5[[:digit:]]+") || (t_branch_timeout() &&
!t_branch_replied()) ) {
xlog("L_NOTICE", "--- SCRIPT_PROVIDER_SERIAL: No more provider options,
giving up\n");
exit;
} else {
xlog("L_NOTICE", "--- SCRIPT_PROVIDER_SERIAL: Non-5xx error received,
relaying\n");
}
}
route[RELAY] {
// Mostly identical to the sample config file
}
_______________________________________________
Kamailio (SER) - Users Mailing
Listsr-users@lists.kamailio.orghttps://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
--
Daniel-Constantin Mierla --
www.asipto.comwww.twitter.com/miconda --
www.linkedin.com/in/miconda
Kamailio Advanced Training - March 9-11, 2020, Berlin -
www.asipto.com
Kamailio World Conference - April 27-29, 2020, in Berlin --
www.kamailioworld.com