<div dir="ltr"><div>Hello all,</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>Here's some points that have troubled me, if anyone can provide some insight:</div><div></div><div><ol><li>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?</li><ul><li>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.<br></li></ul><li>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?<br></li><li>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?</li></ol><div>Thanks!</div><div>George<br></div></div><div><br></div><div><span style="font-family:monospace">request_route {</span></div><div style="margin-left:40px"><span style="font-family:monospace">...</span></div><div style="margin-left:40px"><span style="font-family:monospace">$vn(some_var) = "some_value";</span></div><div style="margin-left:40px"><span style="font-family:monospace">$vn(some_other_var) = "some_other_value";</span></div><div style="margin-left:40px"><span style="font-family:monospace">...</span></div><div style="margin-left:40px"><span style="font-family:monospace">$avp(provider_order) = "last_provider";</span></div><div style="margin-left:40px"><span style="font-family:monospace">$avp(provider_order) = "first_provider";</span></div><div style="margin-left:40px"><span style="font-family:monospace">...</span></div><div style="margin-left:40px"><span style="font-family:monospace">t_set_fr(120000, 2000);</span></div><div style="margin-left:40px"><span style="font-family:monospace">route(PROVIDER_SELECTION);</span></div><div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">route[PROVIDER_SELECTION] {</span></div><div style="margin-left:40px"><span style="font-family:monospace">if ( is_avp_set("$avp(provider_order)") ) {</span></div><div style="margin-left:80px"><span style="font-family:monospace">t_on_failure("PROVIDER_SERIAL");</span></div><div style="margin-left:80px"><span style="font-family:monospace">if ( $avp(provider_order) == "first_provider" ) {</span></div><div style="margin-left:120px"><span style="font-family:monospace">$avp(provider_order) = $null;</span></div><div style="margin-left:120px"><span style="font-family:monospace">route(DISPATCH_FIRST_PROV);</span></div><div style="margin-left:80px"><span style="font-family:monospace">} else if ( $avp(provider_order) == "last_provider" ) {</span></div><div><div style="margin-left:120px"><span style="font-family:monospace">$avp(provider_order) = $null;</span></div><div style="margin-left:120px"><span style="font-family:monospace">route(DISPATCH_LAST_PROV);</span></div><div style="margin-left:80px"><span style="font-family:monospace">}<br></span></div><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div><div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">route[DISPATCH_FIRST_PROV] {<br></span><div style="margin-left:40px"><span style="font-family:monospace">if ( !ds_select_dst("1", "4") ) {<br></span></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">if ( is_avp_set("$avp(provider_order)") ) {<br></span></div></div><div style="margin-left:40px"><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">route(PROVIDER_SELECTION);<br></span></div></div></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">} else {<br></span></div></div><div style="margin-left:40px"><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">t_send_reply("503", "Downstream carrier unavailable");<br></span></div></div></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div></div><div style="margin-left:40px"><span style="font-family:monospace">}<br><br>t_on_branch_failure("DISPATCH_FIRST_PROV_FAILOVER");<br>t_on_branch("FIRST_PROV_BRANCH");<br><br>route(RELAY);<br>exit;<br></span></div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">route[DISPATCH_LAST_PROV] {<br></span><div style="margin-left:40px"><span style="font-family:monospace">//Similar to First Prov</span></div><span style="font-family:monospace">}</span></div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">event_route[tm:branch-failure:DISPATCH_FIRST_PROV_FAILOVER] {<br></span><div style="margin-left:40px"><span style="font-family:monospace">if (t_is_canceled()) exit;<br><br># next DST - only for 5xx or local timeout<br>if ( t_check_status("5[[:digit:]]+") || (t_branch_timeout() && !t_branch_replied()) ) {<br></span></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">if ( ds_next_dst() ) {<br></span></div></div><div style="margin-left:40px"><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">t_on_branch_failure("DISPATCH_FIRST_PROV_FAILOVER");<br>route(RELAY);<br>exit;<br></span></div></div></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">} else {<br></span></div></div><div style="margin-left:40px"><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">xlog("L_ERR", "--- SCRIPT_DISPATCH_FIRST_PROV_FAILOVER: Failed to route request to first prov.\n");<br></span></div></div></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div><span style="font-family:monospace">}<br></span></div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><div><span style="font-family:monospace">event_route[tm:branch-failure:DISPATCH_LAST_PROV_FAILOVER] {</span></div></div><div><div style="margin-left:40px"><span style="font-family:monospace">//Similar to First Prov</span></div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">branch_route[FIRST_PROV_BRANCH] {<br></span><div style="margin-left:40px"><span style="font-family:monospace">uac_replace_to("$vn(some_var)");<br></span></div></div><div style="margin-left:40px"><span style="font-family:monospace">$ru = $vn(some_other_var);</span></div><div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">branch_route[LAST_PROV_BRANCH] {</span></div><div><div><div style="margin-left:40px"><span style="font-family:monospace">uac_replace_to("$vn(some_var)");<br></span></div></div><div style="margin-left:40px"><span style="font-family:monospace">$ru = $vn(some_other_var);</span><span style="font-family:monospace"></span></div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">failure_route[PROVIDER_SERIAL] {<br></span><div style="margin-left:40px"><span style="font-family:monospace">if (t_is_canceled()) exit;<br><br># next Provider - only for 5xx or local timeout<br>if ( (t_check_status("5[[:digit:]]+") || (t_branch_timeout() && !t_branch_replied())) && is_avp_set("$avp(provider_order)") ) {<br></span></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">xlog("L_NOTICE", "--- SCRIPT_PROVIDER_SERIAL: A failover provider was selected: Forwarding to $avp(provider_order)\n");<br>route(PROVIDER_SELECTION);<br>route(RELAY);<br>exit;<br></span></div></div><div style="margin-left:40px"><span style="font-family:monospace">} else if ( t_check_status("5[[:digit:]]+") || (t_branch_timeout() && !t_branch_replied()) ) {<br></span></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">xlog("L_NOTICE", "--- SCRIPT_PROVIDER_SERIAL: No more provider options, giving up\n");</span></div></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">exit;<br></span></div></div><div style="margin-left:40px"><span style="font-family:monospace">} else {<br></span></div><div style="margin-left:40px"><div style="margin-left:40px"><span style="font-family:monospace">xlog("L_NOTICE", "--- SCRIPT_PROVIDER_SERIAL: Non-5xx error received, relaying\n");<br></span></div></div><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div><span style="font-family:monospace">}</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">route[RELAY] {</span></div><div style="margin-left:40px"><span style="font-family:monospace">// Mostly identical to the sample config file</span></div><span style="font-family:monospace">}<br></span><div><div><span style="font-family:monospace"><br></span></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"></div>
</blockquote></div></div></div>