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 76
 
93 77
 void tm_shutdown()
94 78
 {
79
+    struct timer_link  *tl, *tmp;
95 80
     int i;
96 81
 
82
+    /*remember the DELETE LIST */
83
+    tl = hash_table->timers[DELETE_LIST].first_tl;
84
+
97 85
     /*unlink the lists*/
98 86
     for( i=NR_OF_TIMER_LISTS ; i>=0 ; i-- )
87
+    {
88
+       //lock( hash_table->timers[i].mutex );
99 89
        hash_table->timers[ i ].first_tl = hash_table->timers[ i ].last_tl = 0;
90
+       //unlock( hash_table->timers[i].mutex );
91
+    }
92
+
93
+    /* deletes all cells from DELETE_LIST list (they are no more accessible from enrys) */
94
+    for(   ;  tl  ;  tmp=tl->next_tl , free_cell((struct cell*)tl->payload) , tl=tmp );
100 95
 
101 96
     /* destroy the hash table */
102 97
     free_hash_table( hash_table );
... ...
@@ -192,7 +187,7 @@ int t_lookup_request( struct sip_msg* p_msg, char* foo, char* bar  )
192 187
    hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
193 188
    if ( p_msg->first_line.u.request.method_value==METHOD_ACK  )
194 189
       isACK = 1;
195
-   DBG("t_lookup_request: continue searching;  hash=%d, isACK=5d\n",hash_index,isACK);
190
+   DBG("t_lookup_request: continue searching;  hash=%d, isACK=%d\n",hash_index,isACK);
196 191
 
197 192
    /* all the transactions from the entry are compared */
198 193
    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 354
       memcpy( T->outbound_request[branch]->retr_buffer , buf , len );
360 355
       free( buf ) ; buf=NULL;
361 356
 
362
-      DBG("DEBUG: t_forward: starting timers (retrans and FR)\n");
357
+      DBG("DEBUG: t_forward: starting timers (retrans and FR) %d\n",get_ticks() );
363 358
       /*sets and starts the FINAL RESPONSE timer */
364 359
       insert_into_timer( hash_table , (&(T->outbound_request[branch]->tl[FR_TIMER_LIST])) , FR_TIMER_LIST, FR_TIME_OUT );
365 360
 
... ...
@@ -491,13 +486,13 @@ int t_on_reply_received( struct sip_msg  *p_msg )
491 486
 
492 487
    /* parse_headers( p_msg , HDR_EOH ); */ /*????*/
493 488
    /* this might be good enough -- is not like with
494
-      generating own responses where I have to 
489
+      generating own responses where I have to
495 490
       parse all vias to copy them
496 491
 
497 492
    /* if a reply received which has not all fields we might want to
498 493
       have for stateul forwarding, give the stateless router
499 494
       a chance for minimum routing
500
-   */ 
495
+   */
501 496
    if ( parse_headers(p_msg, HDR_VIA1|HDR_VIA2|HDR_TO|HDR_CSEQ )==-1 ||
502 497
         !p_msg->via1 || !p_msg->via2 || !p_msg->to || !p_msg->cseq )
503 498
 	return 1;
... ...
@@ -512,13 +507,10 @@ int t_on_reply_received( struct sip_msg  *p_msg )
512 507
 
513 508
    /* we were not able to process the response due to memory
514 509
       shortage; simply drop it; hopefuly, we will have more
515
-      memory on the next try
516
-   */
510
+      memory on the next try */
517 511
    relay = t_should_relay_response( T , p_msg->first_line.u.reply.statuscode );
518 512
    if (relay && !(clone=sip_msg_cloner( p_msg )))
519
-	return 0;
520
-
521
-
513
+     return 0;
522 514
 
523 515
    /* stop retransmission */
524 516
    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 533
    #endif
542 534
 
543 535
    /* if the incoming response code is not reliable->drop it*/
544
-   if (!relay) 
536
+   if (!relay)
545 537
 	return 0;
546 538
 
547 539
    /* 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 565
    {
574 566
       if (push_reply_from_uac_to_uas( T , branch )==-1 && clone ) {
575 567
 	T->inbound_response[branch]=NULL;
576
- 	sip_msg_free( clone );	
568
+	sip_msg_free( clone );
577 569
 	return -1;
578 570
       }
579 571
    }
... ...
@@ -1397,8 +1389,9 @@ void wait_handler( void *attr)
1397 1389
 
1398 1390
    /* the transaction is already removed from WT_LIST by the timer */
1399 1391
    /* the cell is removed from the hash table */
1400
-   DBG("DEBUG: wait_handler : removing from table ans stopping all timers\n");
1392
+   DBG("DEBUG: wait_handler : removing from table \n");
1401 1393
    remove_from_hash_table( hash_table, p_cell );
1394
+   DBG("DEBUG: wait_handler : stopping all timers\n");
1402 1395
    stop_RETR_and_FR_timers(hash_table,p_cell) ;
1403 1396
    /* put it on DEL_LIST - sch for del */
1404 1397
     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 40
 {
15 41
    struct timer* timer_list = &(hash_table->timers[ list_id ]);
16 42
 
43
+   /* the entire timer list is locked now -- noone else can manipulate it */
44
+   lock( timer_list->mutex );
45
+
46
+   /* if the element is already in list->first remove it */
47
+   if ( is_in_timer_list( tl,list_id)  )
48
+      remove_from_timer_list_dummy( hash_table , tl , list_id);
49
+
17 50
    tl->time_out = time_out;
18 51
    tl->next_tl= 0;
19
-   DBG("DEBUG: add_to_tail_of_timer[%d]: %d, %p\n",list_id,tl->time_out,tl);
20 52
 
21
-   /* the entire timer list is locked now -- noone else can manipulate it */
22
-   lock( timer_list->mutex );
53
+   DBG("DEBUG: add_to_tail_of_timer[%d]: %d, %p\n",list_id,tl->time_out,tl);
54
+   /* link it into list */
23 55
    if (timer_list->last_tl)
24 56
    {
25 57
        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 76
    struct timer          *timer_list = &(hash_table->timers[ list_id ]);
45 77
    struct timer_link  *tl;
46 78
 
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);
79
+   /* the entire timer list is locked now -- noone else can manipulate it */
80
+   lock( timer_list->mutex );
49 81
 
82
+   /* if the element is already in list->first remove it */
83
+   if ( is_in_timer_list( new_tl,list_id)  )
84
+      remove_from_timer_list_dummy( hash_table , new_tl , list_id);
50 85
 
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 );
86
+   new_tl->time_out = time_out ;
87
+   DBG("DEBUG: insert_into_timer[%d]: %d, %p\n",list_id,new_tl->time_out,new_tl);
88
+    /*seeks the position for insertion */
89
+   for( tl=timer_list->first_tl ; tl && tl->time_out<new_tl->time_out ; tl=tl->next_tl );
90
+
91
+   /* link it into list */
92
+    if ( tl )
93
+    {  /* insert before tl*/
94
+       new_tl->prev_tl = tl->prev_tl;
95
+       tl->prev_tl = new_tl;
96
+    }
97
+   else
98
+    {  /* at the end or empty list */
99
+       new_tl->prev_tl = timer_list->last_tl;
100
+       timer_list->last_tl = new_tl;
101
+    }
102
+    if (new_tl->prev_tl )
103
+       new_tl->prev_tl->next_tl = new_tl;
104
+    else
105
+       timer_list->first_tl = new_tl;
106
+    new_tl->next_tl = tl;
69 107
 
108
+   /* give the list lock away */
109
+    unlock( timer_list->mutex );
70 110
 }
