[Serusers] Need CANCEL before failure_route called on branch timeout...

Phil D'Amore ptdamore at yahoo.com
Thu Jan 26 19:54:30 CET 2006


Hi all...

Sorry this is a bit long, but this problem is driving me nuts...

I have a problem where I need to try a sequence of numbers on the PSTN, where
the one is tried if the previous one fails or times out.  My problem is
handling the timeout (408) case:

1.  First INVITE sent to PSTN gw
2.  final response timer fires, fake 408 generated
3.  failure_route in scripts called, new branch created, next INVITE sent to
PSTN gw
4.  CANCEL is sent (I realize this is not sync'd to step 3 but it typically
happens this way that that causes my problem)
5.  PSTN GW sends 482 Loop Detected back to me for the *second* branch created
in 3.

Of course the second branch fails and that number is never tried at that point.

I understand from looking at the code in timer.c that this sequence is by
design.

What I need is for the CANCEL to come out *before* the next INVITE, and I need
to be able to reasonably ASSume that the CANCEL was received by the PSTN gw and
my invite will not trigger loop detection.  I've fielded two different ways of
doing this, both of which make me feel uneasy.  Both of these involved mucking
with final_response_handler in tm/timer.c.  After the line:

DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);

I changed the rest of the function first to read as follows (try not to laugh
too hard):

    cancel_branch(t, r_buf->branch);
    sleep(1);
    fake_reply(t, r_buf->branch, 408 );

    DBG("DEBUG: final_response_handler : done\n");

I'm a little uneasy about scheduling that cancel while the reply is locked, but
it *seems* safe.  I also didn't like the fact that I was hard-coding the time,
I'd rather have it linked a bit more to the gateway processing the CANCEL,
so...

Then I tried this:

    if(should_cancel_branch(t, r_buf->branch))
    {
        int timer = 2;
        DBG("DEBUG: final_response_handler: cancel hack (%p)\n", t);
        UNLOCK_REPLIES(t);
        cancel_branch(t, r_buf->branch);
        fr_tl->timer_list= NULL; /* set to NULL so that set_timer will work */
        set_timer( fr_tl, FR_INV_TIMER_LIST, &timer );
    }
    else
    {
        DBG("DEBUG: final_response_handler: timeout (%p)\n", t);
        fake_reply(t, r_buf->branch, 408 );
    }
                                                                               

    DBG("DEBUG: final_response_handler : done\n");


This gives me the link between the final from the cancel being received, and
the send of the second invite, but it has the unwanted effect of causing the
status when the failure_route script is called to always be 487, so I'd need a
way to communicate to scripts that the 487 is really the result of a local
cancel triggered by the fr_timer firing.  I could theoretically get that by
re-running branch picking and checking the uac for that branch for a local
cancel, but that doesn't seem clean.

Presumably if I put a hack in place like this, it would default to off, and I'd
use a flag or something on the message before t_relay()ing the original request
to signal to tm that I want this treatment for this transaction, but I digress.

What I really need is a way to make everything look normal to the scripts (i.e.
t_check_status will still match to a 408), but gets me the CANCEL sequence I
need.

Any ideas?  Am I a bad person for trying the code above? ;)

Thanks,
Phil

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 




More information about the sr-users mailing list