<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hello,</p>
    <p>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.</p>
    <p>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.</p>
    <p>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.</p>
    <p>Cheers,<br>
      Daniel<br>
    </p>
    <div class="moz-cite-prefix">On 21.01.20 23:22, George
      Diamantopoulos wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAPcKEYO5oJyAZYAnLX4Gctga=mwQ-Gv6z9URp9VAeX1bf9kExg@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <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>
          <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">
            </blockquote>
          </div>
        </div>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
Kamailio (SER) - Users Mailing List
<a class="moz-txt-link-abbreviated" href="mailto:sr-users@lists.kamailio.org">sr-users@lists.kamailio.org</a>
<a class="moz-txt-link-freetext" href="https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users">https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users</a>
</pre>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Daniel-Constantin Mierla -- <a class="moz-txt-link-abbreviated" href="http://www.asipto.com">www.asipto.com</a>
<a class="moz-txt-link-abbreviated" href="http://www.twitter.com/miconda">www.twitter.com/miconda</a> -- <a class="moz-txt-link-abbreviated" href="http://www.linkedin.com/in/miconda">www.linkedin.com/in/miconda</a>
Kamailio Advanced Training - March 9-11, 2020, Berlin - <a class="moz-txt-link-abbreviated" href="http://www.asipto.com">www.asipto.com</a>
Kamailio World Conference - April 27-29, 2020, in Berlin -- <a class="moz-txt-link-abbreviated" href="http://www.kamailioworld.com">www.kamailioworld.com</a></pre>
  </body>
</html>