71 111
 
72 112
 
... ...
@@ -76,49 +116,64 @@ void insert_into_timer_list( struct s_table* hash_table , struct timer_link* new
76 116
 */
77 117
 void remove_from_timer_list( struct s_table* hash_table , struct timer_link* tl , int list_id)
78 118
 {
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);
119
+   struct timer* timer_list=&(hash_table->timers[ list_id ]);
81 120
 
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;
121
+   /* the entire timer list is locked now -- noone else can manipulate it */
122
+   lock( timer_list->mutex );
123
+
124
+   /* if the element is already in list->first remove it */
125
+   if ( is_in_timer_list( tl,list_id)  )
126
+   {
127
+      remove_from_timer_list_dummy( hash_table , tl , list_id);
128
+   }
129
+
130
+   /* give the list lock away */
131
+   unlock( timer_list->mutex );
94 132
 }
95 133
 
96 134
 
97 135
 
98 136
 
99
-/* remove a cell from the head of  list nr. list_id within a hash_table;
137
+/*
100 138
 */
101
-struct timer_link  *remove_from_timer_list_from_head( struct s_table* hash_table, int list_id )
139
+struct timer_link  *check_and_split_time_list( struct s_table* hash_table, int list_id ,int time)
102 140
 {
103
-   struct timer* timers=&(hash_table->timers[ list_id ]);
104
-   struct timer_link *tl = timers->first_tl;
141
+   struct timer* timer_list=&(hash_table->timers[ list_id ]);
142
+   struct timer_link *tl ;
105 143
 
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);
144
+   /* the entire timer list is locked now -- noone else can manipulate it */
145
+   lock( timer_list->mutex );
121 146
 
