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