Browse code

timeout handler added; minor, but many changes to t-functions

Bogdan-Andrei Iancu authored on 28/11/2001 15:04:42
Showing 4 changed files
... ...
@@ -6,9 +6,7 @@
6 6
 #ifdef THREADS
7 7
 #include <pthread.h>
8 8
 #endif
9
-#include <sys/types.h>
10
-#include <sys/ipc.h>
11
-#include <sys/socket.h>
9
+#include <arpa/inet.h>
12 10
 
13 11
 #include "../../msg_parser.h"
14 12
 
... ...
@@ -50,10 +48,13 @@ typedef struct retrans_buff
50 48
    unsigned int dest_ip;
51 49
    unsigned int dest_port;
52 50
 
53
-   struct sockaddr *to;
51
+   struct sockaddr_in to;
54 52
    socklen_t tolen;
55 53
    /* a message can be linked just to one retransmission list */
56 54
    struct timer_link tl[1];
55
+   unsigned int nr_retrans;
56
+   unsigned int max_retrans;
57
+   unsigned int timeout;
57 58
 }retrans_buff_type;
58 59
 
59 60
 
... ...
@@ -1,22 +1,61 @@
1 1
 #include "t_funcs.h"
2 2
 
3
-struct cell      *T;
4
-unsigned int  global_msg_id;
3
+struct cell         *T;
4
+unsigned int     global_msg_id;
5 5
 struct s_table*  hash_table;
6
+int                      sock_fd;
6 7
 
7 8
 struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg );
8
-
9 9
 int t_reply_matching( struct s_table* , struct sip_msg* , struct cell** , unsigned int*  );
10 10
 int t_store_incoming_reply( struct cell* , unsigned int , struct sip_msg* );
11 11
 int t_relay_reply( struct cell* , unsigned int , struct sip_msg* );
12 12
 int t_check( struct s_table* , struct sip_msg*  );
13 13
 int t_all_final( struct cell * );
14
+int t_cancel_branch(unsigned int branch);
14 15
 int relay_lowest_reply_upstream( struct cell *Trans , struct sip_msg *p_msg );
15 16
 int push_reply_from_uac_to_uas( struct sip_msg * , unsigned int );
16 17
 
17
-void del_Transaction( struct s_table *hash_table , struct cell * p_cell );
18
-void start_FR_timer( struct s_table* hash_table, struct cell* p_cell );
19
-void start_WT_timer( struct s_table* hash_table, struct cell* p_cell );
18
+int send_udp_to( char *buf, unsigned buflen, struct sockaddr_in*  to, unsigned tolen );
19
+
20
+void retransmission_handler( void *);
21
+void final_response_handler( void *);
22
+void wait_handler( void *);
23
+void delete_handler( void *);
24
+
25
+
26
+
27
+
28
+
29
+int tm_startup()
30
+{
31
+   /* building the hash table*/
32
+   hash_table = init_hash_table();
33
+   if (!hash_table)
34
+      return -1;
35
+
36
+   /* installing handlers for timers */
37
+   hash_table->timers[RETRASMISSIONS_LIST].timeout_handler = retransmission_handler;
38
+   hash_table->timers[FR_TIMER_LIST].timeout_handler              = final_response_handler;
39
+   hash_table->timers[WT_TIMER_LIST].timeout_handler             = wait_handler;
40
+   hash_table->timers[DELETE_LIST].timeout_handler                 = delete_handler;
41
+
42
+    /* creating socket for forwarding and retransmision*/
43
+    if ( (sock_fd=socket(AF_INET, SOCK_DGRAM,0))<0 )
44
+       return -1;
45
+
46
+   return 0;
47
+}
48
+
49
+
50
+
51
+
52
+int tm_shutdown()
53
+{
54
+    /* destroy the hash table */
55
+    free_hash_table( hash_table );
56
+
57
+   return 0;
58
+}
20 59
 
21 60
 
22 61
 
... ...
@@ -26,7 +65,7 @@ void start_WT_timer( struct s_table* hash_table, struct cell* p_cell );
26 65
  *      -1 - retransmission
27 66
  *      -2 - error
28 67
  */
29
-int t_add_transaction( struct s_table* hash_table , struct sip_msg* p_msg )
68
+int t_add_transaction( struct sip_msg* p_msg )
30 69
 {
31 70
    struct cell*    new_cell;
32 71
 
... ...
@@ -40,7 +79,7 @@ int t_add_transaction( struct s_table* hash_table , struct sip_msg* p_msg )
40 79
     /* if the transaction is not found yet we are tring to look for it*/
41 80
    if ( (int)T==-1 )
42 81
       /* if the lookup's result is not 0 means that it's a retransmission */
43
-      if ( t_lookup_request( hash_table , p_msg ) )
82
+      if ( t_lookup_request( p_msg ) )
44 83
          return -1;
45 84
 
46 85
    /* creates a new transaction */
... ...
@@ -54,11 +93,13 @@ int t_add_transaction( struct s_table* hash_table , struct sip_msg* p_msg )
54 93
 }
