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 #include "config.h"
00113 #include "h_table.h"
00114 #include "timer.h"
00115 #include "../../dprint.h"
00116 #include "lock.h"
00117
00118 #include "../../hash_func.h"
00119 #include "../../dprint.h"
00120 #include "../../config.h"
00121 #include "../../parser/parser_f.h"
00122 #include "../../ut.h"
00123 #include "t_funcs.h"
00124 #include "t_reply.h"
00125 #include "t_cancel.h"
00126
00127
00128 static struct timer_table *timertable=0;
00129 static struct timer detached_timer;
00130
00131 #define DETACHED_LIST (&detached_timer)
00132
00133 #define is_in_timer_list2(_tl) ( (_tl)->timer_list && \
00134 ((_tl)->timer_list!=DETACHED_LIST) )
00135
00136
00137
00138 int timer_group[NR_OF_TIMER_LISTS] =
00139 {
00140 TG_FR, TG_FR,
00141 TG_WT,
00142 TG_DEL,
00143 TG_RT, TG_RT, TG_RT, TG_RT
00144 };
00145
00146
00147
00148
00149 unsigned int timer_id2timeout[NR_OF_TIMER_LISTS] = {
00150 FR_TIME_OUT,
00151 INV_FR_TIME_OUT,
00152 WT_TIME_OUT,
00153 DEL_TIME_OUT,
00154 RETR_T1,
00155 0,
00156 0,
00157 RETR_T2
00158
00159 };
00160
00161 #define UTIME_TYPE 1
00162
00163 static unsigned int timer_id2type[NR_OF_TIMER_LISTS] = {
00164 0,
00165 0,
00166 0,
00167 0,
00168 UTIME_TYPE,
00169 UTIME_TYPE,
00170 UTIME_TYPE,
00171 UTIME_TYPE
00172
00173 };
00174
00175
00176
00177
00178
00179 static void unlink_timers( struct cell *t );
00180
00181 static void delete_cell( struct cell *p_cell, int unlock )
00182 {
00183 #ifdef EXTRA_DEBUG
00184 int i;
00185 #endif
00186
00187
00188
00189
00190
00191
00192 unlink_timers( p_cell );
00193
00194 #ifdef EXTRA_DEBUG
00195 if (is_in_timer_list2(& p_cell->wait_tl )) {
00196 LM_ERR("transaction %p scheduled for deletion and still on WAIT,"
00197 " timeout=%lld\n",p_cell, p_cell->wait_tl.time_out);
00198 abort();
00199 }
00200 if (is_in_timer_list2(& p_cell->uas.response.retr_timer )) {
00201 LM_ERR("transaction %p scheduled for deletion and still on RETR (rep),"
00202 "timeout=%lld\n",p_cell, p_cell->uas.response.retr_timer.time_out);
00203 abort();
00204 }
00205 if (is_in_timer_list2(& p_cell->uas.response.fr_timer )) {
00206 LM_ERR("transaction %p scheduled for deletion and still on FR (rep),"
00207 " timeout=%lld\n", p_cell,p_cell->uas.response.fr_timer.time_out);
00208 abort();
00209 }
00210 for (i=0; i<p_cell->nr_of_outgoings; i++) {
00211 if (is_in_timer_list2(& p_cell->uac[i].request.retr_timer)) {
00212 LM_ERR("transaction %p scheduled for deletion and still on RETR "
00213 "(req %d), timeout %lld\n", p_cell, i,
00214 p_cell->uac[i].request.retr_timer.time_out);
00215 abort();
00216 }
00217 if (is_in_timer_list2(& p_cell->uac[i].request.fr_timer)) {
00218 LM_ERR("transaction %p scheduled for deletion and"
00219 " still on FR (req %d), timeout %lld\n", p_cell, i,
00220 p_cell->uac[i].request.fr_timer.time_out);
00221 abort();
00222 }
00223 if (is_in_timer_list2(& p_cell->uac[i].local_cancel.retr_timer)) {
00224 LM_ERR("transaction %p scheduled for deletion and"
00225 " still on RETR/cancel (req %d), timeout %lld\n", p_cell, i,
00226 p_cell->uac[i].request.retr_timer.time_out);
00227 abort();
00228 }
00229 if (is_in_timer_list2(& p_cell->uac[i].local_cancel.fr_timer)) {
00230 LM_ERR("transaction %p scheduled for deletion and"
00231 " still on FR/cancel (req %d), timeout %lld\n", p_cell, i,
00232 p_cell->uac[i].request.fr_timer.time_out);
00233 abort();
00234 }
00235 }
00236
00237 #endif
00238
00239 if ( IS_REFFED_UNSAFE(p_cell) ) {
00240 LM_DBG("delete_cell %p: can't delete -- still reffed (%d)\n",
00241 p_cell, p_cell->ref_count);
00242 if (unlock) UNLOCK_HASH(p_cell->hash_index);
00243
00244 p_cell->dele_tl.timer_list= NULL;
00245
00246 set_timer( &(p_cell->dele_tl), DELETE_LIST, 0 );
00247 } else {
00248 if (unlock) UNLOCK_HASH(p_cell->hash_index);
00249 LM_DBG("delete transaction %p\n", p_cell );
00250 free_cell( p_cell );
00251 }
00252 }
00253
00254 static void fake_reply(struct cell *t, int branch, int code )
00255 {
00256 branch_bm_t cancel_bitmap;
00257 short do_cancel_branch;
00258 enum rps reply_status;
00259
00260 do_cancel_branch = is_invite(t) && should_cancel_branch(t, branch);
00261
00262 cancel_bitmap=do_cancel_branch ? 1<<branch : 0;
00263 if ( is_local(t) ) {
00264 reply_status=local_reply( t, FAKED_REPLY, branch,
00265 code, &cancel_bitmap );
00266 if (reply_status==RPS_COMPLETED) {
00267 put_on_wait(t);
00268 }
00269 } else {
00270 reply_status=relay_reply( t, FAKED_REPLY, branch, code,
00271 &cancel_bitmap );
00272 }
00273
00274 if (do_cancel_branch) cancel_branch(t, branch );
00275
00276
00277
00278 }
00279
00280
00281
00282
00283
00284 inline static void retransmission_handler( struct timer_link *retr_tl )
00285 {
00286 struct retr_buf* r_buf ;
00287 enum lists id;
00288
00289 r_buf = get_retr_timer_payload(retr_tl);
00290 #ifdef EXTRA_DEBUG
00291 if (r_buf->my_T->damocles) {
00292 LM_ERR("transaction %p scheduled for deletion and"
00293 " called from RETR timer\n",r_buf->my_T);
00294 abort();
00295 }
00296 #endif
00297
00298
00299
00300 if ( r_buf->activ_type==TYPE_LOCAL_CANCEL
00301 || r_buf->activ_type==TYPE_REQUEST ) {
00302 LM_DBG("retransmission_handler : request resending"
00303 " (t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer.s);
00304 if (SEND_BUFFER( r_buf )==-1) {
00305 reset_timer( &r_buf->fr_timer );
00306 fake_reply(r_buf->my_T, r_buf->branch, 503 );
00307 return;
00308 }
00309 } else {
00310 LM_DBG("retransmission_handler : reply resending "
00311 "(t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer.s);
00312 t_retransmit_reply(r_buf->my_T);
00313 }
00314
00315 id = r_buf->retr_list;
00316 r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
00317
00318 retr_tl->timer_list= NULL;
00319 set_timer( retr_tl, id < RT_T2 ? id + 1 : RT_T2, 0 );
00320
00321 LM_DBG("retransmission_handler : done\n");
00322 }
00323
00324
00325
00326
00327 inline static void final_response_handler( struct timer_link *fr_tl )
00328 {
00329 struct retr_buf* r_buf;
00330 struct cell *t;
00331
00332 if (fr_tl==0){
00333
00334 LM_CRIT("final_response_handler(0) called\n");
00335 return;
00336 }
00337 r_buf = get_fr_timer_payload(fr_tl);
00338 t=r_buf->my_T;
00339
00340 # ifdef EXTRA_DEBUG
00341 if (t->damocles)
00342 {
00343 LM_ERR("transaction %p scheduled for deletion and"
00344 " called from FR timer\n",r_buf->my_T);
00345 abort();
00346 }
00347 # endif
00348
00349 reset_timer( &(r_buf->retr_timer) );
00350
00351
00352
00353
00354 if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
00355 {
00356 LM_DBG("stop retr for Local Cancel\n");
00357 return;
00358 }
00359
00360
00361 if (r_buf->activ_type>0) {
00362 # ifdef EXTRA_DEBUG
00363 if (t->uas.request->REQ_METHOD!=METHOD_INVITE
00364 || t->uas.status < 200 ) {
00365 LM_ERR("unknown type reply buffer\n");
00366 abort();
00367 }
00368 # endif
00369 put_on_wait( t );
00370 return;
00371 };
00372
00373
00374 LOCK_REPLIES( t );
00375 LM_DBG("stop retr. and send CANCEL (%p)\n", t);
00376 fake_reply(t, r_buf->branch, 408 );
00377
00378 LM_DBG("done\n");
00379 }
00380
00381
00382
00383 void cleanup_localcancel_timers( struct cell *t )
00384 {
00385 int i;
00386 for (i=0; i<t->nr_of_outgoings; i++ ) {
00387 reset_timer( &t->uac[i].local_cancel.retr_timer );
00388 reset_timer( &t->uac[i].local_cancel.fr_timer );
00389 }
00390 }
00391
00392
00393 inline static void wait_handler( struct timer_link *wait_tl )
00394 {
00395 struct cell *p_cell;
00396
00397 p_cell = get_wait_timer_payload( wait_tl );
00398 #ifdef EXTRA_DEBUG
00399 if (p_cell->damocles) {
00400 LM_ERR("transaction %p scheduled for deletion and"
00401 " called from WAIT timer\n",p_cell);
00402 abort();
00403 }
00404 LM_DBG("WAIT timer hit\n");
00405 #endif
00406
00407
00408 if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00409
00410
00411
00412 LM_DBG("removing %p from table \n", p_cell );
00413 LOCK_HASH( p_cell->hash_index );
00414 remove_from_hash_table_unsafe( p_cell );
00415
00416 #ifdef EXTRA_DEBUG
00417 p_cell->damocles = 1;
00418 #endif
00419
00420 delete_cell( p_cell, 1 );
00421 LM_DBG("done\n");
00422 }
00423
00424
00425
00426 inline static void delete_handler( struct timer_link *dele_tl )
00427 {
00428 struct cell *p_cell;
00429
00430 p_cell = get_dele_timer_payload( dele_tl );
00431 LM_DBG("removing %p \n", p_cell );
00432 #ifdef EXTRA_DEBUG
00433 if (p_cell->damocles==0) {
00434 LM_ERR("transaction %p not scheduled for deletion"
00435 " and called from DELETE timer\n",p_cell);
00436 abort();
00437 }
00438 #endif
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 delete_cell( p_cell, 0 );
00450 LM_DBG("done\n");
00451 }
00452
00453
00454
00455
00456 struct timer_table *get_timertable(void)
00457 {
00458 return timertable;
00459 }
00460
00461
00462 void unlink_timer_lists(void)
00463 {
00464 struct timer_link *tl, *end, *tmp;
00465 enum lists i;
00466
00467 if (timertable==0) return;
00468
00469 tl = timertable->timers[DELETE_LIST].first_tl.next_tl;
00470 end = & timertable->timers[DELETE_LIST].last_tl;
00471
00472 for( i=0; i<NR_OF_TIMER_LISTS ; i++ )
00473 reset_timer_list( i );
00474 LM_DBG("emptying DELETE list\n");
00475
00476
00477 while (tl!=end) {
00478 tmp=tl->next_tl;
00479 free_cell( get_dele_timer_payload(tl) );
00480 tl=tmp;
00481 }
00482
00483 }
00484
00485
00486
00487 struct timer_table *tm_init_timers(void)
00488 {
00489 enum lists i;
00490
00491 timertable=(struct timer_table *) shm_malloc(sizeof(struct timer_table));
00492 if (!timertable) {
00493 LM_ERR("no more share memory\n");
00494 goto error0;
00495 }
00496 memset(timertable, 0, sizeof (struct timer_table));
00497
00498
00499 if ( timer_id2timeout[FR_TIMER_LIST]<MIN_TIMER_VALUE ) {
00500 LM_ERR("FR_TIMER must be at least %d\n",
00501 MIN_TIMER_VALUE);
00502 goto error0;
00503 }
00504
00505 if ( timer_id2timeout[FR_INV_TIMER_LIST]<MIN_TIMER_VALUE ) {
00506 LM_ERR("FR_INV_TIMER must be at least %d\n",
00507 MIN_TIMER_VALUE);
00508 goto error0;
00509 }
00510
00511 if ( timer_id2timeout[WT_TIMER_LIST]<MIN_TIMER_VALUE ) {
00512 LM_ERR("WT_TIMER must be at least %d\n",
00513 MIN_TIMER_VALUE);
00514 goto error0;
00515 }
00516
00517 if ( timer_id2timeout[DELETE_LIST]<MIN_TIMER_VALUE ) {
00518 LM_ERR("DELETE_TIMER must be at least %d\n",
00519 MIN_TIMER_VALUE);
00520 goto error0;
00521 }
00522
00523 if ( timer_id2timeout[RT_T2]<=timer_id2timeout[RT_T1_TO_1] ) {
00524 LM_ERR("T2 must be greater than T1\n");
00525 goto error0;
00526 }
00527
00528
00529 timer_id2timeout[RT_T1_TO_1] *=1000;
00530 timer_id2timeout[RT_T2] *=1000;
00531
00532 if ( (timer_id2timeout[RT_T1_TO_1]<<1) < timer_id2timeout[RT_T2] )
00533 timer_id2timeout[RT_T1_TO_2] = timer_id2timeout[RT_T1_TO_1]<<1;
00534 else
00535 timer_id2timeout[RT_T1_TO_2] = timer_id2timeout[RT_T2];
00536
00537 if ( (timer_id2timeout[RT_T1_TO_1]<<2) < timer_id2timeout[RT_T2] )
00538 timer_id2timeout[RT_T1_TO_3] = timer_id2timeout[RT_T1_TO_1]<<2;
00539 else
00540 timer_id2timeout[RT_T1_TO_3] = timer_id2timeout[RT_T2];
00541
00542
00543
00544 for( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
00545 init_timer_list( i );
00546
00547
00548 timertable->timers[RT_T1_TO_1].id = RT_T1_TO_1;
00549 timertable->timers[RT_T1_TO_2].id = RT_T1_TO_2;
00550 timertable->timers[RT_T1_TO_3].id = RT_T1_TO_3;
00551 timertable->timers[RT_T2].id = RT_T2;
00552 timertable->timers[FR_TIMER_LIST].id = FR_TIMER_LIST;
00553 timertable->timers[FR_INV_TIMER_LIST].id = FR_INV_TIMER_LIST;
00554 timertable->timers[WT_TIMER_LIST].id = WT_TIMER_LIST;
00555 timertable->timers[DELETE_LIST].id = DELETE_LIST;
00556
00557 return timertable;
00558
00559 error0:
00560 return 0;
00561 }
00562
00563 void free_timer_table(void)
00564 {
00565 if (timertable)
00566 shm_free(timertable);
00567 }
00568
00569 void reset_timer_list( enum lists list_id)
00570 {
00571 timertable->timers[list_id].first_tl.next_tl =
00572 &(timertable->timers[list_id].last_tl );
00573 timertable->timers[list_id].last_tl.prev_tl =
00574 &(timertable->timers[list_id].first_tl );
00575 timertable->timers[list_id].first_tl.prev_tl =
00576 timertable->timers[list_id].last_tl.next_tl = NULL;
00577 timertable->timers[list_id].last_tl.time_out = -1;
00578 }
00579
00580
00581
00582
00583 void init_timer_list( enum lists list_id)
00584 {
00585 reset_timer_list( list_id );
00586 init_timerlist_lock( list_id );
00587 }
00588
00589
00590
00591
00592 void print_timer_list( enum lists list_id)
00593 {
00594 struct timer* timer_list=&(timertable->timers[ list_id ]);
00595 struct timer_link *tl ;
00596
00597 tl = timer_list->first_tl.next_tl;
00598 while (tl!=& timer_list->last_tl)
00599 {
00600 LM_DBG("[%d]: %p, next=%p \n",
00601 list_id, tl, tl->next_tl);
00602 tl = tl->next_tl;
00603 }
00604 }
00605
00606
00607
00608 #ifdef TM_TIMER_DEBUG
00609 static void check_timer_list(enum lists list_id, char *txt )
00610 {
00611 struct timer* timer_list=&(timertable->timers[ list_id ]);
00612 struct timer_link *tl ;
00613 struct timer_link *tl1 ;
00614
00615 if (list_id<0 || list_id>=NR_OF_TIMER_LISTS) {
00616 LM_CRIT("------- list [%d] bug [%s]\n",list_id, txt);
00617 abort();
00618 }
00619
00620 tl = timer_list->last_tl.prev_tl;
00621 while (tl!=&timer_list->first_tl) {
00622 if (tl->prev_tl==0) {
00623 LM_CRIT("------- list [%d] prev_tl==0 [%s]\n",list_id, txt);
00624 abort();
00625 }
00626 tl = tl->prev_tl;
00627 }
00628
00629 tl = timer_list->first_tl.next_tl;
00630 while (tl!=&timer_list->last_tl) {
00631 if (tl->next_tl==0) {
00632 LM_CRIT("------- list [%d] next_tl==0 [%s]\n",list_id, txt);
00633 abort();
00634 }
00635 tl = tl->next_tl;
00636 }
00637
00638 tl = timer_list->first_tl.next_tl;
00639 while (tl!=&timer_list->last_tl) {
00640 if (tl->ld_tl==0) {
00641 LM_CRIT("------- list [%d] currupted - ld=0 [%s]\n",list_id, txt);
00642 abort();
00643 }
00644 if (tl->ld_tl->ld_tl!=tl) {
00645 LM_CRIT("------- list [%d] currupted - ld cycle broken [%s]\n",
00646 list_id, txt);
00647 abort();
00648 }
00649
00650 if (tl->ld_tl!=tl) {
00651 tl1 = tl->next_tl;
00652 while(tl1!=tl->ld_tl) {
00653 if (tl1->ld_tl) {
00654 LM_CRIT("------- list [%d] currupted - ld!=0 inside "
00655 "cycle [%s]\n", list_id, txt);
00656 abort();
00657 }
00658 tl1 = tl1->next_tl;
00659 }
00660 }
00661
00662 tl = tl->ld_tl->next_tl;
00663 }
00664 }
00665 #endif
00666
00667
00668 static void remove_timer_unsafe( struct timer_link* tl )
00669 {
00670 #ifdef EXTRA_DEBUG
00671 if (tl && is_in_timer_list2(tl) &&
00672 tl->timer_list->last_tl.prev_tl==0) {
00673 LM_CRIT("Oh no, zero link in trailing timer element\n");
00674 abort();
00675 };
00676 #endif
00677 if (is_in_timer_list2( tl )) {
00678 #ifdef EXTRA_DEBUG
00679 LM_DBG("unlinking timer: tl=%p, timeout=%lld, group=%d\n",
00680 tl, tl->time_out, tl->tg);
00681 #endif
00682 #ifdef TM_TIMER_DEBUG
00683 check_timer_list( tl->timer_list->id, "before remove" );
00684 #endif
00685 if (tl->ld_tl && tl->ld_tl!=tl) {
00686 if (tl->time_out==tl->prev_tl->time_out) {
00687 tl->prev_tl->ld_tl = tl->ld_tl;
00688 tl->ld_tl->ld_tl = tl->prev_tl;
00689 } else {
00690 tl->next_tl->ld_tl = tl->ld_tl;
00691 tl->ld_tl->ld_tl = tl->next_tl;
00692 }
00693 }
00694 tl->prev_tl->next_tl = tl->next_tl;
00695 tl->next_tl->prev_tl = tl->prev_tl;
00696 #ifdef TM_TIMER_DEBUG
00697 check_timer_list( tl->timer_list->id, "after remove" );
00698 #endif
00699 tl->next_tl = 0;
00700 tl->prev_tl = 0;
00701 tl->ld_tl = 0;
00702 tl->timer_list = NULL;
00703 }
00704 }
00705
00706
00707
00708 static void insert_timer_unsafe( struct timer *timer_list,
00709 struct timer_link *tl, utime_t time_out )
00710 {
00711 struct timer_link* ptr;
00712
00713 tl->time_out = time_out;
00714 tl->timer_list = timer_list;
00715 tl->deleted = 0;
00716
00717 #ifdef TM_TIMER_DEBUG
00718 check_timer_list( timer_list->id, "before insert" );
00719 #endif
00720 ptr = timer_list->last_tl.prev_tl;
00721 for( ; ptr != &timer_list->first_tl ; ptr = ptr->ld_tl->prev_tl) {
00722 if ( ptr->time_out<=time_out )
00723 break;
00724 }
00725
00726
00727 tl->prev_tl = ptr;
00728 tl->next_tl = ptr->next_tl;
00729 tl->prev_tl->next_tl = tl;
00730 tl->next_tl->prev_tl = tl;
00731
00732 if (tl->time_out==ptr->time_out) {
00733 tl->ld_tl = ptr->ld_tl;
00734 ptr->ld_tl = 0;
00735 tl->ld_tl->ld_tl = tl;
00736 } else {
00737 tl->ld_tl = tl;
00738 }
00739 #ifdef TM_TIMER_DEBUG
00740 check_timer_list( timer_list->id, "after insert" );
00741 #endif
00742
00743 LM_DBG("[%d]: %p (%lld)\n",timer_list->id,
00744 tl,tl->time_out);
00745 }
00746
00747
00748
00749
00750 static struct timer_link *check_and_split_time_list( struct timer *timer_list,
00751 utime_t time )
00752 {
00753 struct timer_link *tl , *end, *ret;
00754
00755
00756
00757 if (timer_list->first_tl.next_tl==&timer_list->last_tl
00758 || (
00759 timer_list->first_tl.next_tl->time_out > time) )
00760 return NULL;
00761
00762
00763 lock(timer_list->mutex);
00764
00765 #ifdef TM_TIMER_DEBUG
00766 check_timer_list( timer_list->id, "before split" );
00767 #endif
00768 end = &timer_list->last_tl;
00769 tl = timer_list->first_tl.next_tl;
00770 while( tl!=end && tl->time_out <= time)
00771 tl=tl->ld_tl->next_tl;
00772
00773
00774 if (tl->prev_tl==&(timer_list->first_tl)) {
00775 ret = NULL;
00776 } else {
00777
00778 ret = timer_list->first_tl.next_tl;
00779
00780 tl->prev_tl->next_tl = NULL;
00781
00782 timer_list->first_tl.next_tl = tl;
00783 tl->prev_tl = & timer_list->first_tl;
00784
00785 for( tl=ret ; tl ; tl=tl->next_tl )
00786 tl->timer_list = DETACHED_LIST;
00787 }
00788 #ifdef TM_TIMER_DEBUG
00789 check_timer_list( timer_list->id, "after split" );
00790 #endif
00791
00792 #ifdef EXTRA_DEBUG
00793 if (timer_list->last_tl.prev_tl==0) {
00794 LM_CRIT("Oh no, zero link in trailing timer element\n");
00795 abort();
00796 };
00797 #endif
00798
00799
00800 unlock(timer_list->mutex);
00801
00802 return ret;
00803 }
00804
00805
00806
00807
00808
00809
00810
00811
00812 void reset_timer( struct timer_link* tl )
00813 {
00814
00815
00816
00817
00818
00819
00820 tl->deleted = 1;
00821 #ifdef EXTRA_DEBUG
00822 LM_DBG("(group %d, tl=%p)\n", tl->tg, tl );
00823 #endif
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void set_timer( struct timer_link *new_tl, enum lists list_id,
00838 utime_t* ext_timeout )
00839 {
00840 utime_t timeout;
00841 struct timer* list;
00842
00843 if (list_id>=NR_OF_TIMER_LISTS) {
00844 LM_CRIT("unknown list: %d\n", list_id);
00845 #ifdef EXTRA_DEBUG
00846 abort();
00847 #endif
00848 return;
00849 }
00850
00851 if (!ext_timeout) {
00852 timeout = timer_id2timeout[ list_id ];
00853 } else {
00854 timeout = *ext_timeout;
00855 }
00856 LM_DBG("relative timeout is %lld\n",timeout);
00857
00858 list= &(timertable->timers[ list_id ]);
00859
00860 lock(list->mutex);
00861
00862
00863
00864
00865 if (new_tl->timer_list==DETACHED_LIST){
00866 LM_CRIT("set_timer for %d list called on a \"detached\" "
00867 "timer -- ignoring: %p\n", list_id, new_tl);
00868 goto end;
00869 }
00870
00871 remove_timer_unsafe( new_tl );
00872
00873 insert_timer_unsafe( list, new_tl, timeout +
00874 ((timer_id2type[list_id]==UTIME_TYPE)?get_uticks():get_ticks()));
00875 end:
00876 unlock(list->mutex);
00877 }
00878
00879
00880
00881
00882
00883 void set_1timer( struct timer_link *new_tl, enum lists list_id,
00884 utime_t* ext_timeout )
00885 {
00886 utime_t timeout;
00887 struct timer* list;
00888
00889
00890 if (list_id>=NR_OF_TIMER_LISTS) {
00891 LM_CRIT("unknown list: %d\n", list_id);
00892 #ifdef EXTRA_DEBUG
00893 abort();
00894 #endif
00895 return;
00896 }
00897
00898 if (!ext_timeout) {
00899 timeout = timer_id2timeout[ list_id ];
00900 } else {
00901 timeout = *ext_timeout;
00902 }
00903
00904 list= &(timertable->timers[ list_id ]);
00905
00906 lock(list->mutex);
00907 if (!new_tl->time_out) {
00908 insert_timer_unsafe( list, new_tl, timeout +
00909 ((timer_id2type[list_id]==UTIME_TYPE)?get_uticks():get_ticks()));
00910 }
00911 unlock(list->mutex);
00912 }
00913
00914
00915
00916
00917
00918 static void unlink_timers( struct cell *t )
00919 {
00920 int i;
00921 int remove_fr, remove_retr;
00922
00923 remove_fr=0; remove_retr=0;
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 if (is_in_timer_list2(&t->uas.response.fr_timer)) remove_fr=1;
00935 else for (i=0; i<t->nr_of_outgoings; i++)
00936 if (is_in_timer_list2(&t->uac[i].request.fr_timer)
00937 || is_in_timer_list2(&t->uac[i].local_cancel.fr_timer)) {
00938 remove_fr=1;
00939 break;
00940 }
00941 if (is_in_timer_list2(&t->uas.response.retr_timer)) remove_retr=1;
00942 else for (i=0; i<t->nr_of_outgoings; i++)
00943 if (is_in_timer_list2(&t->uac[i].request.retr_timer)
00944 || is_in_timer_list2(&t->uac[i].local_cancel.retr_timer)) {
00945 remove_retr=1;
00946 break;
00947 }
00948
00949
00950 if (remove_retr) {
00951
00952
00953
00954 lock(timertable->timers[RT_T1_TO_1].mutex);
00955 remove_timer_unsafe(&t->uas.response.retr_timer);
00956 for (i=0; i<t->nr_of_outgoings; i++) {
00957 remove_timer_unsafe(&t->uac[i].request.retr_timer);
00958 remove_timer_unsafe(&t->uac[i].local_cancel.retr_timer);
00959 }
00960 unlock(timertable->timers[RT_T1_TO_1].mutex);
00961 }
00962 if (remove_fr) {
00963
00964
00965
00966 lock(timertable->timers[FR_TIMER_LIST].mutex);
00967 remove_timer_unsafe(&t->uas.response.fr_timer);
00968 for (i=0; i<t->nr_of_outgoings; i++) {
00969 remove_timer_unsafe(&t->uac[i].request.fr_timer);
00970 remove_timer_unsafe(&t->uac[i].local_cancel.fr_timer);
00971 }
00972 unlock(timertable->timers[FR_TIMER_LIST].mutex);
00973 }
00974 }
00975
00976
00977
00978
00979 #define run_handler_for_each( _tl , _handler ) \
00980 while ((_tl))\
00981 {\
00982 \
00983 tmp_tl = (_tl)->next_tl;\
00984 (_tl)->next_tl = (_tl)->prev_tl = 0;\
00985 LM_DBG("timer routine:%d,tl=%p next=%p, timeout=%lld\n",\
00986 id,(_tl),tmp_tl,(_tl)->time_out);\
00987 if ( !(_tl)->deleted ) \
00988 (_handler)( _tl );\
00989 (_tl) = tmp_tl;\
00990 }
00991
00992
00993
00994
00995 void timer_routine(unsigned int ticks , void * attr)
00996 {
00997 struct timer_link *tl, *tmp_tl;
00998 int id;
00999
01000 for( id=0 ; id<RT_T1_TO_1 ; id++ )
01001 {
01002
01003
01004 tl=check_and_split_time_list( &timertable->timers[ id ], ticks);
01005
01006 switch (id)
01007 {
01008 case FR_TIMER_LIST:
01009 case FR_INV_TIMER_LIST:
01010 run_handler_for_each(tl,final_response_handler);
01011 break;
01012 case WT_TIMER_LIST:
01013 run_handler_for_each(tl,wait_handler);
01014 break;
01015 case DELETE_LIST:
01016 run_handler_for_each(tl,delete_handler);
01017 break;
01018 }
01019 }
01020 }
01021
01022
01023
01024 void utimer_routine(utime_t uticks , void * attr)
01025 {
01026 struct timer_link *tl, *tmp_tl;
01027 int id;
01028
01029 for( id=RT_T1_TO_1 ; id<NR_OF_TIMER_LISTS ; id++ )
01030 {
01031
01032
01033 tl=check_and_split_time_list( &timertable->timers[ id ], uticks);
01034
01035 switch (id)
01036 {
01037 case RT_T1_TO_1:
01038 case RT_T1_TO_2:
01039 case RT_T1_TO_3:
01040 case RT_T2:
01041 run_handler_for_each(tl,retransmission_handler);
01042 break;
01043 }
01044 }
01045 }
01046