Browse code

timers fixed

Bogdan-Andrei Iancu authored on 10/12/2001 15:42:45
Showing 6 changed files
... ...
@@ -82,16 +82,6 @@ void free_hash_table( struct s_table *hash_table )
82 82
          }
83 83
       }
84 84
 
85
-      /* deletes all cells from DELETE_LIST list (they are no more accessible from enrys) */
86
-        lock( hash_table->timers[DELETE_LIST].mutex );
87
-        remove_delete_list( hash_table );
88
-        unlock( hash_table->timers[DELETE_LIST].mutex );
89
-
90
-      /*
91
-      while( (tl=remove_from_timer_list_from_head( hash_table, DELETE_LIST ))!=0 )
92
-         free_cell( p_cell ) ;
93
-      */
94
-
95 85
       /* the mutexs for sync the lists are released*/
96 86
       for ( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
97 87
          release_timerlist_lock( &(hash_table->timers[i]) );
... ...
@@ -31,29 +31,13 @@
31 31
 
32 32
 
33 33
 #define insert_into_timer(hash_table,new_tl,list_id,time_out) \
34
-	do{\
35
-		if ( is_in_timer_list((new_tl),(list_id))  )\
36
-			remove_from_timer_list( (hash_table) , (new_tl) ,\
37
-								(list_id));\
38
-			insert_into_timer_list((hash_table), (new_tl), (list_id),\
39
-								get_ticks()+(time_out));\
40
-	}while(0)
41
-
34
+	insert_into_timer_list(hash_table,new_tl,list_id,(get_ticks()+time_out))
42 35
 
43 36
 #define add_to_tail_of_timer(hash_table,new_tl,list_id,time_out) \
44
-	 do{\
45
-		if ( is_in_timer_list((new_tl), (list_id))  )\
46
-			remove_from_timer_list((hash_table), (new_tl), (list_id));\
47
-			add_to_tail_of_timer_list((hash_table), (new_tl), \
48
-								(list_id), get_ticks()+(time_out));\
49
-	}while(0)
50
-
37
+	add_to_tail_of_timer_list(hash_table,new_tl,list_id,(get_ticks()+time_out))
51 38
 
52 39
 #define remove_from_timer(hash_table,tl,list_id) \
53
-	 do{\
54
-		if ( !is_in_timer_list((tl), (list_id))  )\
55
-			remove_from_timer_list( (hash_table), (tl), (list_id));\
56
-	}while(0)
40
+	remove_from_timer_list( hash_table , tl , list_id)\
57 41
 
58 42
 
59 43
 
... ...
@@ -92,11 +76,22 @@ int tm_startup()
92 92
 
93 93
 void tm_shutdown()
94 94
 {
95
+    struct timer_link  *tl, *tmp;
95 96
     int i;
96 97
 
98
+    /*remember the DELETE LIST */
99
+    tl = hash_table->timers[DELETE_LIST].first_tl;
100
+
97 101
     /*unlink the lists*/
98 102
     for( i=NR_OF_TIMER_LISTS ; i>=0 ; i-- )
103
+    {
104
+       //lock( hash_table->timers[i].mutex );
99 105
        hash_table->timers[ i ].first_tl = hash_table->timers[ i ].last_tl = 0;
106
+       //unlock( hash_table->timers[i].mutex );
107
+    }
108
+
109
+    /* deletes all cells from DELETE_LIST list (they are no more accessible from enrys) */
110
+    for(   ;  tl  ;  tmp=tl->next_tl , free_cell((struct cell*)tl->payload) , tl=tmp );
100 111
 
101 112
     /* destroy the hash table */
102 113
     free_hash_table( hash_table );
... ...
@@ -192,7 +187,7 @@ int t_lookup_request( struct sip_msg* p_msg, char* foo, char* bar  )
192 192
    hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
193 193
    if ( p_msg->first_line.u.request.method_value==METHOD_ACK  )
194 194
       isACK = 1;
195
-   DBG("t_lookup_request: continue searching;  hash=%d, isACK=5d\n",hash_index,isACK);
195
+   DBG("t_lookup_request: continue searching;  hash=%d, isACK=%d\n",hash_index,isACK);
196 196
 
197 197
    /* all the transactions from the entry are compared */
198 198
    p_cell     = hash_table->entrys[hash_index].first_cell;
... ...
@@ -359,7 +354,7 @@ int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int
359 359
       memcpy( T->outbound_request[branch]->retr_buffer , buf , len );
360 360
       free( buf ) ; buf=NULL;
361 361
 
362
-      DBG("DEBUG: t_forward: starting timers (retrans and FR)\n");
362
+      DBG("DEBUG: t_forward: starting timers (retrans and FR) %d\n",get_ticks() );
363 363
       /*sets and starts the FINAL RESPONSE timer */
364 364
       insert_into_timer( hash_table , (&(T->outbound_request[branch]->tl[FR_TIMER_LIST])) , FR_TIMER_LIST, FR_TIME_OUT );
365 365
 
... ...
@@ -491,13 +486,13 @@ int t_on_reply_received( struct sip_msg  *p_msg )
491 491
 
492 492
    /* parse_headers( p_msg , HDR_EOH ); */ /*????*/
493 493
    /* this might be good enough -- is not like with
494
-      generating own responses where I have to 
494
+      generating own responses where I have to
495 495
       parse all vias to copy them
496 496
 
497 497
    /* if a reply received which has not all fields we might want to
498 498
       have for stateul forwarding, give the stateless router
499 499
       a chance for minimum routing
500
-   */ 
500
+   */
501 501
    if ( parse_headers(p_msg, HDR_VIA1|HDR_VIA2|HDR_TO|HDR_CSEQ )==-1 ||
502 502
         !p_msg->via1 || !p_msg->via2 || !p_msg->to || !p_msg->cseq )
503 503
 	return 1;
... ...
@@ -512,13 +507,10 @@ int t_on_reply_received( struct sip_msg  *p_msg )
512 512
 
513 513
    /* we were not able to process the response due to memory
514 514
       shortage; simply drop it; hopefuly, we will have more
515
-      memory on the next try
516
-   */
515
+      memory on the next try */
517 516
    relay = t_should_relay_response( T , p_msg->first_line.u.reply.statuscode );
518 517
    if (relay && !(clone=sip_msg_cloner( p_msg )))
519
-	return 0;
520
-
521
-
518
+     return 0;
522 519
 
523 520
    /* stop retransmission */
524 521
    remove_from_timer( hash_table , (&(T->outbound_request[branch]->tl[RETRASMISSIONS_LIST])) , RETRASMISSIONS_LIST );
... ...
@@ -541,7 +533,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
541 541
    #endif
542 542
 
543 543
    /* if the incoming response code is not reliable->drop it*/
544
-   if (!relay) 
544
+   if (!relay)
545 545
 	return 0;
546 546
 
547 547
    /* restart retransmission if provisional response came for a non_INVITE -> retrasmit at RT_T2*/
... ...
@@ -573,7 +565,7 @@ int t_on_reply_received( struct sip_msg  *p_msg )
573 573
    {
574 574
       if (push_reply_from_uac_to_uas( T , branch )==-1 && clone ) {
575 575
 	T->inbound_response[branch]=NULL;
576
- 	sip_msg_free( clone );	
576
+	sip_msg_free( clone );
577 577
 	return -1;
578 578
       }
579 579
    }
... ...
@@ -1397,8 +1389,9 @@ void wait_handler( void *attr)
1397 1397
 
1398 1398
    /* the transaction is already removed from WT_LIST by the timer */
1399 1399
    /* the cell is removed from the hash table */
1400
-   DBG("DEBUG: wait_handler : removing from table ans stopping all timers\n");
1400
+   DBG("DEBUG: wait_handler : removing from table \n");
1401 1401
    remove_from_hash_table( hash_table, p_cell );
1402
+   DBG("DEBUG: wait_handler : stopping all timers\n");
1402 1403
    stop_RETR_and_FR_timers(hash_table,p_cell) ;
1403 1404
    /* put it on DEL_LIST - sch for del */
1404 1405
     add_to_tail_of_timer( hash_table, (&(p_cell->dele_tl)), DELETE_LIST, DEL_TIME_OUT );
... ...
@@ -7,6 +7,32 @@
7 7
 #include "../../dprint.h"
8 8
 
9 9
 
10
+void remove_from_timer_list_dummy( struct s_table* hash_table , struct timer_link* tl , int list_id)
11
+{
12
+   struct timer* timer_list=&(hash_table->timers[ list_id ]);
13
+   DBG("DEBUG: remove_from_timer[%d]: %d, %p \n",list_id,tl->time_out,tl);
14
+
15
+   if ( tl->prev_tl )
16
+       tl->prev_tl->next_tl = tl->next_tl;
17
+    else
18
+         timer_list->first_tl = tl->next_tl;
19
+
20
+   if ( tl->next_tl )
21
+         tl->next_tl->prev_tl = tl->prev_tl;
22
+    else
23
+         timer_list->last_tl = tl->prev_tl;
24
+
25
+    tl->next_tl = 0;
26
+    tl->prev_tl = 0;
27
+}
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
10 36
 /* put a new cell into a list nr. list_id within a hash_table;
11 37
   * set initial timeout
12 38
   */
... ...
@@ -14,12 +40,18 @@ void add_to_tail_of_timer_list( struct s_table* hash_table , struct timer_link*
14 14
 {
15 15
    struct timer* timer_list = &(hash_table->timers[ list_id ]);
16 16
 
17
+   /* the entire timer list is locked now -- noone else can manipulate it */
18
+   lock( timer_list->mutex );
19
+
20
+   /* if the element is already in list->first remove it */
21
+   if ( is_in_timer_list( tl,list_id)  )
22
+      remove_from_timer_list_dummy( hash_table , tl , list_id);
23
+
17 24
    tl->time_out = time_out;
18 25
    tl->next_tl= 0;
19
-   DBG("DEBUG: add_to_tail_of_timer[%d]: %d, %p\n",list_id,tl->time_out,tl);
20 26
 
21
-   /* the entire timer list is locked now -- noone else can manipulate it */
22
-   lock( timer_list->mutex );
27
+   DBG("DEBUG: add_to_tail_of_timer[%d]: %d, %p\n",list_id,tl->time_out,tl);
28
+   /* link it into list */
23 29
    if (timer_list->last_tl)
24 30
    {
25 31
        tl->prev_tl=timer_list->last_tl;
... ...
@@ -44,29 +76,37 @@ void insert_into_timer_list( struct s_table* hash_table , struct timer_link* new
44 44
    struct timer          *timer_list = &(hash_table->timers[ list_id ]);
45 45
    struct timer_link  *tl;
46 46
 
47
-   new_tl->time_out = time_out ;
48
-   DBG("DEBUG: insert_into_timer[%d]: %d, %p\n",list_id,new_tl->time_out,new_tl);
47
+   /* the entire timer list is locked now -- noone else can manipulate it */
48
+   lock( timer_list->mutex );
49 49
 
50
+   /* if the element is already in list->first remove it */
51
+   if ( is_in_timer_list( new_tl,list_id)  )
52
+      remove_from_timer_list_dummy( hash_table , new_tl , list_id);
50 53
 
51
-       lock( timer_list->mutex );
52
-       for( tl=timer_list->first_tl ; tl && tl->time_out<new_tl->time_out ; 
53
-               tl=tl->next_tl );
54
-       if ( tl ) {
55
-               /* insert before tl*/
56
-               new_tl->prev_tl = tl->prev_tl;
57
-               tl->prev_tl = new_tl;
58
-       } else { /* at the end or empty list */
59
-               new_tl->prev_tl = timer_list->last_tl;
60
-               new_tl->next_tl = NULL;
61
-               timer_list->last_tl = new_tl;
62
-       }
63
-       if (new_tl->prev_tl ) 
64
-               new_tl->prev_tl->next_tl = new_tl;
65
-       else
66
-               timer_list->first_tl = new_tl;
67
-       new_tl->next_tl = new_tl;
68
-       unlock( timer_list->mutex );
54
+   new_tl->time_out = time_out ;
55
+   DBG("DEBUG: insert_into_timer[%d]: %d, %p\n",list_id,new_tl->time_out,new_tl);
56
+    /*seeks the position for insertion */
57
+   for( tl=timer_list->first_tl ; tl && tl->time_out<new_tl->time_out ; tl=tl->next_tl );
58
+
59
+   /* link it into list */
60
+    if ( tl )
61
+    {  /* insert before tl*/
62
+       new_tl->prev_tl = tl->prev_tl;
63
+       tl->prev_tl = new_tl;
64
+    }
65
+   else
66
+    {  /* at the end or empty list */
67
+       new_tl->prev_tl = timer_list->last_tl;
68
+       timer_list->last_tl = new_tl;
69
+    }
70
+    if (new_tl->prev_tl )
71
+       new_tl->prev_tl->next_tl = new_tl;
72
+    else
73
+       timer_list->first_tl = new_tl;
74
+    new_tl->next_tl = tl;
69 75
 
76
+   /* give the list lock away */
77
+    unlock( timer_list->mutex );
70 78
 }
71 79
 
72 80
 
... ...
@@ -76,49 +116,64 @@ void insert_into_timer_list( struct s_table* hash_table , struct timer_link* new
76 76
 */
77 77
 void remove_from_timer_list( struct s_table* hash_table , struct timer_link* tl , int list_id)
78 78
 {
79
-   struct timer* timers=&(hash_table->timers[ list_id ]);
80
-   DBG("DEBUG: remove_from_timer[%d]: %d, %p \n",list_id,tl->time_out,tl);
79
+   struct timer* timer_list=&(hash_table->timers[ list_id ]);
81 80
 
82
-      lock( timers->mutex );
83
-      if ( tl->prev_tl )
84
-         tl->prev_tl->next_tl = tl->next_tl;
85
-      else
86
-         timers->first_tl = tl->next_tl;
87
-      if ( tl->next_tl )
88
-         tl->next_tl->prev_tl = tl->prev_tl;
89
-      else
90
-         timers->last_tl = tl->prev_tl;
91
-      unlock( timers->mutex );
92
-      tl->next_tl = 0;
93
-      tl->prev_tl = 0;
81
+   /* the entire timer list is locked now -- noone else can manipulate it */
82
+   lock( timer_list->mutex );
83
+
84
+   /* if the element is already in list->first remove it */
85
+   if ( is_in_timer_list( tl,list_id)  )
86
+   {
87
+      remove_from_timer_list_dummy( hash_table , tl , list_id);
88
+   }
89
+
90
+   /* give the list lock away */
91
+   unlock( timer_list->mutex );
94 92
 }
95 93
 
96 94
 
97 95
 
98 96
 
99
-/* remove a cell from the head of  list nr. list_id within a hash_table;
97
+/*
100 98
 */
101
-struct timer_link  *remove_from_timer_list_from_head( struct s_table* hash_table, int list_id )
99
+struct timer_link  *check_and_split_time_list( struct s_table* hash_table, int list_id ,int time)
102 100
 {
103
-   struct timer* timers=&(hash_table->timers[ list_id ]);
104
-   struct timer_link *tl = timers->first_tl;
101
+   struct timer* timer_list=&(hash_table->timers[ list_id ]);
102
+   struct timer_link *tl ;
105 103
 
106
-   if  (tl)
107
-   {
108
-      DBG("DEBUG: remove_from_timer_head[%d]: %d , p=%p , next=%p\n",list_id,tl->time_out,tl,tl->next_tl);
109
-      lock( timers->mutex  );
110
-      timers->first_tl = tl->next_tl;
111
-      if (!timers->first_tl)
112
-         timers->last_tl=0;
113
-      else
114
-         tl->next_tl->prev_tl = 0;
115
-      unlock( timers->mutex );
116
-      tl->next_tl = 0;
117
-      tl->prev_tl = 0;
118
-   }
119
-   else
120
-      DBG("DEBUG: remove_from_timer_head[%d]: list is empty! nothing to remove!\n",list_id);
104
+   /* the entire timer list is locked now -- noone else can manipulate it */
105
+   lock( timer_list->mutex );
121 106
 
107
+   tl = timer_list->first_tl;
108
+   if ( !tl )
109
+      goto exit;
110
+
111
+   for(  ; tl && tl->time_out <= time ; tl = tl->next_tl );
112
+
113
+    /*if I don't have to remove anything*/
114
+    if ( tl==timer_list->first_tl )
115
+    {
116
+      tl =0;
117
+      goto exit;
118
+    }
119
+
120
+    /*if I have to remove everything*/
121
+    if (tl==0)
122
+    {
123
+      tl = timer_list->first_tl;
124
+      timer_list->first_tl = timer_list->last_tl = 0;
125
+     goto exit;
126
+    }
127
+
128
+    /*I have to split it somewhere in the middle */
129
+    tl->prev_tl->next_tl=0;
130
+    tl->prev_tl = 0;
131
+    timer_list->first_tl = tl;
132
+    tl = timer_list->first_tl;
133
+
134
+exit:
135
+   /* give the list lock away */
136
+   unlock( timer_list->mutex );
122 137
 
123 138
    return tl;
124 139
 }
... ...
@@ -129,30 +184,25 @@ struct timer_link  *remove_from_timer_list_from_head( struct s_table* hash_table
129 129
 
130 130
 void timer_routine(unsigned int ticks , void * attr)
131 131
 {
132
-   struct s_table      *hash_table = (struct s_table *)attr;
133
-   struct timer*         timers= hash_table->timers;
134
-   struct timer_link* tl;
132
+   struct s_table       *hash_table = (struct s_table *)attr;
133
+   struct timer*          timers= hash_table->timers;
134
+   struct timer_link  *tl, *tmp_tl;
135 135
    int                           id;
136 136
 
137 137
    DBG("%d\n", ticks);
138 138
 
139 139
    for( id=0 ; id<NR_OF_TIMER_LISTS ; id++ )
140
-         while ( timers[ id ].first_tl && timers[ id ].first_tl->time_out <= ticks )
141
-         {
142
-            tl = remove_from_timer_list_from_head( hash_table, id );
143
-            timers[id].timeout_handler( tl->payload );
144
-         }
140
+   {
141
+      tl = check_and_split_time_list( hash_table, id , ticks );
142
+      while (tl)
143
+      {
144
+         tmp_tl = tl->next_tl;
145
+         tl->next_tl = tl->prev_tl =0 ;
146
+         timers[id].timeout_handler( tl->payload );
147
+         tl = tmp_tl;
148
+      }
149
+   }
145 150
 }
146 151
 
147
-void remove_delete_list( struct s_table *hash_table )
148
-{
149
-        struct timer_link *tl;
150
-
151
-        /* lock( hash_table->timers[DELETE_LIST].mutex );*/
152
-        while( tl=remove_from_timer_list_from_head( hash_table, DELETE_LIST ) ) {
153
-                free_cell( (struct cell *) tl->payload );
154
-        }
155
-        /* unlock( hash_table->timers[DELETE_LIST].mutex ); */
156
-}
157 152
 
158 153
 
... ...
@@ -53,10 +53,7 @@ typedef struct timer_link
53 53
 void                        add_to_tail_of_timer_list( struct s_table* hash_table , struct timer_link * tl , int list_id, unsigned int time_out );
54 54
 void                        insert_into_timer_list( struct s_table* hash_table , struct timer_link* tl, int list_id , unsigned int time_out );
55 55
 void                        remove_from_timer_list( struct s_table* hash_table , struct timer_link* tl , int list_id);
56
-struct timer_link  *remove_from_timer_list_from_head( struct s_table* hash_table, int list_id );
57
-void                       timer_routine(unsigned int, void *);
58
-
59
-void remove_delete_list( struct s_table *hash_table );
56
+void                        timer_routine(unsigned int, void *);
60 57
 
61 58
 
62 59
 #endif
... ...
@@ -162,17 +162,9 @@ char* via_builder( struct sip_msg *msg , unsigned int *len )
162 162
 				src[3]= msg->first_line.u.request.uri;
163 163
 				src[4]= get_cseq( msg )->number;
164 164
 				MDStringArray ( line_buf+via_len-1, src, 5 );
165
-				/*DBG("DEBUG: build_req_buf_from_sip_req: branch loop "
166
-				/		"detection: %s, %s, %s, %s, %s -> %s32\n",
167
-					msg->from->body.s, msg->to->body.s, msg->callid->body.s,
168
-					msg->first_line.u.request.uri.s,
169
-					((struct cseq_body *)(msg->cseq->parsed))->number.s,
170
-					line_buf+via_len-1 );
171
-				DBG("WARNING: build_req_buf_from_sip_req: branch computation "
172
-						"NOT over canonical values\n");*/
173 165
 				via_len+=MD5_LEN - 1;
174 166
 
175
-			} else DBG("DEBUG: build_req_buf_from_sip_req: required HFs for "
167
+			} else DBG("DEBUG: via_builder: required HFs for "
176 168
 					"loop checking missing\n");
177 169
 		}
178 170
 		//DBG("DEBUG: XXX will add branch now: %s (%d)\n", msg->add_to_branch_s, msg->add_to_branch_len );
... ...
@@ -185,7 +177,7 @@ char* via_builder( struct sip_msg *msg , unsigned int *len )
185 185
 		via_len+=CRLF_LEN;
186 186
 		line_buf[via_len]=0; /* null terminate the string*/
187 187
 	}else{
188
-		LOG(L_ERR, "build_req_buf_from_sip_req: ERROR: via too long (%d)\n",
188
+		LOG(L_ERR, " ERROR: via_builder: via too long (%d)\n",
189 189
 				via_len);
190 190
 		goto error;
191 191
 	}
... ...
@@ -11,20 +11,17 @@
11 11
 #include "msg_parser.h"
12 12
 
13 13
 char * build_req_buf_from_sip_req (	struct sip_msg* msg, 
14
-									unsigned int *returned_len);
14
+				unsigned int *returned_len);
15 15
 
16 16
 char * build_res_buf_from_sip_res(	struct sip_msg* msg,
17
-									unsigned int *returned_len);
17
+				unsigned int *returned_len);
18 18
 
19 19
 char * build_res_buf_from_sip_req(	unsigned int code , 
20
-									char *text ,
21
-									struct sip_msg* msg,
22
-									unsigned int *returned_len);
23
-char* via_builder( struct sip_msg *msg ,
24
-									unsigned int *len );
25
-
26
-
27
-char* via_builder( struct sip_msg *msg , unsigned int *len );
20
+				char *text ,
21
+				struct sip_msg* msg,
22
+				unsigned int *returned_len);
23
+char* via_builder( 			struct sip_msg *msg ,
24
+				unsigned int *len );
28 25
 
29 26
 
30 27
 #endif