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
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 #include "defs.h"
00118
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 "t_funcs.h"
00136 #include "t_reply.h"
00137 #include "t_cancel.h"
00138 #include "t_hooks.h"
00139 #ifdef USE_DNS_FAILOVER
00140 #include "t_fwd.h"
00141 #include "../../cfg_core.h"
00142 #endif
00143 #ifdef USE_DST_BLACKLIST
00144 #include "../../dst_blacklist.h"
00145 #endif
00146
00147
00148
00149 struct msgid_var user_fr_timeout;
00150 struct msgid_var user_fr_inv_timeout;
00151 #ifdef TM_DIFF_RT_TIMEOUT
00152 struct msgid_var user_rt_t1_timeout;
00153 struct msgid_var user_rt_t2_timeout;
00154 #endif
00155 struct msgid_var user_inv_max_lifetime;
00156 struct msgid_var user_noninv_max_lifetime;
00157
00158
00159
00160
00161
00162
00163 #define SIZE_FIT_CHECK(cell_member, val, cfg_name) \
00164 if (MAX_UVAR_VALUE(((struct cell*)0)->cell_member) <= (val)){ \
00165 ERR("tm_init_timers: " cfg_name " too big: %lu (%lu ticks) " \
00166 "- max %lu (%lu ticks) \n", TICKS_TO_MS((unsigned long)(val)),\
00167 (unsigned long)(val), \
00168 TICKS_TO_MS(MAX_UVAR_VALUE(((struct cell*)0)->cell_member)), \
00169 MAX_UVAR_VALUE(((struct cell*)0)->cell_member)); \
00170 goto error; \
00171 }
00172
00173
00174 int tm_init_timers()
00175 {
00176 default_tm_cfg.fr_timeout=MS_TO_TICKS(default_tm_cfg.fr_timeout);
00177 default_tm_cfg.fr_inv_timeout=MS_TO_TICKS(default_tm_cfg.fr_inv_timeout);
00178 default_tm_cfg.wait_timeout=MS_TO_TICKS(default_tm_cfg.wait_timeout);
00179 default_tm_cfg.delete_timeout=MS_TO_TICKS(default_tm_cfg.delete_timeout);
00180 default_tm_cfg.rt_t1_timeout=MS_TO_TICKS(default_tm_cfg.rt_t1_timeout);
00181 default_tm_cfg.rt_t2_timeout=MS_TO_TICKS(default_tm_cfg.rt_t2_timeout);
00182 default_tm_cfg.tm_max_inv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_inv_lifetime);
00183 default_tm_cfg.tm_max_noninv_lifetime=MS_TO_TICKS(default_tm_cfg.tm_max_noninv_lifetime);
00184
00185 if (default_tm_cfg.fr_timeout==0) default_tm_cfg.fr_timeout=1;
00186 if (default_tm_cfg.fr_inv_timeout==0) default_tm_cfg.fr_inv_timeout=1;
00187 if (default_tm_cfg.wait_timeout==0) default_tm_cfg.wait_timeout=1;
00188 if (default_tm_cfg.delete_timeout==0) default_tm_cfg.delete_timeout=1;
00189 if (default_tm_cfg.rt_t2_timeout==0) default_tm_cfg.rt_t2_timeout=1;
00190 if (default_tm_cfg.rt_t1_timeout==0) default_tm_cfg.rt_t1_timeout=1;
00191 if (default_tm_cfg.tm_max_inv_lifetime==0) default_tm_cfg.tm_max_inv_lifetime=1;
00192 if (default_tm_cfg.tm_max_noninv_lifetime==0) default_tm_cfg.tm_max_noninv_lifetime=1;
00193
00194
00195 SIZE_FIT_CHECK(fr_timeout, default_tm_cfg.fr_timeout, "fr_timer");
00196 SIZE_FIT_CHECK(fr_inv_timeout, default_tm_cfg.fr_inv_timeout, "fr_inv_timer");
00197 #ifdef TM_DIFF_RT_TIMEOUT
00198 SIZE_FIT_CHECK(rt_t1_timeout, default_tm_cfg.rt_t1_timeout, "retr_timer1");
00199 SIZE_FIT_CHECK(rt_t2_timeout, default_tm_cfg.rt_t2_timeout, "retr_timer2");
00200 #endif
00201 SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_inv_lifetime, "max_inv_lifetime");
00202 SIZE_FIT_CHECK(end_of_life, default_tm_cfg.tm_max_noninv_lifetime, "max_noninv_lifetime");
00203
00204 memset(&user_fr_timeout, 0, sizeof(user_fr_timeout));
00205 memset(&user_fr_inv_timeout, 0, sizeof(user_fr_inv_timeout));
00206 #ifdef TM_DIFF_RT_TIMEOUT
00207 memset(&user_rt_t1_timeout, 0, sizeof(user_rt_t1_timeout));
00208 memset(&user_rt_t2_timeout, 0, sizeof(user_rt_t2_timeout));
00209 #endif
00210 memset(&user_inv_max_lifetime, 0, sizeof(user_inv_max_lifetime));
00211 memset(&user_noninv_max_lifetime, 0, sizeof(user_noninv_max_lifetime));
00212
00213 DBG("tm: tm_init_timers: fr=%d fr_inv=%d wait=%d delete=%d t1=%d t2=%d"
00214 " max_inv_lifetime=%d max_noninv_lifetime=%d\n",
00215 default_tm_cfg.fr_timeout, default_tm_cfg.fr_inv_timeout,
00216 default_tm_cfg.wait_timeout, default_tm_cfg.delete_timeout,
00217 default_tm_cfg.rt_t1_timeout, default_tm_cfg.rt_t2_timeout,
00218 default_tm_cfg.tm_max_inv_lifetime, default_tm_cfg.tm_max_noninv_lifetime);
00219 return 0;
00220 error:
00221 return -1;
00222 }
00223
00224
00225
00226
00227 #define IF_IS_TIMER_NAME(cell_member, cfg_name) \
00228 if ((name->len == sizeof(cfg_name)-1) && \
00229 (memcmp(name->s, cfg_name, sizeof(cfg_name)-1)==0)) { \
00230 SIZE_FIT_CHECK(cell_member, t, cfg_name); \
00231 }
00232
00233
00234
00235
00236 int timer_fixup(void *handle, str *gname, str *name, void **val)
00237 {
00238 ticks_t t;
00239
00240 t = MS_TO_TICKS((unsigned int)(long)(*val));
00241
00242 if (t == 0) t = 1;
00243
00244
00245 IF_IS_TIMER_NAME(fr_timeout, "fr_timer")
00246 else IF_IS_TIMER_NAME(fr_inv_timeout, "fr_inv_timer")
00247 #ifdef TM_DIFF_RT_TIMEOUT
00248 else IF_IS_TIMER_NAME(rt_t1_timeout, "retr_timer1")
00249 else IF_IS_TIMER_NAME(rt_t2_timeout, "retr_timer2")
00250 #endif
00251 else IF_IS_TIMER_NAME(end_of_life, "max_inv_lifetime")
00252 else IF_IS_TIMER_NAME(end_of_life, "max_noninv_lifetime")
00253
00254 *val = (void *)(long)t;
00255 return 0;
00256
00257 error:
00258 return -1;
00259 }
00260
00261
00262
00263
00264 #ifndef TM_DEL_UNREF
00265
00266
00267 inline static ticks_t delete_cell( struct cell *p_cell, int unlock )
00268 {
00269
00270
00271
00272
00273
00274 unlink_timers( p_cell );
00275
00276 if ( IS_REFFED_UNSAFE(p_cell) ) {
00277 if (unlock) UNLOCK_HASH(p_cell->hash_index);
00278 DBG("DEBUG: delete_cell %p: can't delete -- still reffed (%d)\n",
00279 p_cell, p_cell->ref_count);
00280
00281
00282 return cfg_get(tm, tm_cfg, delete_timeout);
00283 } else {
00284 if (unlock) UNLOCK_HASH(p_cell->hash_index);
00285 #ifdef EXTRA_DEBUG
00286 DBG("DEBUG: delete transaction %p\n", p_cell );
00287 #endif
00288 free_cell( p_cell );
00289 return 0;
00290 }
00291 }
00292 #endif
00293
00294
00295
00296
00297
00298
00299 static void fake_reply(struct cell *t, int branch, int code )
00300 {
00301 branch_bm_t cancel_bitmap;
00302 short do_cancel_branch;
00303 enum rps reply_status;
00304
00305 do_cancel_branch = is_invite(t) && should_cancel_branch(t, branch, 0);
00306
00307 t->uac[branch].request.flags|=F_RB_CANCELED;
00308 if ( is_local(t) ) {
00309 reply_status=local_reply( t, FAKED_REPLY, branch,
00310 code, &cancel_bitmap );
00311 } else {
00312
00313
00314 reply_status=relay_reply( t, FAKED_REPLY, branch, code,
00315 &cancel_bitmap, 0 );
00316 }
00317
00318 if (do_cancel_branch) cancel_branch(t, branch, 0);
00319
00320
00321
00322 if (reply_status == RPS_COMPLETED)
00323 put_on_wait(t);
00324 }
00325
00326
00327
00328
00329 inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
00330 {
00331 #ifdef EXTRA_DEBUG
00332 if (r_buf->my_T->flags & T_IN_AGONY) {
00333 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
00334 " called from RETR timer (flags %x)\n",
00335 r_buf->my_T, r_buf->my_T->flags );
00336 abort();
00337 }
00338 #endif
00339 if ( r_buf->activ_type==TYPE_LOCAL_CANCEL
00340 || r_buf->activ_type==TYPE_REQUEST ) {
00341 #ifdef EXTRA_DEBUG
00342 DBG("DEBUG: retransmission_handler : "
00343 "request resending (t=%p, %.9s ... )\n",
00344 r_buf->my_T, r_buf->buffer);
00345 #endif
00346 if (SEND_BUFFER( r_buf )==-1) {
00347
00348 fake_reply(r_buf->my_T, r_buf->branch, 503 );
00349 return (ticks_t)-1;
00350 }
00351 #ifdef TMCB_ONSEND
00352 if (unlikely(has_tran_tmcbs(r_buf->my_T, TMCB_REQUEST_SENT)))
00353 run_onsend_callbacks(TMCB_REQUEST_SENT, r_buf,
00354 0, 0, TMCB_RETR_F);
00355 #endif
00356 } else {
00357 #ifdef EXTRA_DEBUG
00358 DBG("DEBUG: retransmission_handler : "
00359 "reply resending (t=%p, %.9s ... )\n",
00360 r_buf->my_T, r_buf->buffer);
00361 #endif
00362 t_retransmit_reply(r_buf->my_T);
00363 }
00364
00365 return 0;
00366 }
00367
00368
00369
00370 inline static void final_response_handler( struct retr_buf* r_buf,
00371 struct cell* t)
00372 {
00373 int silent;
00374 #ifdef USE_DNS_FAILOVER
00375
00376
00377
00378 int branch_ret;
00379 int prev_branch;
00380 ticks_t now;
00381 #endif
00382
00383 # ifdef EXTRA_DEBUG
00384 if (t->flags & T_IN_AGONY)
00385 {
00386 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
00387 " called from FR timer (flags %x)\n", t, t->flags);
00388 abort();
00389 }
00390 # endif
00391
00392 if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
00393 {
00394 #ifdef TIMER_DEBUG
00395 DBG("DEBUG: final_response_handler: stop retr for Local Cancel\n");
00396 #endif
00397 return;
00398 }
00399
00400 if (r_buf->activ_type>0) {
00401 # ifdef EXTRA_DEBUG
00402 if (t->uas.request->REQ_METHOD!=METHOD_INVITE
00403 || t->uas.status < 200 ) {
00404 LOG(L_CRIT, "BUG: final_response_handler: unknown type reply"
00405 " buffer\n");
00406 abort();
00407 }
00408 # endif
00409 put_on_wait( t );
00410 return;
00411 };
00412
00413
00414 LOCK_REPLIES( t );
00415
00416
00417
00418
00419 silent=
00420
00421 cfg_get(tm, tm_cfg, noisy_ctimer)==0
00422
00423 && has_noisy_ctimer(t) == 0
00424
00425 && !is_local(t)
00426
00427 && is_invite(t)
00428
00429 && t->nr_of_outgoings==1
00430
00431
00432 && t->on_negative==0
00433
00434 && !has_tran_tmcbs( t, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE)
00435
00436 && t->uac[r_buf->branch].last_received==0;
00437
00438 if (silent) {
00439 UNLOCK_REPLIES(t);
00440 #ifdef EXTRA_DEBUG
00441 DBG("DEBUG: final_response_handler: transaction silently dropped (%p)"
00442 ", branch %d, last_received %d\n",t, r_buf->branch,
00443 t->uac[r_buf->branch].last_received);
00444 #endif
00445 put_on_wait( t );
00446 return;
00447 }
00448 #ifdef EXTRA_DEBUG
00449 DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
00450 #endif
00451 if ((r_buf->branch < MAX_BRANCHES) &&
00452 (t->uac[r_buf->branch].last_received==0) &&
00453 (t->uac[r_buf->branch].request.buffer!=NULL)
00454 ){
00455
00456 #ifdef USE_DST_BLACKLIST
00457 if (cfg_get(core, core_cfg, use_dst_blacklist)
00458 && r_buf->my_T
00459 && r_buf->my_T->uas.request
00460 && (r_buf->my_T->uas.request->REQ_METHOD & cfg_get(tm, tm_cfg, tm_blst_methods_add))
00461 )
00462 dst_blacklist_add( BLST_ERR_TIMEOUT, &r_buf->dst,
00463 r_buf->my_T->uas.request);
00464 #endif
00465 #ifdef USE_DNS_FAILOVER
00466
00467
00468
00469 if (cfg_get(core, core_cfg, use_dns_failover)){
00470 now=get_ticks_raw();
00471 if ((s_ticks_t)(t->end_of_life-now)>0){
00472 branch_ret=add_uac_dns_fallback(t, t->uas.request,
00473 &t->uac[r_buf->branch], 0);
00474 prev_branch=-1;
00475 while((branch_ret>=0) &&(branch_ret!=prev_branch)){
00476 prev_branch=branch_ret;
00477 branch_ret=t_send_branch(t, branch_ret, t->uas.request ,
00478 0, 0);
00479 }
00480 }
00481 }
00482 #endif
00483 }
00484 fake_reply(t, r_buf->branch, 408);
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 ticks_t retr_buf_handler(ticks_t ticks, struct timer_ln* tl, void *p)
00502 {
00503 struct retr_buf* rbuf ;
00504 ticks_t fr_remainder;
00505 ticks_t retr_remainder;
00506 ticks_t retr_interval;
00507 ticks_t new_retr_interval;
00508 struct cell *t;
00509
00510 rbuf=(struct retr_buf*)
00511 ((void*)tl-(void*)(&((struct retr_buf*)0)->timer));
00512 membar_depends();
00513 t=rbuf->my_T;
00514
00515 #ifdef TIMER_DEBUG
00516 DBG("tm: timer retr_buf_handler @%d (%p -> %p -> %p)\n",
00517 ticks, tl, rbuf, t);
00518 #endif
00519 if (unlikely(rbuf->flags & F_RB_DEL_TIMER)){
00520
00521 rbuf->t_active=0;
00522
00523
00524
00525
00526 return 0;
00527 }
00528
00529 if ((s_ticks_t)(rbuf->fr_expire-ticks)<=0){
00530
00531 rbuf->t_active=0;
00532
00533
00534
00535 rbuf->flags|=F_RB_TIMEOUT;
00536
00537
00538
00539 timer_allow_del();
00540
00541 final_response_handler(rbuf, t);
00542 return 0;
00543 }else{
00544
00545 if ((s_ticks_t)(rbuf->retr_expire-ticks)<=0){
00546 if (rbuf->flags & F_RB_RETR_DISABLED)
00547 goto disabled;
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 if ((rbuf->flags & F_RB_T2) ||
00560 (((ticks_t)(unsigned long)p)>RT_T2_TIMEOUT(rbuf))){
00561 retr_interval=RT_T2_TIMEOUT(rbuf);
00562 new_retr_interval=RT_T2_TIMEOUT(rbuf);
00563 }else{
00564 retr_interval=(ticks_t)(unsigned long)p;
00565 new_retr_interval=retr_interval<<1;
00566 }
00567 #ifdef TIMER_DEBUG
00568 DBG("tm: timer: retr: new interval %d (max %d)\n",
00569 retr_interval, RT_T2_TIMEOUT(rbuf));
00570 #endif
00571
00572
00573
00574 rbuf->retr_expire=ticks+retr_interval;
00575
00576 retr_remainder=retransmission_handler(rbuf) | retr_interval;
00577
00578
00579 tl->data=(void*)(unsigned long)(new_retr_interval);
00580 }else{
00581 retr_remainder= rbuf->retr_expire-ticks;
00582 DBG("tm: timer: retr: nothing to do, expire in %d\n",
00583 retr_remainder);
00584 }
00585 }
00586
00587
00588
00589
00590 fr_remainder=rbuf->fr_expire-ticks;
00591
00592
00593
00594 #ifdef TIMER_DEBUG
00595 DBG("tm: timer retr_buf_handler @%d (%p ->%p->%p) exiting min (%d, %d)\n",
00596 ticks, tl, rbuf, t, retr_remainder, fr_remainder);
00597 #endif
00598 #ifdef EXTRA_DEBUG
00599 if (retr_remainder==0 || fr_remainder==0){
00600 BUG("tm: timer retr_buf_handler: 0 remainder => disabling timer!: "
00601 "retr_remainder=%d, fr_remainder=%d\n", retr_remainder,
00602 fr_remainder);
00603 }
00604 #endif
00605 if (retr_remainder<fr_remainder)
00606 return retr_remainder;
00607 else{
00608
00609 #ifdef TM_FAST_RETR_TIMER
00610 tl->flags&=~F_TIMER_FAST;
00611 #endif
00612 return fr_remainder;
00613 }
00614 disabled:
00615 return rbuf->fr_expire-ticks;
00616 }
00617
00618
00619
00620 ticks_t wait_handler(ticks_t ti, struct timer_ln *wait_tl, void* data)
00621 {
00622 struct cell *p_cell;
00623 ticks_t ret;
00624
00625 p_cell=(struct cell*)data;
00626 #ifdef TIMER_DEBUG
00627 DBG("DEBUG: WAIT timer hit @%d for %p (timer_lm %p)\n",
00628 ti, p_cell, wait_tl);
00629 #endif
00630
00631 #ifdef TM_DEL_UNREF
00632
00633 if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00634
00635 LOCK_HASH( p_cell->hash_index );
00636 remove_from_hash_table_unsafe( p_cell );
00637 UNLOCK_HASH( p_cell->hash_index );
00638 p_cell->flags |= T_IN_AGONY;
00639 UNREF_FREE(p_cell);
00640 ret=0;
00641 #else
00642 if (p_cell->flags & T_IN_AGONY){
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 ret=delete_cell( p_cell, 0 );
00654 }else {
00655
00656 if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00657
00658 LOCK_HASH( p_cell->hash_index );
00659 remove_from_hash_table_unsafe( p_cell );
00660 p_cell->flags |= T_IN_AGONY;
00661
00662 ret=delete_cell( p_cell, 1 );
00663 }
00664 #endif
00665 return ret;
00666 }
00667