00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00110 #ifndef _TM_TIMER_H
00111 #define _TM_TIMER_H
00112
00113 #include "defs.h"
00114
00115 #include "../../compiler_opt.h"
00116 #include "lock.h"
00117
00118 #include "../../timer.h"
00119 #include "h_table.h"
00120 #include "config.h"
00121
00125 #define TM_FAST_RETR_TIMER
00126
00127
00128 #ifdef TM_DIFF_RT_TIMEOUT
00129 #define RT_T1_TIMEOUT_MS(rb) ((rb)->my_T->rt_t1_timeout_ms)
00130 #define RT_T2_TIMEOUT_MS(rb) ((rb)->my_T->rt_t2_timeout_ms)
00131 #else
00132 #define RT_T1_TIMEOUT_MS(rb) (cfg_get(tm, tm_cfg, rt_t1_timeout_ms))
00133 #define RT_T2_TIMEOUT_MS(rb) (cfg_get(tm, tm_cfg, rt_t2_timeout_ms))
00134 #endif
00135
00136 #define TM_REQ_TIMEOUT(t) \
00137 (is_invite(t)? \
00138 cfg_get(tm, tm_cfg, tm_max_inv_lifetime): \
00139 cfg_get(tm, tm_cfg, tm_max_noninv_lifetime))
00140
00141
00142 extern struct msgid_var user_fr_timeout;
00143 extern struct msgid_var user_fr_inv_timeout;
00144 #ifdef TM_DIFF_RT_TIMEOUT
00145 extern struct msgid_var user_rt_t1_timeout_ms;
00146 extern struct msgid_var user_rt_t2_timeout_ms;
00147 #endif
00148 extern struct msgid_var user_inv_max_lifetime;
00149 extern struct msgid_var user_noninv_max_lifetime;
00150
00151
00155 extern int tm_init_timers(void);
00156
00168 int timer_fixup(void *handle, str *gname, str *name, void **val);
00169 int timer_fixup_ms(void *handle, str *gname, str *name, void **val);
00170
00171 ticks_t wait_handler(ticks_t t, struct timer_ln *tl, void* data);
00172 ticks_t retr_buf_handler(ticks_t t, struct timer_ln *tl, void* data);
00173
00174
00175 #define init_cell_timers(c) \
00176 timer_init(&(c)->wait_timer, wait_handler, (c), F_TIMER_FAST)
00177
00178 #define init_rb_timers(rb) \
00179 timer_init(&(rb)->timer, retr_buf_handler, \
00180 (void*)(unsigned long)(RT_T1_TIMEOUT_MS(rb)), 0)
00181
00182
00183
00184
00185
00186
00187 #ifdef TIMER_DEBUG
00188 inline static int _set_fr_retr(struct retr_buf* rb, unsigned retr_ms,
00189 const char* file, const char* func,
00190 unsigned line)
00191 #else
00192 inline static int _set_fr_retr(struct retr_buf* rb, unsigned retr_ms)
00193 #endif
00194 {
00195 ticks_t timeout;
00196 ticks_t ticks;
00197 ticks_t eol;
00198 ticks_t retr_ticks;
00199 int ret;
00200
00201 ticks=get_ticks_raw();
00202 timeout=rb->my_T->fr_timeout;
00203 eol=rb->my_T->end_of_life;
00204 retr_ticks = (retr_ms != (unsigned)(-1))?MS_TO_TICKS(retr_ms):retr_ms;
00205
00206 rb->timer.data=(void*)(unsigned long)(2*retr_ms);
00207 rb->retr_expire=ticks + retr_ticks;
00208 if (unlikely(rb->t_active)){
00209
00210
00211 #ifdef TIMER_DEBUG
00212 LOG(L_WARN, "WARNING: _set_fr_timer called from: %s(%s):%d\n",
00213 file, func, line);
00214 #endif
00215 LOG(L_CRIT, "WARNING: -_set_fr_timer- already added: %p , tl=%p!!!\n",
00216 rb, &rb->timer);
00217 }
00218
00219 rb->flags|= (F_RB_RETR_DISABLED & -(retr_ms==(unsigned)-1));
00220 #ifdef TM_FAST_RETR_TIMER
00221
00222 rb->timer.flags|=(F_TIMER_FAST & -(retr_ms!=(unsigned)-1));
00223 #endif
00224
00225
00226 if (unlikely ((rb->activ_type==TYPE_REQUEST) &&
00227 ((s_ticks_t)(eol-(ticks+timeout))<0)) ){
00228 timeout=(((s_ticks_t)(eol-ticks))>0)?(eol-ticks):1;
00229 }
00230 atomic_cmpxchg_int((void*)&rb->fr_expire, 0, (int)(ticks+timeout));
00231 if (unlikely(rb->flags & F_RB_DEL_TIMER)){
00232
00233
00234
00235 DBG("_set_fr_timer: too late, timer already marked for deletion\n");
00236 return 0;
00237 }
00238 #ifdef TIMER_DEBUG
00239 ret=timer_add_safe(&(rb)->timer, (timeout<retr_ticks)?timeout:retr_ticks,
00240 file, func, line);
00241 #else
00242 ret=timer_add(&(rb)->timer, (timeout<retr_ticks)?timeout:retr_ticks);
00243 #endif
00244 if (ret==0) rb->t_active=1;
00245 membar_write_atomic_op();
00246
00247
00248 return ret;
00249 }
00250
00251
00252
00253
00254 #define stop_rb_timers(rb) \
00255 do{ \
00256 membar_depends(); \
00257 (rb)->flags|=F_RB_DEL_TIMER; \
00258 if ((rb)->t_active){ \
00259 (rb)->t_active=0; \
00260 timer_del(&(rb)->timer); \
00261 }\
00262 }while(0)
00263
00264
00265 #define stop_rb_retr(rb) \
00266 ((rb)->flags|=F_RB_RETR_DISABLED)
00267
00268
00269 #define switch_rb_retr_to_t2(rb) \
00270 do{ \
00271 (rb)->flags|=F_RB_T2; \
00272 (rb)->retr_expire=get_ticks_raw()+MS_TO_TICKS(RT_T2_TIMEOUT_MS(rb)); \
00273 }while(0)
00274
00275
00276
00277 inline static void restart_rb_fr(struct retr_buf* rb, ticks_t new_val)
00278 {
00279 ticks_t now;
00280 struct cell* t;
00281
00282 now=get_ticks_raw();
00283 t=rb->my_T;
00284 if (unlikely ((rb->activ_type==TYPE_REQUEST) &&
00285 (((s_ticks_t)(t->end_of_life-(now+new_val)))<0)) )
00286 rb->fr_expire=t->end_of_life;
00287 else
00288 rb->fr_expire=now+new_val;
00289 }
00290
00291
00292
00293
00294
00295
00296 inline static void change_fr(struct cell* t, ticks_t fr_inv, ticks_t fr)
00297 {
00298 int i;
00299 ticks_t fr_inv_expire, fr_expire, req_fr_expire;
00300
00301 fr_expire=get_ticks_raw();
00302 fr_inv_expire=fr_expire+fr_inv;
00303 fr_expire+=fr;
00304 req_fr_expire=((s_ticks_t)(t->end_of_life-fr_expire)<0)?
00305 t->end_of_life:fr_expire;
00306 if (fr_inv) t->fr_inv_timeout=fr_inv;
00307 if (fr) t->fr_timeout=fr;
00308 for (i=0; i<t->nr_of_outgoings; i++){
00309 if (t->uac[i].request.t_active){
00310 if ((t->uac[i].request.flags & F_RB_FR_INV) && fr_inv)
00311 t->uac[i].request.fr_expire=fr_inv_expire;
00312 else if (fr){
00313 if (t->uac[i].request.activ_type==TYPE_REQUEST)
00314 t->uac[i].request.fr_expire=req_fr_expire;
00315 else
00316 t->uac[i].request.fr_expire=fr_expire;
00317 }
00318 }
00319 }
00320 }
00321
00322
00323 #ifdef TM_DIFF_RT_TIMEOUT
00324
00325
00326
00327
00328
00329
00330 inline static void change_retr(struct cell* t, int now,
00331 unsigned rt_t1_ms, unsigned rt_t2_ms)
00332 {
00333 int i;
00334
00335 if (rt_t1_ms) t->rt_t1_timeout_ms=rt_t1_ms;
00336 if (rt_t2_ms) t->rt_t2_timeout_ms=rt_t2_ms;
00337 if (now){
00338 for (i=0; i<t->nr_of_outgoings; i++){
00339 if (t->uac[i].request.t_active){
00340 if ((t->uac[i].request.flags & F_RB_T2) && rt_t2_ms)
00341
00342
00343 t->uac[i].request.timer.data =
00344 (void*)(unsigned long)rt_t2_ms;
00345 else if (rt_t1_ms)
00346 t->uac[i].request.timer.data =
00347 (void*)(unsigned long)rt_t1_ms;
00348 }
00349 }
00350 }
00351 }
00352 #endif
00353
00354
00355
00356
00357
00358
00359
00360 inline static void change_end_of_life(struct cell* t, int adj, ticks_t eol)
00361 {
00362 int i;
00363
00364 t->end_of_life=get_ticks_raw()+eol;
00365 if (adj){
00366 for (i=0; i<t->nr_of_outgoings; i++){
00367 if (t->uac[i].request.t_active){
00368 if ((t->uac[i].request.activ_type==TYPE_REQUEST) &&
00369 ((s_ticks_t)(t->end_of_life -
00370 t->uac[i].request.fr_expire)<0))
00371 t->uac[i].request.fr_expire=t->end_of_life;
00372 }
00373 }
00374 }
00375 }
00376
00377 inline static void cleanup_localcancel_timers( struct cell *t )
00378 {
00379 int i;
00380 for (i=0; i<t->nr_of_outgoings; i++ )
00381 stop_rb_timers(&t->uac[i].local_cancel);
00382 }
00383
00384
00385
00386 inline static void unlink_timers( struct cell *t )
00387 {
00388 int i;
00389
00390 stop_rb_timers(&t->uas.response);
00391 for (i=0; i<t->nr_of_outgoings; i++)
00392 stop_rb_timers(&t->uac[i].request);
00393 cleanup_localcancel_timers(t);
00394 }
00395
00396
00397
00398 #endif