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
00039
00040
00041
00042
00043
00044
00045
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"
00142 #include "../../cfg_core.h"
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
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
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
00261 if (t == 0) t = 1;
00262
00263
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
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
00301
00302
00303 #ifndef TM_DEL_UNREF
00304
00305
00306 inline static ticks_t delete_cell( struct cell *p_cell, int unlock )
00307 {
00308
00309
00310
00311
00312
00313 unlink_timers( p_cell );
00314
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
00320
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
00332
00333
00334
00335
00336
00337
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
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
00353
00354 reply_status=relay_reply( t, FAKED_REPLY, branch, code,
00355 &cancel_data, 0 );
00356 }
00357
00358 #ifdef CANCEL_REASON_SUPPORT
00359 if (do_cancel_branch) cancel_branch(t, branch, &cancel_data.reason, 0);
00360 #else
00361 if (do_cancel_branch) cancel_branch(t, branch, 0);
00362 #endif
00363
00364
00365
00366 if (reply_status == RPS_COMPLETED)
00367 put_on_wait(t);
00368 }
00369
00370
00371
00372
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
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
00418
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
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
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
00456 LOCK_REPLIES( t );
00457
00458
00459
00460
00461 silent=
00462
00463 cfg_get(tm, tm_cfg, noisy_ctimer)==0
00464
00465 && has_noisy_ctimer(t) == 0
00466
00467 && !is_local(t)
00468
00469 && is_invite(t)
00470
00471 && t->nr_of_outgoings==1
00472
00473
00474 && t->on_negative==0
00475
00476 && !has_tran_tmcbs( t, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE)
00477
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) &&
00494 (t->uac[r_buf->branch].last_received==0) &&
00495 (t->uac[r_buf->branch].request.buffer!=NULL)
00496 ){
00497
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
00509
00510
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
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
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();
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
00564 rbuf->t_active=0;
00565
00566
00567
00568
00569 return 0;
00570 }
00571
00572 if ((s_ticks_t)(rbuf->fr_expire-ticks)<=0){
00573
00574 rbuf->t_active=0;
00575
00576
00577
00578 rbuf->flags|=F_RB_TIMEOUT;
00579
00580
00581
00582 timer_allow_del();
00583
00584 final_response_handler(rbuf, t);
00585 return 0;
00586 }else{
00587
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
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
00607
00608
00609 rbuf->retr_expire=ticks+retr_interval;
00610
00611 retr_remainder=retransmission_handler(rbuf) | retr_interval;
00612
00613
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
00622
00623
00624
00625 fr_remainder=rbuf->fr_expire-ticks;
00626
00627
00628
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
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
00668 if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00669
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
00677 if (p_cell->flags & T_IN_AGONY){
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 ret=delete_cell( p_cell, 0 );
00689 }else {
00690
00691 if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00692
00693 LOCK_HASH( p_cell->hash_index );
00694 remove_from_hash_table_unsafe( p_cell );
00695 p_cell->flags |= T_IN_AGONY;
00696
00697 ret=delete_cell( p_cell, 1 );
00698 }
00699 #endif
00700 return ret;
00701 }
00702