147
+   tl = timer_list->first_tl;
148
+   if ( !tl )
149
+      goto exit;
150
+
151
+   for(  ; tl && tl->time_out <= time ; tl = tl->next_tl );
152
+
153
+    /*if I don't have to remove anything*/
154
+    if ( tl==timer_list->first_tl )
155
+    {
156
+      tl =0;
157
+      goto exit;
158
+    }
159
+
160
+    /*if I have to remove everything*/
161
+    if (tl==0)
162
+    {
163
+      tl = timer_list->first_tl;
164
+      timer_list->first_tl = timer_list->last_tl = 0;
165
+     goto exit;
166
+    }
167
+
168
+    /*I have to split it somewhere in the middle */
169
+    tl->prev_tl->next_tl=0;
170
+    tl->prev_tl = 0;
171
+    timer_list->first_tl = tl;
172
+    tl = timer_list->first_tl;
173
+
174
+exit:
175
+   /* give the list lock away */
176
+   unlock( timer_list->mutex );
122 177
 
123 178
    return tl;
124 179
 }
... ...
@@ -129,30 +184,25 @@ struct timer_link  *remove_from_timer_list_from_head( struct s_table* hash_table
129 184
 
130 185
 void timer_routine(unsigned int ticks , void * attr)
131 186
 {
132
-   struct s_table      *hash_table = (struct s_table *)attr;
133
-   struct timer*         timers= hash_table->timers;
134
-   struct timer_link* tl;
187
+   struct s_table       *hash_table = (struct s_table *)attr;
188
+   struct timer*          timers= hash_table->timers;
189
+   struct timer_link  *tl, *tmp_tl;
135 190
    int                           id;
136 191
 
137 192
    DBG("%d\n", ticks);
138 193
 
139 194
    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
-         }
195
+   {
196
+      tl = check_and_split_time_list( hash_table, id , ticks );
197
+      while (tl)
198
+      {
199
+         tmp_tl = tl->next_tl;
200
+         tl->next_tl = tl->prev_tl =0 ;
201
+         timers[id].timeout_handler( tl->payload );
202
+         tl = tmp_tl;
203
+      }
204
+   }
145 205
 }
146 206
 
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 207
 
158 208
 
... ...
@@ -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 177
 		via_len+=CRLF_LEN;
186 178
 		line_buf[via_len]=0; /* null terminate the string*/
187 179
 	}else{
188
-		LOG(L_ERR, "build_req_buf_from_sip_req: ERROR: via too long (%d)\n",
180
+		LOG(L_ERR, " ERROR: via_builder: via too long (%d)\n",
189 181
 				via_len);
190 182
 		goto error;
191 183
 	}
... ...
@@ -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