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 List
sr-users(a)lists.kamailio.org
https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
--
Daniel-Constantin Mierla --
www.asipto.com
www.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