55 94
 
56 95
 
96
+
97
+
57 98
 /* function returns:
58 99
  *       0 - transaction wasn't found
59 100
  *       1 - transaction found
60 101
  */
61
-int t_lookup_request(  struct s_table* hash_table , struct sip_msg* p_msg )
102
+int t_lookup_request( struct sip_msg* p_msg )
62 103
 {
63 104
    struct cell      *p_cell;
64 105
    struct cell      *tmp_cell;
... ...
@@ -99,20 +140,18 @@ int t_lookup_request(  struct s_table* hash_table , struct sip_msg* p_msg )
99 140
          /* first only the length are checked */
100 141
          if ( /*from length*/ p_cell->inbound_request->from->body.len == p_msg->from->body.len )
101 142
             if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
102
-                //if ( /*tag length*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && p_cell->inbound_request->tag->body.len == p_msg->tag->body.len) )
103
-                  if ( /*callid length*/ p_cell->inbound_request->callid->body.len == p_msg->callid->body.len )
104
-                     if ( /*cseq length*/ p_cell->inbound_request->cseq->body.len == p_msg->cseq->body.len )
105
-                            /* so far the lengths are the same -> let's check the contents */
106
-                            if ( /*from*/ !memcmp( p_cell->inbound_request->from->body.s , p_msg->from->body.s , p_msg->from->body.len ) )
107
-                               if ( /*to*/ !memcmp( p_cell->inbound_request->to->body.s , p_msg->to->body.s , p_msg->to->body.len)  )
108
-                                  //if ( /*tag*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && !memcmp( p_cell->inbound_request->tag->body.s , p_msg->tag->body.s , p_msg->tag->body.len )) )
109
-                                     if ( /*callid*/ !memcmp( p_cell->inbound_request->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
110
-                                        if ( /*cseq*/ !memcmp( p_cell->inbound_request->cseq->body.s , p_msg->cseq->body.s , p_msg->cseq->body.len ) )
111
-                                              { /* WE FOUND THE GOLDEN EGG !!!! */
112
-                                                 T = p_cell;
113
-                                                 unref_transaction ( p_cell );
114
-                                                 return 1;
115
-                                              }
143
+               if ( /*callid length*/ p_cell->inbound_request->callid->body.len == p_msg->callid->body.len )
144
+                  if ( /*cseq length*/ p_cell->inbound_request->cseq->body.len == p_msg->cseq->body.len )
145
+                     /* so far the lengths are the same -> let's check the contents */
146
+                        if ( /*from*/ !memcmp( p_cell->inbound_request->from->body.s , p_msg->from->body.s , p_msg->from->body.len ) )
147
+                           if ( /*to*/ !memcmp( p_cell->inbound_request->to->body.s , p_msg->to->body.s , p_msg->to->body.len)  )
148
+                               if ( /*callid*/ !memcmp( p_cell->inbound_request->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
149
+                                  if ( /*cseq*/ !memcmp( p_cell->inbound_request->cseq->body.s , p_msg->cseq->body.s , p_msg->cseq->body.len ) )
150
+                                     { /* WE FOUND THE GOLDEN EGG !!!! */
151
+                                        T = p_cell;
152
+                                        unref_transaction ( p_cell );
153
+                                        return 1;
154
+                                     }
116 155
       }
117 156
       else
118 157
       { /* it's a ACK request*/
... ...
@@ -121,7 +160,7 @@ int t_lookup_request(  struct s_table* hash_table , struct sip_msg* p_msg )
121 160
             if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
122 161
                if ( /*callid length*/ p_cell->inbound_request->callid->body.len == p_msg->callid->body.len )
123 162
                   if ( /*cseq_nr length*/ get_cseq(p_cell->inbound_request)->number.len == get_cseq(p_msg)->number.len )
124
-                      if ( /*cseq_method length*/ get_cseq(p_cell->inbound_request)->method.len == 6 /*INVITE*/ )
163
+                      if ( /*cseq_method type*/ p_cell->inbound_request->first_line.u.request.method_value == METHOD_INVITE  )
125 164
                          //if ( /*tag length*/ p_cell->tag &&  p_cell->tag->len==p_msg->tag->body.len )
126 165
                             /* so far the lengths are the same -> let's check the contents */
127 166
                             if ( /*from*/ !memcmp( p_cell->inbound_request->from->body.s , p_msg->from->body.s , p_msg->from->body.len ) )
... ...
@@ -129,12 +168,11 @@ int t_lookup_request(  struct s_table* hash_table , struct sip_msg* p_msg )
129 168
                                   //if ( /*tag*/ !memcmp( p_cell->tag->s , p_msg->tag->body.s , p_msg->tag->body.len ) )
130 169
                                      if ( /*callid*/ !memcmp( p_cell->inbound_request->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
131 170
                                         if ( /*cseq_nr*/ !memcmp( get_cseq(p_cell->inbound_request)->number.s , get_cseq(p_msg)->number.s , get_cseq(p_msg)->number.len ) )
132
-                                           if ( /*cseq_method*/ !memcmp( get_cseq(p_cell->inbound_request)->method.s , "INVITE" , 6 ) )
133
-                                              { /* WE FOUND THE GOLDEN EGG !!!! */
134
-                                                 T = p_cell;
135
-                                                 unref_transaction ( p_cell );
136
-                                                 return 1;
137
-                                              }
171
+                                           { /* WE FOUND THE GOLDEN EGG !!!! */
172
+                                              T = p_cell;
173
+                                              unref_transaction ( p_cell );
174
+                                               return 1;
175
+                                           }
138 176
       } /* end if is ACK or not*/
139 177
       /* next transaction */
140 178
       tmp_cell = p_cell;
... ...
@@ -151,72 +189,12 @@ int t_lookup_request(  struct s_table* hash_table , struct sip_msg* p_msg )
151 189
 
152 190
 
153 191
 
154
-/* function returns:
155
- *       0 - transaction wasn't found
156
- *       T - transaction found
157
- */
158
-struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg )
159
-{
160
-   struct cell      *p_cell;
161
-   struct cell      *tmp_cell;
162
-   unsigned int  hash_index=0;
163
-
164
-   /* it's a CANCEL request for sure */
165
-
166
-   /* start searching into the table */
167
-   hash_index = hash( p_msg->callid , get_cseq(p_msg)->number  ) ;
168
-
169
-   /* all the transactions from the entry are compared */
170
-   p_cell     = hash_table->entrys[hash_index].first_cell;
171
-   tmp_cell = 0;
172
-   while( p_cell )
173
-   {
174
-      /* the transaction is referenceted for reading */
175
-      ref_transaction( p_cell );
176
-
177
-      /* is it the wanted transaction ? */
178
-      /* first only the length are checked */
179
-      if ( /*from length*/ p_cell->inbound_request->from->body.len == p_msg->from->body.len )
180
-         if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
181
-            //if ( /*tag length*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && p_cell->inbound_request->tag->body.len == p_msg->tag->body.len) )
182
-               if ( /*callid length*/ p_cell->inbound_request->callid->body.len == p_msg->callid->body.len )
183
-                  if ( /*cseq_nr length*/ get_cseq(p_cell->inbound_request)->number.len == get_cseq(p_msg)->number.len )
184
-                      //if ( /*cseq_method length*/ p_cell->inbound_request->cseq_method->body.len != 6 /*CANCEL*/ )
185
-                         if ( /*req_uri length*/ p_cell->inbound_request->first_line.u.request.uri.len == p_msg->first_line.u.request.uri.len )
186
-                             /* so far the lengths are the same -> let's check the contents */
187
-                             if ( /*from*/ !memcmp( p_cell->inbound_request->from->body.s , p_msg->from->body.s , p_msg->from->body.len ) )
188
-                                if ( /*to*/ !memcmp( p_cell->inbound_request->to->body.s , p_msg->to->body.s , p_msg->to->body.len)  )
189
-                                   //if ( /*tag*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && !memcmp( p_cell->inbound_request->tag->body.s , p_msg->tag->body.s , p_msg->tag->body.len )) )
190
-                                      if ( /*callid*/ !memcmp( p_cell->inbound_request->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
191
-                                          if ( /*cseq_nr*/ !memcmp( get_cseq(p_cell->inbound_request)->number.s , get_cseq(p_msg)->number.s , get_cseq(p_msg)->number.len ) )
192
-                                             if ( /*cseq_method*/ strcmp( get_cseq(p_cell->inbound_request)->method.s , "CANCEL" ) )
193
-                                                if ( /*req_uri*/ memcmp( p_cell->inbound_request->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.len ) )
194
-                                                { /* WE FOUND THE GOLDEN EGG !!!! */
195
-                                                   unref_transaction ( p_cell );
196
-                                                   return p_cell;
197
-                                                }
198
-      /* next transaction */
199
-      tmp_cell = p_cell;
200
-      p_cell = p_cell->next_cell;
201
-
202
-      /* the transaction is dereferenceted */
203
-      unref_transaction ( tmp_cell );
204
-   }
205
-
206
-   /* no transaction found */
207
-   T = 0;
208
-   return 0;
209
-
210
-
211
-   return 0;
212
-}
213
-
214 192
 
215 193
 /* function returns:
216 194
  *       0 - forward successfull
217 195
  *      -1 - error during forward
218 196
  */
219
-int t_forward( struct s_table* hash_table , struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int dest_port_param )
197
+int t_forward( struct sip_msg* p_msg , unsigned int dest_ip_param , unsigned int dest_port_param )
220 198
 {
221 199
    /* it's about the same transaction or not? */
222 200
    if ( global_msg_id != p_msg->id )
... ...
@@ -227,14 +205,14 @@ int t_forward( struct s_table* hash_table , struct sip_msg* p_msg , unsigned int
227 205
 
228 206
    /* if  T hasn't been previous searched -> search for it */
229 207
    if ( (int)T !=-1 )
230
-      t_lookup_request( hash_table , p_msg );
208
+      t_lookup_request( p_msg );
231 209
 
232 210
    /*if T hasn't been found after all -> return not found (error) */
233 211
    if ( !T )
234 212
       return -1;
235 213
 
236 214
    /*if it's an ACK and the status is not final or is final, but error the ACK is not forwarded*/
237
-   if ( !memcmp(p_msg->first_line.u.request.method.s,"ACK",3) && (T->status/100)!=2 )
215
+   if ( p_msg->first_line.u.request.method_value==METHOD_ACK  && (T->status/100)!=2 )
238 216
       return 0;
239 217
 
240 218
    /* if it's forwarded for the first time ; else the request is retransmited from the transaction buffer */
... ...
@@ -247,6 +225,7 @@ int t_forward( struct s_table* hash_table , struct sip_msg* p_msg , unsigned int
247 225
 
248 226
       /* allocates a new retrans_buff for the outbound request */
249 227
       T->outbound_request[0] = (struct retrans_buff*)sh_malloc( sizeof(struct retrans_buff) );
228
+      memset( T->outbound_request[0] , 0 , sizeof (struct retrans_buff) );
250 229
       T->nr_of_outgoings = 1;
251 230
 
252 231
       /* special case : CANCEL */
... ...
@@ -270,28 +249,36 @@ int t_forward( struct s_table* hash_table , struct sip_msg* p_msg , unsigned int
270 249
       }/* end special case CANCEL*/
271 250
 
272 251
       /* store */
273
-      T->outbound_request[0]->dest_ip    = dest_ip;
274
-      T->outbound_request[0]->dest_port = dest_port;
275
-      // buf = build_message( p_mesg , &len );
252
+      T->outbound_request[0]->tl[0].payload = &(T->outbound_request[0]);
253
+      T->outbound_request[0]->dest_ip         = dest_ip;
254
+      T->outbound_request[0]->dest_port      = dest_port;
255
+      T->outbound_request[0]->to.sin_family = AF_INET;
256
+      T->outbound_request[0]->to.sin_port     = htonl( dest_port ) ;
257
+      T->outbound_request[0]->to.sin_addr.s_addr = ntohl( dest_port ) ;
258
+
259
+      // buf = build_message( p_mesg , &len );      TO DO!!
276 260
       // T->outbound_request[0]->bufflen     = len ;
277 261
       // memcpy( T->outbound_request[0]->buffer , buf , len );
278 262
    }/* end for the first time */
279 263
 
280
-   /* send the request */
281
-   // send ( T->outbound_request.buffer , T->outbound_request.dest_ip , T->outbound_request.dest_ip );
282 264
 
265
+   /* sets and starts the RETRANS timer */
266
+   T->outbound_request[0]->nr_retrans    = 0;
267
+   T->outbound_request[0]->max_retrans = (T->inbound_request->first_line.u.request.method_value==METHOD_INVITE) ? MAX_INVITE_RETR : MAX_NON_INVITE_RETR;
268
+   T->outbound_request[0]->timeout         = RETR_T1;
269
+   /* send the request */
270
+   send_udp_to( T->outbound_request[0]->buffer , T->outbound_request[0]->bufflen , &(T->outbound_request[0]->to) , sizeof(struct sockaddr_in) );
283 271
 }
284 272
 
285 273
 
286 274
 
287 275
 
288
-
289 276
 /*  This function is called whenever a reply for our module is received; we need to register
290 277
   *  this function on module initialization;
291 278
   *  Returns :   1 - core router stops
292 279
   *                    0 - core router relay statelessly
293 280
   */
294
-int t_on_reply_received( struct s_table  *hash_table , struct sip_msg  *p_msg )
281
+int t_on_reply_received( struct sip_msg  *p_msg )
295 282
 {
296 283
    unsigned int  branch;
297 284
 
... ...
@@ -308,7 +295,7 @@ int t_on_reply_received( struct s_table  *hash_table , struct sip_msg  *p_msg )
308 295
    if ( T->inbound_request->first_line.u.request.method_value==METHOD_INVITE && p_msg->first_line.u.reply.statusclass>2 )
309 296
    {
310 297
       // sendACK   TO DO !!!!!!!!!!
311
-      // remove_from_retransmission_list( T->outbound_request[branch] );     TO DO !!!!!
298
+      remove_from_timer_list( hash_table , &(T->outbound_request[branch]->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
312 299
       t_store_incoming_reply( T , branch , p_msg );
313 300
    }
314 301
 
... ...
@@ -329,10 +316,13 @@ int t_on_reply_received( struct s_table  *hash_table , struct sip_msg  *p_msg )
329 316
    {  /* no reply sent yet or sent but not final*/
330 317
 
331 318
       /* stops the request's retransmission*/
332
-      // remove_from_retransmission_list( T->outbound_request[branch] );     TO DO !!!!!
319
+      remove_from_timer_list( hash_table , &(T->outbound_request[branch]->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
333 320
       /* restart retransmission if provisional response came for a non_INVITE -> retrasmit at RT_T2*/
334 321
       if ( p_msg->first_line.u.reply.statusclass==1 && T->inbound_request->first_line.u.request.method_value!=METHOD_INVITE )
335
-         /*put_in_retransmission_list( T->trasaction.outbound_request[branch] , RT_T2 ) TO DO !!!!!!!*/ ;
322
+      {
323
+         T->outbound_request[branch]->timeout = RETR_T2;
324
+         insert_into_timer_list( hash_table , &(T->outbound_request[branch]->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , 10/* TO DO !!! */ );
325
+      }
336 326
 
337 327
 
338 328
       /* relay ringing and OK immediately */
... ...
@@ -366,6 +356,37 @@ int t_on_reply_received( struct s_table  *hash_table , struct sip_msg  *p_msg )
366 356
 
367 357
 
368 358
 
359
+/*
360
+  */
361
+int t_put_on_wait(  struct sip_msg  *p_msg  )
362
+{
363
+   unsigned int i;
364
+
365
+   t_check( hash_table , p_msg );
366
+   /* do we have something to release? */
367
+   if (T==0)
368
+      return -1;
369
+
370
+   /**/
371
+  for( i=0 ; i<T->nr_of_outgoings ; i++ )
372
+      if ( T->outbound_response[i] && T->outbound_response[i]->first_line.u.reply.statusclass==1)
373
+          t_cancel_branch(i);
374
+
375
+   /* make double-sure we have finished everything */
376
+   /* retranssmision list */
377
+   remove_from_timer_list( hash_table , &(T->inbound_response->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
378
+   for( i=0 ; i<T->nr_of_outgoings ; i++ )
379
+      remove_from_timer_list( hash_table , &(T->outbound_request[i]->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST );
380
+   /* final response list */
381
+   remove_from_timer_list( hash_table , &(T->tl[FR_TIMER_LIST]) , FR_TIMER_LIST );
382
+
383
+   add_to_tail_of_timer_list( hash_table, &(T->tl[WT_TIMER_LIST]), WT_TIMER_LIST, WT_TIME_OUT );
384
+   return 0;
385
+}
386
+
387
+
388
+
389
+
369 390
 /* Retransmits the last sent inbound reply.
370 391
   * Returns  -1 -error
371 392
   *                0 - OK
... ...
@@ -377,7 +398,7 @@ int t_retransmit_reply( struct s_table *hash_table , struct sip_msg* p_msg )
377 398
    /* if no transaction exists or no reply to be resend -> out */
378 399
    if ( T  && T->inbound_response )
379 400
    {
380
-       //sendto(  );   TO DO !!!!!!
401
+      send_udp_to( T->inbound_response->buffer , T->inbound_response->bufflen , &(T->inbound_response->to) , sizeof(struct sockaddr_in) );
381 402
       return 0;
382 403
    }
383 404
 
... ...
@@ -387,9 +408,77 @@ int t_retransmit_reply( struct s_table *hash_table , struct sip_msg* p_msg )
387 408
 
388 409
 
389 410
 
411
+
412
+
413
+
414
+
415
+
416
+
390 417
 /* ----------------------------HELPER FUNCTIONS-------------------------------- */
391 418
 
392 419
 
420
+/* function returns:
421
+ *       0 - transaction wasn't found
422
+ *       T - transaction found
423
+ */
424
+struct cell* t_lookupOriginalT(  struct s_table* hash_table , struct sip_msg* p_msg )
425
+{
426
+   struct cell      *p_cell;
427
+   struct cell      *tmp_cell;
428
+   unsigned int  hash_index=0;
429
+
430
+   /* it's a CANCEL request for sure */
431
+
432
+   /* start searching into the table */
433
+   hash_index = hash( p_msg->callid , get_cseq(p_msg)->number  ) ;
434
+
435
+   /* all the transactions from the entry are compared */
436
+   p_cell     = hash_table->entrys[hash_index].first_cell;
437
+   tmp_cell = 0;
438
+   while( p_cell )
439
+   {
440
+      /* the transaction is referenceted for reading */
441
+      ref_transaction( p_cell );
442
+
443
+      /* is it the wanted transaction ? */
444
+      /* first only the length are checked */
445
+      if ( /*from length*/ p_cell->inbound_request->from->body.len == p_msg->from->body.len )
446
+         if ( /*to length*/ p_cell->inbound_request->to->body.len == p_msg->to->body.len )
447
+            //if ( /*tag length*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && p_cell->inbound_request->tag->body.len == p_msg->tag->body.len) )
448
+               if ( /*callid length*/ p_cell->inbound_request->callid->body.len == p_msg->callid->body.len )
449
+                  if ( /*cseq_nr length*/ get_cseq(p_cell->inbound_request)->number.len == get_cseq(p_msg)->number.len )
450
+                      if ( /*cseq_method type*/ p_cell->inbound_request->first_line.u.request.method_value!=METHOD_CANCEL )
451
+                         if ( /*req_uri length*/ p_cell->inbound_request->first_line.u.request.uri.len == p_msg->first_line.u.request.uri.len )
452
+                             /* so far the lengths are the same -> let's check the contents */
453
+                             if ( /*from*/ !memcmp( p_cell->inbound_request->from->body.s , p_msg->from->body.s , p_msg->from->body.len ) )
454
+                                if ( /*to*/ !memcmp( p_cell->inbound_request->to->body.s , p_msg->to->body.s , p_msg->to->body.len)  )
455
+                                   //if ( /*tag*/ (!p_cell->inbound_request->tag && !p_msg->tag) || (p_cell->inbound_request->tag && p_msg->tag && !memcmp( p_cell->inbound_request->tag->body.s , p_msg->tag->body.s , p_msg->tag->body.len )) )
456
+                                      if ( /*callid*/ !memcmp( p_cell->inbound_request->callid->body.s , p_msg->callid->body.s , p_msg->callid->body.len ) )
457
+                                          if ( /*cseq_nr*/ !memcmp( get_cseq(p_cell->inbound_request)->number.s , get_cseq(p_msg)->number.s , get_cseq(p_msg)->number.len ) )
458
+                                             if ( /*req_uri*/ memcmp( p_cell->inbound_request->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.s , p_msg->first_line.u.request.uri.len ) )
459
+                                             { /* WE FOUND THE GOLDEN EGG !!!! */
460
+                                                unref_transaction ( p_cell );
461
+                                                return p_cell;
462
+                                             }
463
+      /* next transaction */
464
+      tmp_cell = p_cell;
465
+      p_cell = p_cell->next_cell;
466
+
467
+      /* the transaction is dereferenceted */
468
+      unref_transaction ( tmp_cell );
469
+   }
470
+
471
+   /* no transaction found */
472
+   T = 0;
473
+   return 0;
474
+
475
+
476
+   return 0;
477
+}
478
+
479
+
480
+
481
+
393 482
 /* Returns 0 - nothing found
394 483
   *              1  - T found
395 484
   */
... ...
@@ -461,7 +550,7 @@ int t_store_incoming_reply( struct cell* Trans, unsigned int branch, struct sip_
461 550
 {
462 551
    /* if there is a previous reply, replace it */
463 552
    if ( Trans->outbound_response[branch] )
464
-      /*free_sip_msg( Trans->outbound_response[branch] ) TO DO*/ ;
553
+      free_sip_msg( Trans->outbound_response[branch] ) ;
465 554
    Trans->outbound_response[branch] = sip_msg_cloner( p_msg );
466 555
 }
467 556
 
... ...
@@ -494,7 +583,7 @@ int t_check( struct s_table *hash_table , struct sip_msg* p_msg )
494 583
       global_msg_id = p_msg->id;
495 584
       /* transaction lookup */
496 585
      if ( p_msg->first_line.type=SIP_REQUEST )
497
-         t_lookup_request(  hash_table , p_msg );
586
+         t_lookup_request( p_msg );
498 587
       else
499 588
          t_reply_matching( hash_table , p_msg , &T , &branch );
500 589
 
... ...
@@ -568,7 +657,19 @@ int push_reply_from_uac_to_uas( struct sip_msg *p_msg , unsigned int branch )
568 657
 
569 658
 
570 659
 
660
+/* sends a buffer as a datagram
661
+  */
662
+int send_udp_to( char *buf, unsigned buflen, struct sockaddr_in*  to, unsigned tolen )
663
+{
664
+   int res;
665
+
666
+    do
667
+    {
668
+       res = sendto(sock_fd, buf, buflen, 0, to, tolen);
669
+    }while( res==-1 && errno==EINTR );
571 670
 
671
+   return res;
672
+}
572 673
 
573 674
 
574 675
 
... ...
@@ -576,65 +677,76 @@ int push_reply_from_uac_to_uas( struct sip_msg *p_msg , unsigned int branch )
576 677
 
577 678
 
578 679
 
579
-/*
580
-*   The cell is inserted at the end of the FINAL RESPONSE timer list.
581
-*   The expire time is given by the current time plus the FINAL
582
-    RESPONSE timeout - FR_TIME_OUT
583
-*/
584
-void start_FR_timer( struct s_table* hash_table, struct cell* p_cell )
680
+
681
+/*---------------------------------TIMEOUT HANDLERS--------------------------------------*/
682
+
683
+
684
+void retransmission_handler( void *attr)
585 685
 {
686
+   struct retrans_buff* r_buf = (struct retrans_buff*)attr;
586 687
 
587
-   /* adds the cell int FINAL RESPONSE timer list*/
588
-   add_to_tail_of_timer_list( hash_table, &(p_cell->tl[FR_TIMER_LIST]), FR_TIMER_LIST, FR_TIME_OUT);
688
+   /* the transaction is already removed from RETRANSMISSION_LIST by the timer */
689
+
690
+   /* do we still have to retransmit? */
691
+   if ( r_buf->nr_retrans<=r_buf->max_retrans )
692
+   {
693
+       /* computs the new timeout. */
694
+       if ( r_buf->timeout<RETR_T2 )
695
+          r_buf->timeout *=2;
696
+       r_buf->nr_retrans++;
697
+       /* re-insert into RETRASMISSIONS_LIST */
698
+       insert_into_timer_list( hash_table , &(r_buf->tl[RETRASMISSIONS_LIST]) , RETRASMISSIONS_LIST , r_buf->timeout );
699
+   }
700
+   else
701
+   {
702
+    // send also 408 ?  TO DO !!!!!!
703
+   }
589 704
 
590 705
 }
591 706
 
592 707
 
593
-/*
594
-*   The cell is inserted at the end of the WAIT timer list. Before adding to the WT list, it's verify if the cell is
595
-*   or not in the FR list (normally it should be there). If it is, it's first removed from FR list and after that
596
-*   added to the WT list.
597
-*   The expire time is given by the current time plus the WAIT timeout - WT_TIME_OUT
598
-*/
599 708
 
600
-void start_WT_timer( struct s_table* hash_table, struct cell* p_cell )
709
+
710
+void final_response_handler( void *attr)
601 711
 {
602
-   	struct timer* timers= hash_table->timers;
712
+   struct cell *p_cell = (struct cell*)attr;
603 713
 
604
-   	//if is in FR list -> first it must be removed from there
605
-	remove_from_timer_list( hash_table, &(p_cell->tl[FR_TIMER_LIST]), FR_TIMER_LIST );
714
+   /* the transaction is already removed from FR_LIST by the timer */
715
+   /* send a 408 (some dirty trick)*/
716
+   /* TO DO!!!!! to build the message  and to send*/
717
+   p_cell->status = 408;
718
+   /* put it on WT_LIST - transaction is over */
719
+   add_to_tail_of_timer_list( hash_table , &(p_cell->tl[WT_TIMER_LIST]) , WT_TIMER_LIST , WT_TIME_OUT );
606 720
 
607
-   	/* adds the cell int WAIT timer list*/
608
-   	add_to_tail_of_timer_list( hash_table, &(p_cell->tl[WT_TIMER_LIST]), WT_TIMER_LIST, WT_TIME_OUT );
609 721
 }
610 722
 
611 723
 
612 724
 
613 725
 
614
-/*
615
-*   prepare for del a transaction ; the transaction is first removed from the hash entry list (oniy the links from
616
-*   cell to list are deleted in order to make the cell unaccessible from the list and in the same time to keep the
617
-*   list accessible from the cell for process that are currently reading the cell). If no process is reading the cell
618
-*   (ref conter is 0) the cell is immediatly deleted. Otherwise it is put in a waitting list (del_hooker list) for
619
-*   future del. This list is veify by the the timer every sec and the cell that finaly have ref_counter 0 are del.
620
-*/
621
-void del_Transaction( struct s_table *hash_table , struct cell * p_cell )
726
+void wait_handler( void *attr)
622 727
 {
623
-    int      ref_counter         = 0;
728
+   struct cell *p_cell = (struct cell*)attr;
624 729
 
625
-    /* the cell is removed from the list */
730
+   /* the transaction is already removed from WT_LIST by the timer */
731
+   /* the cell is removed from the hash table */
626 732
     remove_from_hash_table( hash_table, p_cell );
733
+   /* put it on DEL_LIST - sch for del */
734
+    add_to_tail_of_timer_list( hash_table, &(p_cell->tl[DELETE_LIST]), DELETE_LIST, DEL_TIME_OUT );
735
+}
627 736
 
628
-    /* gets the cell's ref counter*/
629
-    lock( p_cell->mutex );
630
-    ref_counter = p_cell->ref_counter;
631
-    unlock( p_cell->mutex );
632 737
 
738
+
739
+
740
+void delete_handler( void *attr)
741
+{
742
+   struct cell *p_cell = (struct cell*)attr;
743
+
744
+   /* the transaction is already removed from DEL_LIST by the timer */
633 745
     /* if is not refenceted -> is deleted*/
634
-    if ( ref_counter==0 )
746
+    if ( p_cell->ref_counter==0 )
635 747
        free_cell( p_cell );
636
-     /* else it's added to del hooker list for future del */
637
-    else add_to_tail_of_timer_list( hash_table, &(p_cell->tl[DELETE_LIST]), DELETE_LIST, 0 );
748
+    else
749
+       /* else it's readded to del list for future del */
750
+       add_to_tail_of_timer_list( hash_table, &(p_cell->tl[DELETE_LIST]), DELETE_LIST, DEL_TIME_OUT );
638 751
 }
639 752
 
640
-
... ...
@@ -1,6 +1,8 @@
1 1
 #ifndef _T_FUNCS_H
2 2
 #define _T_FUNCS_H
3 3
 
4
+#include <errno.h>
5
+#include <netinet/in.h>
4 6
 #include "../../msg_parser.h"
5 7
 
6 8
 struct s_table;
... ...
@@ -18,26 +20,30 @@ struct cell;
18 20
 
19 21
 
20 22
 
23
+int tm_startup();
24
+int tm_shutdown();
25
+
26
+
21 27
 /* function returns:
22 28
  *       0 - a new transaction was created
23 29
  *      -1 - retransmission
24 30
  *      -2 - error
25 31
  */
26
-int  t_add_transaction( struct s_table* hash_table , struct sip_msg* p_msg );
32
+int  t_add_transaction( struct sip_msg* p_msg );
27 33
 
28 34
 
29 35
 /* function returns:
30 36
  *       0 - transaction wasn't found
31 37
  *       1 - transaction found
32 38
  */
33
-int  t_lookup_request( struct s_table* hash_table , struct sip_msg* p_msg );
39
+int  t_lookup_request( struct sip_msg* p_msg );
34 40
 
35 41
 
36 42
 /* function returns:
37 43
  *       0 - forward successfull
38 44
  *      -1 - error during forward
39 45
  */
40
-int t_forward( struct s_table* hash_table , struct sip_msg* p_msg , unsigned int dst_ip , unsigned int dst_port);
46
+int t_forward( struct sip_msg* p_msg , unsigned int dst_ip , unsigned int dst_port);
41 47
 
42 48
 
43 49
 
... ...
@@ -46,7 +52,15 @@ int t_forward( struct s_table* hash_table , struct sip_msg* p_msg , unsigned int
46 52
   *  Returns :   1 - core router stops
47 53
   *                    0 - core router relay statelessly
48 54
   */
49
-int t_on_reply_received( struct s_table  *hash_table , struct sip_msg  *p_msg ) ;
55
+int t_on_reply_received( struct sip_msg  *p_msg ) ;
56
+
57
+
58
+
59
+
60
+/*
61
+*/
62
+int t_put_on_wait(  struct sip_msg  *p_msg  );
63
+
50 64
 
51 65
 
52 66
 
... ...
@@ -11,14 +11,24 @@ enum lists { RETRASMISSIONS_LIST, FR_TIMER_LIST, WT_TIMER_LIST, DELETE_LIST, NR_
11 11
 
12 12
 
13 13
 /* FINAL_RESPONSE_TIMER ... tells how long should the transaction engine
14
-   wait if no final response comes back
15
-*/
14
+   wait if no final response comes back*/
16 15
 #define FR_TIME_OUT     16
16
+
17 17
 /* WAIT timer ... tells how long state should persist in memory after
18
-   a transaction was finalized
19
-*/
18
+   a transaction was finalized*/
20 19
 #define WT_TIME_OUT      16
21 20
 
21
+/* DELETE timer ... tells how long should the transaction persist in memory
22
+   after it was removed from the hash table and before it will be deleted */
23
+#define DEL_TIME_OUT      2
24
+
25
+
26
+#define RETR_T1  1
27
+#define RETR_T2  2
28
+
29
+#define MAX_INVITE_RETR           7
30
+#define MAX_NON_INVITE_RETR  11
31
+
22 32
 
23 33
 /* all you need to put a cell in a timer list:
24 34
    links to neighbours and timer value         */