modules/tm/timer.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2003 FhG Fokus
00003  *
00004  * This file is part of ser, a free SIP server.
00005  *
00006  * ser is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version
00010  *
00011  * For a license to use the ser software under conditions
00012  * other than those described here, or to purchase support for this
00013  * software, please contact iptel.org by e-mail at the following addresses:
00014  *    info@iptel.org
00015  *
00016  * ser is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  */
00025 
00026 /*
00027  * History:
00028  * --------
00029  *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
00030  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
00031  *              timer_link.payload removed (bogdan)
00032  *  2005-10-03  almost completely rewritten to use the new timers (andrei)
00033  *  2005-12-12  on final response marked the rb as removed to avoid deleting
00034  *              it from the timer handle; timer_allow_del()  (andrei)
00035  *  2006-08-11  final_response_handler dns failover support for timeout-ed
00036  *              invites (andrei)
00037  *  2006-09-28  removed the 480 on fr_inv_timeout reply: on timeout always 
00038  *               return a 408
00039  *              set the corresponding "faked" failure route sip_msg->msg_flags 
00040  *               on timeout or if the branch received a reply (andrei)
00041  *  2007-03-15  TMCB_ONSEND callbacks support (andrei)
00042  *  2007-05-29  delete on transaction ref_count==0 : removed the delete timer
00043  *               (andrei)
00044  * 2007-06-01  support for different retransmissions intervals per transaction;
00045  *             added maximum inv. and non-inv. transaction life time (andrei)
00046  */
00047 
00118 #include "defs.h"
00119 
00120 
00121 #include "config.h"
00122 #include "h_table.h"
00123 #include "timer.h"
00124 #include "../../dprint.h"
00125 #include "lock.h"
00126 #include "t_stats.h"
00127 
00128 #include "../../hash_func.h"
00129 #include "../../dprint.h"
00130 #include "../../config.h"
00131 #include "../../parser/parser_f.h"
00132 #include "../../ut.h"
00133 #include "../../timer_ticks.h"
00134 #include "../../compiler_opt.h" 
00135 #include "../../sr_compat.h" 
00136 #include "t_funcs.h"
00137 #include "t_reply.h"
00138 #include "t_cancel.h"
00139 #include "t_hooks.h"
00140 #ifdef USE_DNS_FAILOVER
00141 #include "t_fwd.h" /* t_send_branch */
00142 #include "../../cfg_core.h" /* cfg_get(core, core_cfg, use_dns_failover) */
00143 #endif
00144 #ifdef USE_DST_BLACKLIST
00145 #include "../../dst_blacklist.h"
00146 #endif
00147 
00148 
00149 
00150 struct msgid_var user_fr_timeout;
00151 struct msgid_var user_fr_inv_timeout;
00152 #ifdef TM_DIFF_RT_TIMEOUT
00153 struct msgid_var user_rt_t1_timeout_ms;
00154 struct msgid_var user_rt_t2_timeout_ms;
00155 #endif
00156 struct msgid_var user_inv_max_lifetime;
00157 struct msgid_var user_noninv_max_lifetime;
00158 
00159 
00169 #define SIZE_FIT_CHECK(cell_member, val, cfg_name) \
00170         if (MAX_UVAR_VALUE(((struct cell*)0)->cell_member) <= (val)){ \
00171                 ERR("tm_init_timers: " cfg_name " too big: %lu (%lu ticks) " \
00172                                 "- max %lu (%lu ticks) \n", TICKS_TO_MS((unsigned long)(val)),\
00173                                 (unsigned long)(val), \
00174                                 TICKS_TO_MS(MAX_UVAR_VALUE(((struct cell*)0)->cell_member)), \
00175                                 MAX_UVAR_VALUE(((struct cell*)0)->cell_member)); \
00176                 goto error; \
00177         } 
00178 
00182 int tm_init_timers(void)
00183 {
00184         default_tm_cfg.fr_timeout=MS_TO_TICKS(default_tm_cfg.fr_timeout); 
00185         default_tm_cfg.fr_inv_timeout=MS_TO_TICKS(default_tm_cfg.fr_inv_timeout);
00186         default_tm_cfg.wait_timeout=MS_TO_TICKS(default_tm_cfg.wait_timeout);
00187         default_tm_cfg.delete_timeout=MS_TO_TICKS(default_tm_cfg.delete_timeout);
00188         default_tm_cfg.tm_max_inv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_inv_lifetime);
00189         default_tm_cfg.tm_max_noninv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_noninv_lifetime);
00190         /* fix 0 values to 1 tick (minimum possible wait time ) */
00191         if (default_tm_cfg.fr_timeout==0) default_tm_cfg.fr_timeout=1;
00192         if (default_tm_cfg.fr_inv_timeout==0) default_tm_cfg.fr_inv_timeout=1;
00193         if (default_tm_cfg.wait_timeout==0) default_tm_cfg.wait_timeout=1;
00194         if (default_tm_cfg.delete_timeout==0) default_tm_cfg.delete_timeout=1;
00195         if (default_tm_cfg.rt_t2_timeout_ms==0) default_tm_cfg.rt_t2_timeout_ms=1;
00196         if (default_tm_cfg.rt_t1_timeout_ms==0) default_tm_cfg.rt_t1_timeout_ms=1;
00197         if (default_tm_cfg.tm_max_inv_lifetime==0) default_tm_cfg.tm_max_inv_lifetime=1;
00198         if (default_tm_cfg.tm_max_noninv_lifetime==0) default_tm_cfg.tm_max_noninv_lifetime=1;
00199         
00200         /* size fit checks */
00201         SIZE_FIT_CHECK(fr_timeout, default_tm_cfg.fr_timeout, "fr_timer");
00202         SIZE_FIT_CHECK(fr_inv_timeout, default_tm_cfg.fr_inv_timeout, "fr_inv_timer");
00203 #ifdef TM_DIFF_RT_TIMEOUT
00204         SIZE_FIT_CHECK(rt_t1_timeout_ms, default_tm_cfg.rt_t1_timeout_ms,
00205                                         "retr_timer1");
00206         SIZE_FIT_CHECK(rt_t2_timeout_ms, default_tm_cfg.rt_t2_timeout_ms,
00207                                         "retr_timer2");
00208 #endif
00209         SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_inv_lifetime, "max_inv_lifetime");
00210         SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_noninv_lifetime, "max_noninv_lifetime");
00211         
00212         memset(&user_fr_timeout, 0, sizeof(user_fr_timeout));
00213         memset(&user_fr_inv_timeout, 0, sizeof(user_fr_inv_timeout));
00214 #ifdef TM_DIFF_RT_TIMEOUT
00215         memset(&user_rt_t1_timeout_ms, 0, sizeof(user_rt_t1_timeout_ms));
00216         memset(&user_rt_t2_timeout_ms, 0, sizeof(user_rt_t2_timeout_ms));
00217 #endif
00218         memset(&user_inv_max_lifetime, 0, sizeof(user_inv_max_lifetime));
00219         memset(&user_noninv_max_lifetime, 0, sizeof(user_noninv_max_lifetime));
00220         
00221         DBG("tm: tm_init_timers: fr=%d fr_inv=%d wait=%d delete=%d t1=%d t2=%d"
00222                         " max_inv_lifetime=%d max_noninv_lifetime=%d\n",
00223                         default_tm_cfg.fr_timeout, default_tm_cfg.fr_inv_timeout,
00224                         default_tm_cfg.wait_timeout, default_tm_cfg.delete_timeout,
00225                         default_tm_cfg.rt_t1_timeout_ms, default_tm_cfg.rt_t2_timeout_ms,
00226                         default_tm_cfg.tm_max_inv_lifetime, default_tm_cfg.tm_max_noninv_lifetime);
00227         return 0;
00228 error:
00229         return -1;
00230 }
00231 
00238 #define IF_IS_TIMER_NAME(cell_member, cfg_name) \
00239         if ((name->len == sizeof(cfg_name)-1) && \
00240                 (memcmp(name->s, cfg_name, sizeof(cfg_name)-1)==0)) { \
00241                         SIZE_FIT_CHECK(cell_member, t, cfg_name); \
00242         }
00243 
00255 int timer_fixup(void *handle, str *gname, str *name, void **val)
00256 {
00257         ticks_t t;
00258 
00259         t = MS_TO_TICKS((unsigned int)(long)(*val));
00260         /* fix 0 values to 1 tick (minimum possible wait time ) */
00261         if (t == 0) t = 1;
00262 
00263         /* size fix checks */
00264         IF_IS_TIMER_NAME(fr_timeout, "fr_timer")
00265         else IF_IS_TIMER_NAME(fr_inv_timeout, "fr_inv_timer")
00266         else IF_IS_TIMER_NAME(end_of_life, "max_inv_lifetime")
00267         else IF_IS_TIMER_NAME(end_of_life, "max_noninv_lifetime")
00268 
00269         *val = (void *)(long)t;
00270         return 0;
00271 
00272 error:
00273         return -1;
00274 }
00275 
00276 
00277 
00282 int timer_fixup_ms(void *handle, str *gname, str *name, void **val)
00283 {
00284         long    t;
00285 
00286         t = (long)(*val);
00287 
00288         /* size fix checks */
00289 #ifdef TM_DIFF_RT_TIMEOUT
00290         IF_IS_TIMER_NAME(rt_t1_timeout_ms, "retr_timer1")
00291         else IF_IS_TIMER_NAME(rt_t2_timeout_ms, "retr_timer2")
00292 #endif
00293 
00294         return 0;
00295 
00296 error:
00297         return -1;
00298 }
00299 
00300 /******************** handlers ***************************/
00301 
00302 
00303 #ifndef TM_DEL_UNREF
00304 /* returns number of ticks before retrying the del, or 0 if the del.
00305  * was succesfull */
00306 inline static ticks_t  delete_cell( struct cell *p_cell, int unlock )
00307 {
00308         /* there may still be FR/RETR timers, which have been reset
00309            (i.e., time_out==TIMER_DELETED) but are stilled linked to
00310            timer lists and must be removed from there before the
00311            structures are released
00312         */
00313         unlink_timers( p_cell );
00314         /* still in use ... don't delete */
00315         if ( IS_REFFED_UNSAFE(p_cell) ) {
00316                 if (unlock) UNLOCK_HASH(p_cell->hash_index);
00317                 DBG("DEBUG: delete_cell %p: can't delete -- still reffed (%d)\n",
00318                                 p_cell, p_cell->ref_count);
00319                 /* delay the delete */
00320                 /* TODO: change refcnts and delete on refcnt==0 */
00321                 return cfg_get(tm, tm_cfg, delete_timeout);
00322         } else {
00323                 if (unlock) UNLOCK_HASH(p_cell->hash_index);
00324 #ifdef EXTRA_DEBUG
00325                 DBG("DEBUG: delete transaction %p\n", p_cell );
00326 #endif
00327                 free_cell( p_cell );
00328                 return 0;
00329         }
00330 }
00331 #endif /* TM_DEL_UNREF */
00332 
00333 
00334 
00335 
00336 /* generate a fake reply
00337  * it assumes the REPLY_LOCK is already held and returns unlocked */
00338 static void fake_reply(struct cell *t, int branch, int code )
00339 {
00340         struct cancel_info cancel_data;
00341         short do_cancel_branch;
00342         enum rps reply_status;
00343 
00344         init_cancel_info(&cancel_data);
00345         do_cancel_branch = is_invite(t) && prepare_cancel_branch(t, branch, 0);
00346         /* mark branch as canceled */
00347         t->uac[branch].request.flags|=F_RB_CANCELED;
00348         if ( is_local(t) ) {
00349                 reply_status=local_reply( t, FAKED_REPLY, branch, 
00350                                           code, &cancel_data );
00351         } else {
00352                 /* rely reply, but don't put on wait, we still need t
00353                  * to send the cancels */
00354                 reply_status=relay_reply( t, FAKED_REPLY, branch, code,
00355                                           &cancel_data, 0 );
00356         }
00357         /* now when out-of-lock do the cancel I/O */
00358 #ifdef CANCEL_REASON_SUPPORT
00359         if (do_cancel_branch) cancel_branch(t, branch, &cancel_data.reason, 0);
00360 #else /* CANCEL_REASON_SUPPORT */
00361         if (do_cancel_branch) cancel_branch(t, branch, 0);
00362 #endif /* CANCEL_REASON_SUPPORT */
00363         /* it's cleaned up on error; if no error occurred and transaction
00364            completed regularly, I have to clean-up myself
00365         */
00366         if (reply_status == RPS_COMPLETED)
00367                 put_on_wait(t);
00368 }
00369 
00370 
00371 
00372 /* return (ticks_t)-1 on error/disable and 0 on success */
00373 inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
00374 {
00375 #ifdef EXTRA_DEBUG
00376         if (r_buf->my_T->flags & T_IN_AGONY) {
00377                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
00378                         " called from RETR timer (flags %x)\n",
00379                         r_buf->my_T, r_buf->my_T->flags );
00380                 abort();
00381         }       
00382 #endif
00383         if ( r_buf->activ_type==TYPE_LOCAL_CANCEL 
00384                 || r_buf->activ_type==TYPE_REQUEST ) {
00385 #ifdef EXTRA_DEBUG
00386                         DBG("DEBUG: retransmission_handler : "
00387                                 "request resending (t=%p, %.9s ... )\n", 
00388                                 r_buf->my_T, r_buf->buffer);
00389 #endif
00390                         if (SEND_BUFFER( r_buf )==-1) {
00391                                 /* disable retr. timers => return -1 */
00392                                 fake_reply(r_buf->my_T, r_buf->branch, 503 );
00393                                 return (ticks_t)-1;
00394                         }
00395                         if (unlikely(has_tran_tmcbs(r_buf->my_T, TMCB_REQUEST_SENT))) 
00396                                 run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, r_buf, 
00397                                 0, 0, TMCB_RETR_F);
00398         } else {
00399 #ifdef EXTRA_DEBUG
00400                         DBG("DEBUG: retransmission_handler : "
00401                                 "reply resending (t=%p, %.9s ... )\n", 
00402                                 r_buf->my_T, r_buf->buffer);
00403 #endif
00404                         t_retransmit_reply(r_buf->my_T);
00405         }
00406         
00407         return 0;
00408 }
00409 
00410 
00411 
00412 inline static void final_response_handler(      struct retr_buf* r_buf,
00413                                                                                         struct cell* t)
00414 {
00415         int silent;
00416 #ifdef USE_DNS_FAILOVER
00417         /*int i; 
00418         int added_branches;
00419         */
00420         int branch_ret;
00421         int prev_branch;
00422         ticks_t now;
00423 #endif
00424 
00425 #       ifdef EXTRA_DEBUG
00426         if (t->flags & T_IN_AGONY) 
00427         {
00428                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
00429                         " called from FR timer (flags %x)\n", t, t->flags);
00430                 abort();
00431         }
00432 #       endif
00433         /* FR for local cancels.... */
00434         if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
00435         {
00436 #ifdef TIMER_DEBUG
00437                 DBG("DEBUG: final_response_handler: stop retr for Local Cancel\n");
00438 #endif
00439                 return;
00440         }
00441         /* FR for replies (negative INVITE replies) */
00442         if (r_buf->activ_type>0) {
00443 #               ifdef EXTRA_DEBUG
00444                 if (t->uas.request->REQ_METHOD!=METHOD_INVITE
00445                         || t->uas.status < 200 ) {
00446                         LOG(L_CRIT, "BUG: final_response_handler: unknown type reply"
00447                                         " buffer\n");
00448                         abort();
00449                 }
00450 #               endif
00451                 put_on_wait( t );
00452                 return;
00453         };
00454 
00455         /* lock reply processing to determine how to proceed reliably */
00456         LOCK_REPLIES( t );
00457         /* now it can be only a request retransmission buffer;
00458            try if you can simply discard the local transaction 
00459            state without compellingly removing it from the
00460            world */
00461         silent=
00462                 /* don't go silent if disallowed globally ... */
00463                 cfg_get(tm, tm_cfg, noisy_ctimer)==0
00464                 /* ... or for this particular transaction */
00465                 && has_noisy_ctimer(t) == 0
00466                 /* not for UACs */
00467                 && !is_local(t)
00468                 /* invites only */
00469                 && is_invite(t)
00470                 /* parallel forking does not allow silent state discarding */
00471                 && t->nr_of_outgoings==1
00472                 /* on_negativ reply handler not installed -- serial forking 
00473                  * could occur otherwise */
00474                 && t->on_negative==0
00475                 /* the same for FAILURE callbacks */
00476                 && !has_tran_tmcbs( t, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE) 
00477                 /* something received -- we will not be silent on error */
00478                 && t->uac[r_buf->branch].last_received==0;
00479         
00480         if (silent) {
00481                 UNLOCK_REPLIES(t);
00482 #ifdef EXTRA_DEBUG
00483                 DBG("DEBUG: final_response_handler: transaction silently dropped (%p)"
00484                                 ", branch %d, last_received %d\n",t, r_buf->branch,
00485                                  t->uac[r_buf->branch].last_received);
00486 #endif
00487                 put_on_wait( t );
00488                 return;
00489         }
00490 #ifdef EXTRA_DEBUG
00491         DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
00492 #endif
00493         if ((r_buf->branch < MAX_BRANCHES) && /* r_buf->branch is always >=0 */
00494                         (t->uac[r_buf->branch].last_received==0) &&
00495                         (t->uac[r_buf->branch].request.buffer!=NULL) /* not a blind UAC */
00496         ){
00497                 /* no reply received */
00498 #ifdef USE_DST_BLACKLIST
00499                 if (r_buf->my_T
00500                         && r_buf->my_T->uas.request
00501                         && (r_buf->my_T->uas.request->REQ_METHOD &
00502                                         cfg_get(tm, tm_cfg, tm_blst_methods_add))
00503                 )
00504                         dst_blacklist_add( BLST_ERR_TIMEOUT, &r_buf->dst,
00505                                                                 r_buf->my_T->uas.request);
00506 #endif
00507 #ifdef USE_DNS_FAILOVER
00508                 /* if this is an invite, the destination resolves to more ips, and
00509                  *  it still hasn't passed more than fr_inv_timeout since we
00510                  *  started, add another branch/uac */
00511                 if (cfg_get(core, core_cfg, use_dns_failover)){
00512                         now=get_ticks_raw();
00513                         if ((s_ticks_t)(t->end_of_life-now)>0){
00514                                 branch_ret=add_uac_dns_fallback(t, t->uas.request,
00515                                                                                                         &t->uac[r_buf->branch], 0);
00516                                 prev_branch=-1;
00517                                 while((branch_ret>=0) &&(branch_ret!=prev_branch)){
00518                                         prev_branch=branch_ret;
00519                                         branch_ret=t_send_branch(t, branch_ret, t->uas.request , 
00520                                                                                                 0, 0);
00521                                 }
00522                         }
00523                 }
00524 #endif
00525         }
00526         fake_reply(t, r_buf->branch, 408);
00527 }
00528 
00529 
00530 
00531 /* handles retransmissions and fr timers */
00532 /* the following assumption are made (to avoid deleting/re-adding the timer):
00533  *  retr_buf->retr_interval < ( 1<<((sizeof(ticks_t)*8-1) )
00534  *  if retr_buf->retr_interval==0 => timer disabled
00535  *                            ==(ticks_t) -1 => retr. disabled (fr working)
00536  *     retr_buf->retr_interval & (1 <<(sizeof(ticks_t)*8-1) => retr. & fr reset
00537  *     (we never reset only retr, it's either reset both of them or retr 
00538  *      disabled & reset fr). In this case the fr_origin will contain the 
00539  *      "time" of the reset and next retr should occur at 
00540  *      fr->origin+retr_interval (we also assume that we'll never reset retr
00541  *      to a lower value then the current one)
00542  */
00543 ticks_t retr_buf_handler(ticks_t ticks, struct timer_ln* tl, void *p)
00544 {
00545         struct retr_buf* rbuf ;
00546         ticks_t fr_remainder;
00547         ticks_t retr_remainder;
00548         ticks_t retr_interval;
00549         unsigned long new_retr_interval_ms;
00550         unsigned long crt_retr_interval_ms;
00551         struct cell *t;
00552 
00553         rbuf=(struct  retr_buf*)
00554                         ((void*)tl-(void*)(&((struct retr_buf*)0)->timer));
00555         membar_depends(); /* to be on the safe side */
00556         t=rbuf->my_T;
00557         
00558 #ifdef TIMER_DEBUG
00559         DBG("tm: timer retr_buf_handler @%d (%p -> %p -> %p)\n",
00560                         ticks, tl, rbuf, t);
00561 #endif
00562         if (unlikely(rbuf->flags & F_RB_DEL_TIMER)){
00563                 /* timer marked for deletion */
00564                 rbuf->t_active=0; /* mark it as removed */
00565                 /* a membar is not really needed, in the very unlikely case that 
00566                  * another process will see old t_active's value and will try to 
00567                  * delete the timer again, but since timer_del it's safe in this cases
00568                  * it will be a no-op */
00569                 return 0;
00570         }
00571         /* overflow safe check (should work ok for fr_intervals < max ticks_t/2) */
00572         if ((s_ticks_t)(rbuf->fr_expire-ticks)<=0){
00573                 /* final response */
00574                 rbuf->t_active=0; /* mark the timer as removed 
00575                                                          (both timers disabled)
00576                                                           a little race risk, but
00577                                                           nothing bad would happen */
00578                 rbuf->flags|=F_RB_TIMEOUT;
00579                 /* WARNING:  the next line depends on taking care not to start the 
00580                  *           wait timer before finishing with t (if this is not 
00581                  *           guaranteed then comment the timer_allow_del() line) */
00582                 timer_allow_del(); /* [optional] allow timer_dels, since we're done
00583                                                           and there is no race risk */
00584                 final_response_handler(rbuf, t);
00585                 return 0;
00586         }else{
00587                 /*  4 possible states running (t1), t2, paused, disabled */
00588                         if ((s_ticks_t)(rbuf->retr_expire-ticks)<=0){
00589                                 if (rbuf->flags & F_RB_RETR_DISABLED)
00590                                         goto disabled;
00591                                 crt_retr_interval_ms = (unsigned long)p;
00592                                 /* get the  current interval from timer param. */
00593                                 if (unlikely((rbuf->flags & F_RB_T2) ||
00594                                                 (crt_retr_interval_ms > RT_T2_TIMEOUT_MS(rbuf)))){
00595                                         retr_interval = MS_TO_TICKS(RT_T2_TIMEOUT_MS(rbuf));
00596                                         new_retr_interval_ms = RT_T2_TIMEOUT_MS(rbuf);
00597                                 }else{
00598                                         retr_interval = MS_TO_TICKS(crt_retr_interval_ms);
00599                                         new_retr_interval_ms=crt_retr_interval_ms<<1;
00600                                 }
00601 #ifdef TIMER_DEBUG
00602                                 DBG("tm: timer: retr: new interval %ld ms / %d ticks"
00603                                                 " (max %d ms)\n", new_retr_interval_ms, retr_interval,
00604                                                 RT_T2_TIMEOUT_MS(rbuf));
00605 #endif
00606                                 /* we could race with the reply_received code, but the 
00607                                  * worst thing that can happen is to delay a reset_to_t2
00608                                  * for crt_interval and send an extra retr.*/
00609                                 rbuf->retr_expire=ticks+retr_interval;
00610                                 /* set new interval to -1 on error, or retr_int. on success */
00611                                 retr_remainder=retransmission_handler(rbuf) | retr_interval;
00612                                 /* store the next retr. interval in ms inside the timer struct,
00613                                  * in the data member */
00614                                 tl->data=(void*)(new_retr_interval_ms);
00615                         }else{
00616                                 retr_remainder= rbuf->retr_expire-ticks;
00617                                 DBG("tm: timer: retr: nothing to do, expire in %d\n", 
00618                                                 retr_remainder);
00619                         }
00620         }
00621 /* skip: */
00622         /* return minimum of the next retransmission handler and the 
00623          * final response (side benefit: it properly cancels timer if ret==0 and
00624          *  sleeps for fr_remainder if retr. is canceled [==(ticks_t)-1]) */
00625         fr_remainder=rbuf->fr_expire-ticks; /* to be more precise use
00626                                                                                         get_ticks_raw() instead of ticks
00627                                                                                         (but make sure that 
00628                                                                                         crt. ticks < fr_expire */
00629 #ifdef TIMER_DEBUG
00630         DBG("tm: timer retr_buf_handler @%d (%p ->%p->%p) exiting min (%d, %d)\n",
00631                         ticks, tl, rbuf, t, retr_remainder, fr_remainder);
00632 #endif
00633 #ifdef EXTRA_DEBUG
00634         if  (retr_remainder==0 || fr_remainder==0){
00635                 BUG("tm: timer retr_buf_handler: 0 remainder => disabling timer!: "
00636                                 "retr_remainder=%d, fr_remainder=%d\n", retr_remainder,
00637                                 fr_remainder);
00638         }
00639 #endif
00640         if (retr_remainder<fr_remainder)
00641                 return retr_remainder;
00642         else{
00643                 /* hack to switch to the slow timer */
00644 #ifdef TM_FAST_RETR_TIMER
00645                 tl->flags&=~F_TIMER_FAST;
00646 #endif
00647                 return fr_remainder;
00648         }
00649 disabled:
00650         return rbuf->fr_expire-ticks;
00651 }
00652 
00653 
00654 
00655 ticks_t wait_handler(ticks_t ti, struct timer_ln *wait_tl, void* data)
00656 {
00657         struct cell *p_cell;
00658         ticks_t ret;
00659 
00660         p_cell=(struct cell*)data;
00661 #ifdef TIMER_DEBUG
00662         DBG("DEBUG: WAIT timer hit @%d for %p (timer_lm %p)\n", 
00663                         ti, p_cell, wait_tl);
00664 #endif
00665 
00666 #ifdef TM_DEL_UNREF
00667         /* stop cancel timers if any running */
00668         if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00669         /* remove the cell from the hash table */
00670         LOCK_HASH( p_cell->hash_index );
00671         remove_from_hash_table_unsafe(  p_cell );
00672         UNLOCK_HASH( p_cell->hash_index );
00673         p_cell->flags |= T_IN_AGONY;
00674         UNREF_FREE(p_cell);
00675         ret=0;
00676 #else /* TM_DEL_UNREF */
00677         if (p_cell->flags & T_IN_AGONY){
00678                 /* delayed delete */
00679                 /* we call delete now without any locking on hash/ref_count;
00680                    we can do that because delete_handler is only entered after
00681                    the delete timer was installed from wait_handler, which
00682                    removed transaction from hash table and did not destroy it
00683                    because some processes were using it; that means that the
00684                    processes currently using the transaction can unref and no
00685                    new processes can ref -- we can wait until ref_count is
00686                    zero safely without locking
00687                 */
00688                 ret=delete_cell( p_cell, 0 /* don't unlock on return */ );
00689         }else {
00690                 /* stop cancel timers if any running */
00691                 if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00692                 /* remove the cell from the hash table */
00693                 LOCK_HASH( p_cell->hash_index );
00694                 remove_from_hash_table_unsafe(  p_cell );
00695                 p_cell->flags |= T_IN_AGONY;
00696                 /* delete (returns with UNLOCK-ed_HASH) */
00697                 ret=delete_cell( p_cell, 1 /* unlock on return */ );
00698         }
00699 #endif /* TM_DEL_UNREF */
00700         return ret;
00701 }
00702