Index: modules/tm/t_reply.c =================================================================== --- modules/tm/t_reply.c (revision 5326) +++ modules/tm/t_reply.c (working copy) @@ -1030,8 +1030,8 @@ /* reset FR/retransmission timers */ for (i=t->first_branch; inr_of_outgoings; i++ ) { - reset_timer( &t->uac[i].request.retr_timer ); - reset_timer( &t->uac[i].request.fr_timer ); + reset_timer( &t->uac[i].request.retr_timer, TIMER_RB_DEL); + reset_timer( &t->uac[i].request.fr_timer, TIMER_RB_DEL); } LM_DBG("RETR/FR timers reset\n"); } @@ -1361,21 +1361,21 @@ /* it's a cancel which is not e2e ? */ if ( get_cseq(p_msg)->method_id==METHOD_CANCEL && is_invite(t) ) { /* ... then just stop timers */ - reset_timer( &uac->local_cancel.retr_timer); + reset_timer( &uac->local_cancel.retr_timer, TIMER_RB_DEL); if ( msg_status >= 200 ) { - reset_timer( &uac->local_cancel.fr_timer); + reset_timer( &uac->local_cancel.fr_timer, TIMER_RB_DEL); } LM_DBG("reply to local CANCEL processed\n"); goto done; } /* *** stop timers *** */ - /* stop retransmission */ - reset_timer(&uac->request.retr_timer); + /* stop retransmission and assume end of transaction */ + reset_timer(&uac->request.retr_timer, TIMER_RB_DEL); /* stop final response timer only if I got a final response */ if ( msg_status >= 200 ) { - reset_timer( &uac->request.fr_timer); + reset_timer( &uac->request.fr_timer, TIMER_RB_DEL); } /* acknowledge negative INVITE replies (do it before detailed @@ -1468,6 +1468,12 @@ if (reply_status!=RPS_PROVISIONAL) goto done; + /* not done with current branch, jump to RB Stop state + * - we may need to retransmit */ + reset_timer(&uac->request.retr_timer, TIMER_RB_STOP); + if ( msg_status >= 200 ) + reset_timer( &uac->request.fr_timer, TIMER_RB_STOP); + /* update FR/RETR timers on provisional replies */ if (msg_status < 200 && (restart_fr_on_each_reply || ((last_uac_statusuas.response.fr_timer ); - reset_timer( & trans->uas.response.retr_timer ); + reset_timer( & trans->uas.response.fr_timer , TIMER_RB_DEL ); + reset_timer( & trans->uas.response.retr_timer, TIMER_RB_DEL ); cleanup_uac_timers( trans ); Index: modules/tm/t_fwd.c =================================================================== --- modules/tm/t_fwd.c (revision 5326) +++ modules/tm/t_fwd.c (working copy) @@ -552,8 +552,8 @@ for (i=t_invite->first_branch; inr_of_outgoings; i++) { if (t_invite->uac[i].last_received==0){ /* reset the "request" timers */ - reset_timer(&t_invite->uac[i].request.retr_timer); - reset_timer(&t_invite->uac[i].request.fr_timer); + reset_timer(&t_invite->uac[i].request.retr_timer, TIMER_RB_DEL); + reset_timer(&t_invite->uac[i].request.fr_timer, TIMER_RB_DEL); LOCK_REPLIES( t_invite ); if (RPS_ERROR==relay_reply(t_invite,FAKED_REPLY,i,487,&dummy_bm)) lowest_error = -1; /* force sending 500 error */ @@ -718,6 +718,9 @@ -p_msg->REQ_METHOD); } + //LM_DBG("++++++++++++ before sleep\n"); + //sleep(2); + //LM_DBG("++++++++++++ after sleep\n"); start_retr( &t->uac[i].request ); set_kr(REQ_FWDED); } Index: modules/tm/timer.c =================================================================== --- modules/tm/timer.c (revision 5326) +++ modules/tm/timer.c (working copy) @@ -302,7 +302,7 @@ LM_DBG("retransmission_handler : request resending" " (t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer.s); if (SEND_BUFFER( r_buf )==-1) { - reset_timer( &r_buf->fr_timer ); + reset_timer( &r_buf->fr_timer, TIMER_RB_DEL ); fake_reply(r_buf->my_T, r_buf->branch, 503 ); return; } @@ -346,7 +346,7 @@ } # endif - reset_timer( &(r_buf->retr_timer) ); + reset_timer( &(r_buf->retr_timer) , TIMER_RB_DEL); /* the transaction is already removed from FR_LIST by the timer */ @@ -384,8 +384,8 @@ { int i; for (i=0; inr_of_outgoings; i++ ) { - reset_timer( &t->uac[i].local_cancel.retr_timer ); - reset_timer( &t->uac[i].local_cancel.fr_timer ); + reset_timer( &t->uac[i].local_cancel.retr_timer, TIMER_RB_DEL); + reset_timer( &t->uac[i].local_cancel.fr_timer , TIMER_RB_DEL); } } @@ -809,7 +809,7 @@ * (successive set_timer won't work unless you're lucky * an catch the race condition, the idea here is there is no * guarantee you can do anything after a timer_reset)*/ -void reset_timer( struct timer_link* tl ) +void reset_timer( struct timer_link* tl , int state) { /* disqualify this timer from execution by setting its time_out to zero; it will stay in timer-list until the timer process @@ -817,9 +817,10 @@ but not execute; there is a race condition, though -- see timer.c for more details */ - tl->deleted = 1; + tl->deleted = state; + LM_DBG("+++++++++++ tl=%p, st=%d)\n", tl, state); #ifdef EXTRA_DEBUG - LM_DBG("(group %d, tl=%p)\n", tl->tg, tl ); + LM_DBG("(group %d, tl=%p, st=%d)\n", tl->tg, tl, state); #endif } @@ -848,6 +849,17 @@ return; } + /* rb timer already scheduled for delete */ + if(new_tl->deleted==TIMER_RB_DEL) + { + LM_DBG("++++++++++++ too late to arm the timer [%p] [%d]\n", + new_tl, list_id); + return; + } + + LM_DBG("++++++++++++ arming the timer [%p] [%d]\n", + new_tl, list_id); + if (!ext_timeout) { timeout = timer_id2timeout[ list_id ]; } else { Index: modules/tm/timer.h =================================================================== --- modules/tm/timer.h (revision 5326) +++ modules/tm/timer.h (working copy) @@ -57,6 +57,9 @@ NR_OF_TIMER_LISTS }; +#define TIMER_RB_INIT 0 +#define TIMER_RB_STOP 1 +#define TIMER_RB_DEL 2 /* all you need to put a cell in a timer list links to neighbors and timer value */ @@ -67,7 +70,7 @@ struct timer_link *ld_tl; volatile utime_t time_out; struct timer *timer_list; - unsigned int deleted; + volatile unsigned int deleted; #ifdef EXTRA_DEBUG enum timer_groups tg; #endif @@ -106,7 +109,7 @@ void init_timer_list( enum lists list_id); void reset_timer_list( enum lists list_id); -void reset_timer( struct timer_link* tl ); +void reset_timer( struct timer_link* tl, int state); /* determine timer length and put on a correct timer list */ void set_timer( struct timer_link *new_tl, enum lists list_id,