ser_error processing, ipv6-ization of TM, new TM callbacks;
[sip-router] / modules / tm / t_lookup.c
1 /*
2  * $Id$
3  *
4  * This C-file takes care of matching requests and replies with
5  * existing transactions. Note that we do not do SIP-compliant
6  * request matching as asked by SIP spec. We do bitwise matching of 
7  * all header fields in requests which form a transaction key. 
8  * It is much faster and it worx pretty well -- we haven't 
9  * had any interop issue neither in lab nor in bake-offs. The reason
10  * is that retransmissions do look same as original requests
11  * (it would be really silly if they wuld be mangled). The only
12  * exception is we parse To as To in ACK is compared to To in
13  * reply and both  of them are constructed by different software.
14  * 
15  * As for reply matching, we match based on branch value -- that is
16  * faster too. There are two versions .. with SYNONYMs #define
17  * enabled, the branch includes ordinal number of a transaction
18  * in a synonym list in hash table and is somewhat faster but
19  * not reboot-resilient. SYNONYMs turned off are little slower
20  * but work across reboots as well.
21  *
22  * The branch parameter is formed as follows:
23  * SYNONYMS  on: hash.synonym.branch
24  * SYNONYMS off: md5.hash.branch
25  *
26  * -jiri
27  *
28  */
29
30 #include <assert.h>
31 #include "../../dprint.h"
32 #include "../../config.h"
33 #include "../../parser/parser_f.h"
34 #include "../../ut.h"
35 #include "../../timer.h"
36 #include "hash_func.h"
37 #include "t_funcs.h"
38 #include "config.h"
39 #include "sip_msg.h"
40 #include "t_hooks.h"
41
42
43 #define EQ_LEN(_hf) (t_msg->_hf->body.len==p_msg->_hf->body.len)
44 #define EQ_STR(_hf) (memcmp(t_msg->_hf->body.s,\
45         translate_pointer(p_msg->orig,p_msg->buf,p_msg->_hf->body.s), \
46         p_msg->_hf->body.len)==0)
47 #define EQ_REQ_URI_LEN\
48         (p_msg->first_line.u.request.uri.len==t_msg->first_line.u.request.uri.len)
49 #define EQ_REQ_URI_STR\
50         ( memcmp( t_msg->first_line.u.request.uri.s,\
51         translate_pointer(p_msg->orig,p_msg->buf,p_msg->first_line.u.request.uri.s),\
52         p_msg->first_line.u.request.uri.len)==0)
53 #define EQ_VIA_LEN(_via)\
54         ( (p_msg->via1->bsize-(p_msg->_via->name.s-(p_msg->_via->hdr.s+p_msg->_via->hdr.len)))==\
55         (t_msg->via1->bsize-(t_msg->_via->name.s-(t_msg->_via->hdr.s+t_msg->_via->hdr.len))) )
56
57 #define EQ_VIA_STR(_via)\
58         ( memcmp( t_msg->_via->name.s,\
59          translate_pointer(p_msg->orig,p_msg->buf,p_msg->_via->name.s),\
60          (t_msg->via1->bsize-(t_msg->_via->name.s-(t_msg->_via->hdr.s+t_msg->_via->hdr.len)))\
61         )==0 )
62
63
64 /* function returns:
65  *      negative - transaction wasn't found
66  *                      (-2 = possibly e2e ACK matched )
67  *      positive - transaction found
68  */
69
70 int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
71 {
72         struct cell         *p_cell;
73         unsigned int       isACK;
74         struct sip_msg  *t_msg;
75         int ret;
76
77         /* parse all*/
78         if (check_transaction_quadruple(p_msg)==0)
79         {
80                 LOG(L_ERR, "ERROR: TM module: t_lookup_request: too few headers\n");
81                 T=0;
82                 /* stop processing */
83                 return 0;
84         }
85
86         /* start searching into the table */
87         p_msg->hash_index=hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
88         isACK = p_msg->REQ_METHOD==METHOD_ACK;
89         DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
90                 p_msg->hash_index,isACK);
91
92         /* asume not found */
93         ret=-1;
94
95         /* lock the hole entry*/
96         lock(&(hash_table->entrys[p_msg->hash_index].mutex));
97
98         /* all the transactions from the entry are compared */
99         for ( p_cell = hash_table->entrys[p_msg->hash_index].first_cell;
100                   p_cell; p_cell = p_cell->next_cell ) 
101         {
102                 t_msg = p_cell->uas.request;
103
104                 if (!isACK) {   
105                         /* compare lengths first */ 
106                         if (!EQ_LEN(callid)) continue;
107                         if (!EQ_LEN(cseq)) continue;
108                         if (!EQ_LEN(from)) continue;
109                         if (!EQ_LEN(to)) continue;
110                         if (!EQ_REQ_URI_LEN) continue;
111                         if (!EQ_VIA_LEN(via1)) continue;
112
113                         /* length ok -- move on */
114                         if (!EQ_STR(callid)) continue;
115                         if (!EQ_STR(cseq)) continue;
116                         if (!EQ_STR(from)) continue;
117                         if (!EQ_STR(to)) continue;
118                         if (!EQ_REQ_URI_STR) continue;
119                         if (!EQ_VIA_STR(via1)) continue;
120
121                         /* request matched ! */
122                         DBG("DEBUG: non-ACK matched\n");
123                         goto found;
124                 } else { /* it's an ACK request*/
125                         /* ACK's relate only to INVITEs */
126                         if (t_msg->REQ_METHOD!=METHOD_INVITE) continue;
127
128                         /* compare lengths now */
129                         if (!EQ_LEN(callid)) continue;
130                         /* CSeq only the number without method ! */
131                         if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len)
132                                 continue;
133                         if (! EQ_LEN(from)) continue;
134                         /* To only the uri and ... */
135                         if (get_to(t_msg)->uri.len!=get_to(p_msg)->uri.len)
136                                 continue;
137                         /* ... its to-tag compared to reply's tag */
138                         if (p_cell->uas.tag->len!=get_to(p_msg)->tag_value.len)
139                                 continue;
140
141                         /* we first skip r-uri and Via and proceed with
142                            content of other header-fields */
143
144                         if ( memcmp(t_msg->callid->body.s, p_msg->callid->body.s,
145                                 p_msg->callid->body.len)!=0) continue;
146                         if ( memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,
147                                 get_cseq(p_msg)->number.len)!=0) continue;
148                         if (!EQ_STR(from)) continue;
149                         if (memcmp(get_to(t_msg)->uri.s, get_to(p_msg)->uri.s,
150                                 get_to(t_msg)->uri.len)!=0) continue;
151                         if (memcmp(p_cell->uas.tag->s, get_to(p_msg)->tag_value.s,
152                                 p_cell->uas.tag->len)!=0) continue;
153         
154                         /* ok, now only r-uri or via can mismatch; they must match
155                            for non-2xx; if it is a 2xx, we don't try to match
156                            (we might have checked that earlier to speed-up, but
157                            we still want to see a diagnosti message telling
158                            "this ACK presumably belongs to this 2xx transaction";
159                            might change in future); the reason is 2xx ACKs are
160                            a separate transaction which may carry different
161                            r-uri/via1 and is thus also impossible to match it
162                            uniquely to a spiraled transaction;
163                         */
164                         if (p_cell->uas.status>=200 && p_cell->uas.status<300) {
165                                 DBG("DEBUG: an ACK hit a 2xx transaction (T=%p); "
166                                         "considered mismatch\n", p_cell );
167                                 /* perhaps there are some spirals on the synonym list, but
168                                    it makes no sense to iterate the list until bitter end */
169                                 ret=-2;
170                                 break;
171                         }
172                         /* its for a >= 300 ... everything must match ! */
173                         if (! EQ_REQ_URI_LEN ) continue;
174                         if (! EQ_VIA_LEN(via1)) continue;
175                         if (!EQ_REQ_URI_STR) continue;
176                         if (!EQ_VIA_STR(via1)) continue;
177
178                         /* wow -- we survived all the check! we matched! */
179                         DBG("DEBUG: non-2xx ACK matched\n");
180                         goto found;
181                 } /* ACK */
182         } /* synonym loop */
183
184         /* no transaction found */
185         T = 0;
186         if (!leave_new_locked)
187                 unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
188         DBG("DEBUG: t_lookup_request: no transaction found\n");
189         return ret;
190
191 found:
192         T=p_cell;
193         T_REF( T );
194         DBG("DEBUG: t_lookup_request: transaction found (T=%p , ref=%x)\n",
195                 T,T->ref_bitmap);
196         unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
197         return 1;
198 }
199
200
201 #ifdef __YOU_DONT_WANT_TO_DO_THIS
202
203 /* function returns:
204  *      -1 - transaction wasn't found
205  *       1  - transaction found
206  */
207 int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
208 {
209         struct cell         *p_cell;
210         struct cell         *tmp_cell;
211         unsigned int       isACK;
212         struct sip_msg  *t_msg;
213
214         /* parse all*/
215         if (check_transaction_quadruple(p_msg)==0)
216         {
217                 LOG(L_ERR, "ERROR: TM module: t_lookup_request: too few headers\n");
218                 T=0;
219                 /* stop processing */
220                 return 0;
221         }
222
223         /* start searching into the table */
224         p_msg->hash_index=hash( p_msg->callid->body , get_cseq(p_msg)->number ) ;
225         isACK = p_msg->REQ_METHOD==METHOD_ACK;
226         DBG("t_lookup_request: start searching: hash=%d, isACK=%d\n",
227                 p_msg->hash_index,isACK);
228
229         /* lock the hole entry*/
230         lock(&(hash_table->entrys[p_msg->hash_index].mutex));
231
232         /* all the transactions from the entry are compared */
233         p_cell   = hash_table->entrys[p_msg->hash_index].first_cell;
234         tmp_cell = 0;
235         while( p_cell )
236         {
237                 t_msg = p_cell->uas.request;
238
239                 /* is it the wanted transaction ? */
240                 if ( !isACK )
241                 { /* is not an ACK request */
242                         /* first only the length are checked */
243                         if ( /*callied*/EQ_LEN(callid) && /*cseq*/EQ_LEN(cseq)
244                         && /*req URI*/EQ_REQ_URI_LEN && /*VIA*/EQ_VIA_LEN(via1)
245                         && /*from*/EQ_LEN(from) && /*to*/EQ_LEN(to)  )
246                                 /* so far the lengths are the same
247                                 -> let's check the contents */
248                                 if ( /*callid*/EQ_STR(callid) && /*cseq*/EQ_STR(cseq)
249                                 && /*req URI*/EQ_REQ_URI_STR && /*VIA*/EQ_VIA_STR(via1)
250                                 && /*from*/EQ_STR(from) && /*to*/EQ_STR(to) )
251                                         { /* WE FOUND THE GOLDEN EGG !!!! */
252                                                 goto found;
253                                         }
254                 }
255                 else
256                 { /* it's a ACK request*/
257                         /* first only the length are checked */
258                         /* use shortcut; -jiri
259                         if ( t_msg->first_line.u.request.method_value==METHOD_INVITE */
260                         if (t_msg->REQ_METHOD==METHOD_INVITE
261                         /* && (fprintf(stderr,"------Method name OK->testing callid len...\n")) */
262                         && /*callid length*/ EQ_LEN(callid)
263                         /* && (fprintf(stderr,"------CallID OK -> testing cseq nr len\n")) */
264                         && get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
265                         /* && (fprintf(stderr,"------Cseq nr OK -> testing from len\n")) */
266                         && /*from length*/ EQ_LEN(from)
267                         /* && (fprintf(stderr,"------from OK -> testing To uri len\n")) */
268                         && /*to uri*/get_to(t_msg)->uri.len==get_to(p_msg)->uri.len
269                         /* && (fprintf(stderr,"------To uri OK -> testing To tag len\n")) */
270                         && /*to tag*/p_cell->uas.tag->len==get_to(p_msg)->tag_value.len
271                         /* && (fprintf(stderr,"------To tag OK -> testing uri len\n")) */
272
273                         /* in ACKs to 200, r-uri and Via may be different than in
274                            original INVITE; we still try to match the transaction
275                            so that we can retransmit an ACK on resent 200 -- different
276                            from SIP spec which kills transaction state after INVITE-200
277                            and considers 200-ACK a new transaction which just happens
278                            to have the same CSeq. -jiri
279                         */
280
281                         && /*req URI*/(p_cell->uas.status==200 || EQ_REQ_URI_LEN )
282                         /* && (fprintf(stderr,"------uri OK -> testing via len\n")) */
283                         && /*VIA*/(p_cell->uas.status==200 || EQ_VIA_LEN(via1)) )
284                                 /* so far the lengths are the same
285                                 -> let's check the contents */
286                                 if ( /* fprintf(stderr,"------callid |%.*s| |%.*s|\n",
287                                         p_msg->callid->body.len,p_msg->callid->body.s,
288                                         t_msg->callid->body.len,t_msg->callid->body.s)
289                                 && */ /*callid*/!memcmp( t_msg->callid->body.s,
290                                         p_msg->callid->body.s,p_msg->callid->body.len)
291                                 /* && fprintf(stderr,"------cseq |%.*s| |%.*s|\n",
292                                         get_cseq(p_msg)->number.len,get_cseq(p_msg)->number.s,
293                                         get_cseq(t_msg)->number.len,get_cseq(t_msg)->number.s) */
294                                 && /*cseq nr*/!memcmp(get_cseq(t_msg)->number.s,
295                                         get_cseq(p_msg)->number.s,get_cseq(p_msg)->number.len)
296                                 /* &&  fprintf(stderr,"------from |%.*s| |%.*s|\n",
297                                         p_msg->from->body.len, translate_pointer(p_msg->orig,
298                                                 p_msg->buf,p_msg->from->body.s),
299                                         t_msg->from->body.len,t_msg->from->body.s) */
300                                 && /*from*/EQ_STR(from)
301                                 /* && fprintf(stderr,"------to uri |%.*s| |%.*s|\n",
302                                         get_to(p_msg)->uri.len,get_to(p_msg)->uri.s,
303                                         get_to(t_msg)->uri.len,get_to(t_msg)->uri.s) */
304                                 && /*to uri*/!memcmp(get_to(t_msg)->uri.s,
305                                         get_to(p_msg)->uri.s,get_to(t_msg)->uri.len)
306                                 /* && fprintf(stderr,"------to tag |%.*s| |%.*s|\n",
307                     get_to(p_msg)->tag_value.len,get_to(p_msg)->tag_value.s,
308                     p_cell->uas.tag->len, p_cell->uas.tag->s) */
309                                 && /*to tag*/!memcmp(p_cell->uas.tag->s,
310                                         get_to(p_msg)->tag_value.s,p_cell->uas.tag->len)
311                                 /* && fprintf(stderr,"------URI %d |%.*s| |%.*s|\n",
312                                         p_cell->uas.status,p_msg->first_line.u.request.uri.len,
313                                         translate_pointer(p_msg->orig, p_msg->buf,
314                                                 p_msg->first_line.u.request.uri.s),
315                                         t_msg->first_line.u.request.uri.len,
316                                         t_msg->first_line.u.request.uri.s) */
317                                 && /*req URI*/(p_cell->uas.status==200 || EQ_REQ_URI_STR)
318                                 /* && fprintf(stderr,"------VIA %d |%.*s| |%.*s|\n",
319                                         p_cell->uas.status, 
320                                         (p_msg->via1->bsize-(p_msg->via1->name.s-
321                                                 (p_msg->via1->hdr.s+p_msg->via1->hdr.len))),
322                                         translate_pointer(p_msg->orig,p_msg->buf,
323                                                 p_msg->via1->name.s),
324                     (t_msg->via1->bsize-(t_msg->via1->name.s-
325                                                 (t_msg->via1->hdr.s+t_msg->via1->hdr.len))),
326                                         t_msg->via1->name.s) */
327                                 && /*VAI*/(p_cell->uas.status==200 ||EQ_VIA_STR(via1)) )
328                                         { /* WE FOUND THE GOLDEN EGG !!!! */
329                                                 goto found;
330                                         }
331                 }
332                 /* next transaction */
333                 tmp_cell = p_cell;
334                 p_cell = p_cell->next_cell;
335         } /* synonym loop */
336
337         /* no transaction found */
338         T = 0;
339         if (!leave_new_locked)
340                 unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
341         DBG("DEBUG: t_lookup_request: no transaction found\n");
342         /* DON'T FORGET TO REMOVE IT!!!!! bogdan */
343         //if (isACK) assert(0);
344         return -1;
345
346 found:
347         T=p_cell;
348         T_REF( T );
349         DBG("DEBUG: t_lookup_request: transaction found (T=%p , ref=%x)\n",
350                 T,T->ref_bitmap);
351         unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
352         return 1;
353 }
354
355 #endif
356
357
358
359 /* function returns:
360  *       0 - transaction wasn't found
361  *       T - transaction found
362  */
363 struct cell* t_lookupOriginalT(  struct s_table* hash_table ,
364                                                                                                         struct sip_msg* p_msg )
365 {
366         struct cell     *p_cell;
367         struct cell     *tmp_cell;
368         unsigned int     hash_index=0;
369         struct sip_msg  *t_msg=0;
370
371
372         /* start searching into the table */
373         hash_index = p_msg->hash_index;
374         DBG("DEBUG: t_lookupOriginalT: searching on hash entry %d\n",hash_index );
375
376         /* all the transactions from the entry are compared */
377         p_cell   = hash_table->entrys[hash_index].first_cell;
378         tmp_cell = 0;
379         while( p_cell )
380         {
381                 t_msg = p_cell->uas.request;
382
383                 /* is it the wanted transaction ? */
384                 /* first only the length are checked */
385                 if ( /* fprintf(stderr,"starting\n")  && */ p_cell->uas.request->REQ_METHOD!=METHOD_CANCEL
386                         /* && fprintf(stderr,"checking callid length....\n") */
387                         && /*callid length*/ EQ_LEN(callid)
388                         /* && fprintf(stderr,"OK. checking cseg nr len....\n")   */
389                         && get_cseq(t_msg)->number.len==get_cseq(p_msg)->number.len
390                         /* && fprintf(stderr,"OK. checking REQ_URI len.... \n") */
391                         && EQ_REQ_URI_LEN
392                         /* && fprintf(stderr,"OK. checking VIA %d %d....\n",
393                                 (p_msg->via1->bsize-(p_msg->via1->name.s-
394                                         (p_msg->via1->hdr.s+p_msg->via1->hdr.len))),
395                                 (t_msg->via1->bsize-(t_msg->via1->name.s-
396                                         (t_msg->via1->hdr.s+t_msg->via1->hdr.len)))) */
397             /* && fprintf(stderr,"OK. VIA |%.*s| |%.*s|\n",
398                 (p_msg->via1->bsize-(p_msg->via1->name.s-
399                      (p_msg->via1->hdr.s+p_msg->via1->hdr.len))),
400                 translate_pointer(p_msg->orig,p_msg->buf,
401                        p_msg->via1->name.s),
402                 (t_msg->via1->bsize-(t_msg->via1->name.s-
403                       (t_msg->via1->hdr.s+t_msg->via1->hdr.len))),
404                 t_msg->via1->name.s) */
405                         && EQ_VIA_LEN(via1) 
406                         /* && fprintf(stderr,"OK. checking FROM len... \n") */
407                         && EQ_LEN(from)
408                         /* && fprintf(stderr,"OK. checking TO len... \n") */
409                         && EQ_LEN(to)
410                         /* && fprintf(stderr,"OK\n") */ )
411                                 /* so far the lengths are the same
412                                  let's check the contents */
413                                 if (
414                         /* fprintf(stderr,"checking callid |%.*s| |%.*s|\n",
415                         p_msg->callid->body.len, translate_pointer(p_msg->orig,
416                                 p_msg->buf,p_msg->callid->body.s),
417                         t_msg->callid->body.len,t_msg->callid->body.s) 
418                                         && *//*callid*/ EQ_STR(callid)
419                                         /* && fprintf(stderr,"OK. cseq nr |%.*s| |%.*s|\n",
420                                                 get_cseq(p_msg)->number.len,get_cseq(p_msg)->number.s,
421                                                 get_cseq(t_msg)->number.len,get_cseq(t_msg)->number.s) */
422                                         && /*cseq_nr*/ !memcmp(get_cseq(t_msg)->number.s,
423                                                 get_cseq(p_msg)->number.s,get_cseq(p_msg)->number.len)
424                         /* && fprintf(stderr,"OK. URI %d |%.*s| |%.*s|\n",
425                         p_cell->uas.status,p_msg->first_line.u.request.uri.len,
426                         translate_pointer(p_msg->orig, p_msg->buf,
427                                 p_msg->first_line.u.request.uri.s),
428                         t_msg->first_line.u.request.uri.len,
429                         t_msg->first_line.u.request.uri.s) */
430                                         && EQ_REQ_URI_STR
431                         /* && fprintf(stderr,"OK. VIA |%.*s| |%.*s|\n",
432                             (p_msg->via1->bsize-(p_msg->via1->name.s-
433                             (p_msg->via1->hdr.s+p_msg->via1->hdr.len))),
434                             translate_pointer(p_msg->orig,p_msg->buf,
435                             p_msg->via1->name.s),
436                                         (t_msg->via1->bsize-(t_msg->via1->name.s-
437                             (t_msg->via1->hdr.s+t_msg->via1->hdr.len))),
438                                                 t_msg->via1->name.s) */
439                                         && EQ_VIA_STR(via1)
440                         /* && fprintf(stderr,"OK. from |%.*s| |%.*s|\n",
441                         p_msg->from->body.len, translate_pointer(p_msg->orig,
442                             p_msg->buf,p_msg->from->body.s),
443                         t_msg->from->body.len,t_msg->from->body.s) */
444                                         && EQ_STR(from)
445                                         /* && fprintf(stderr,"OK\n") */ )
446                                         { /* WE FOUND THE GOLDEN EGG !!!! */
447                                                 DBG("DEBUG: t_lookupOriginalT: canceled transaction"
448                                                         " found (%p)! \n",p_cell );
449                                                 return p_cell;
450                                         }
451                 /* next transaction */
452                 tmp_cell = p_cell;
453                 p_cell = p_cell->next_cell;
454         }
455
456         /* no transaction found */
457         DBG("DEBUG: t_lookupOriginalT: no CANCEL maching found! \n" );
458         return 0;
459 }
460
461
462
463
464 /* Returns 0 - nothing found
465  *         1  - T found
466  */
467 int t_reply_matching( struct sip_msg *p_msg , int *p_branch ,
468                                                                                          int *local_cancel)
469 {
470         struct cell*  p_cell;
471         int hash_index   = 0;
472         int entry_label  = 0;
473         int branch_id    = 0;
474         char  *hashi, *branchi, *p, *n;
475         int hashl, branchl;
476         int scan_space;
477 #ifndef USE_SYNONIM
478         char *loopi;
479         int loopl;
480 #else
481         char *syni;
482         int synl;
483 #endif
484
485         /* split the branch into pieces: loop_detection_check(ignored),
486          hash_table_id, synonym_id, branch_id */
487
488         if (!(p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s))
489                 goto nomatch2;
490
491         p=p_msg->via1->branch->value.s;
492         scan_space=p_msg->via1->branch->value.len;
493
494 #ifndef USE_SYNONIM
495         /* loop detection ... ignore */
496         n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR );
497         loopl = n-p;
498         scan_space-= loopl;
499         if (n==p || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2;
500         loopi=p;
501         p=n+1; scan_space--;
502 #endif
503
504         /* hash_id */
505         n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR);
506         hashl=n-p;
507         scan_space-=hashl;
508         if (!hashl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2;
509         hashi=p;
510         p=n+1;scan_space--;
511
512 #ifdef USE_SYNONIM
513         /* sequence id */
514         n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR);
515         synl=n-p;
516         scan_space-=synl;
517         if (!synl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2;
518         syni=p;
519         p=n+1;scan_space--;
520 #endif
521
522         /* branch id  -  should exceed the scan_space */
523         n=eat_token_end( p, p+scan_space );
524         branchl=n-p;
525         if (!branchl ) goto nomatch2;
526         branchi=p;
527
528         /* sanity check */
529         if ((hash_index=reverse_hex2int(hashi, hashl))<0||hash_index>=TABLE_ENTRIES
530                 || (branch_id=reverse_hex2int(branchi, branchl))<0||branch_id>=MAX_FORK
531 #ifdef USE_SYNONIM
532                 || (entry_label=reverse_hex2int(syni, synl))<0
533 #else
534                 || loopl!=MD5_LEN
535 #endif
536         ) {
537                 DBG("DEBUG: t_reply_matching: poor reply lables %d label %d "
538                         "branch %d\n",hash_index, entry_label, branch_id );
539                 goto nomatch2;
540         }
541
542
543         DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
544                 hash_index, entry_label, branch_id );
545
546
547         /* search the hash table list at entry 'hash_index'; lock the
548            entry first 
549         */
550         lock(&(hash_table->entrys[hash_index].mutex));
551         for (p_cell = hash_table->entrys[hash_index].first_cell; p_cell; 
552                 p_cell=p_cell->next_cell) {
553
554                 /* does method match ? */
555                 if (get_cseq(p_msg)->method.len==
556                           get_cseq(p_cell->uas.request)->method.len 
557                         && get_cseq(p_msg)->method.s[0]==
558                           get_cseq(p_cell->uas.request)->method.s[0]) {
559                                 *local_cancel=0;
560                 /* or is it perhaps a CANCEL ? */
561                 } else if ( p_cell->uas.request->REQ_METHOD==METHOD_INVITE 
562                         && get_cseq(p_msg)->method.len==CANCEL_LEN 
563                         && memcmp( get_cseq(p_msg)->method.s, CANCEL, CANCEL_LEN )==0 
564                         && p_cell->uac[branch_id].request.cancel!=NO_CANCEL 
565                         && p_cell->uac[branch_id].request.cancel!=EXTERNAL_CANCEL ) {
566                                 *local_cancel=1;
567                 } else { /* method mismatched */
568                         continue;
569                 };
570                 #ifdef USE_SYNONIM
571                 if (p_cell->label != entry_label) 
572                         continue;
573                 #else
574                 if ( p_cell->uas.request->add_to_branch_len<MD5_LEN 
575                          || memcmp(p_cell->uas.request->add_to_branch_s,loopi,MD5_LEN)!=0)
576                                 continue;
577                 #endif
578                 /* sanity check ... too high branch ? */
579                 if ( branch_id>=p_cell->nr_of_outgoings )
580                         continue;
581                 /* we passed all disqualifying factors .... the transaction has been
582                    matched !
583                 */
584                 T=p_cell;
585                 *p_branch = branch_id;
586                 T_REF( T );
587                 unlock(&(hash_table->entrys[hash_index].mutex));
588                 DBG("DEBUG: t_reply_matching: reply matched (T=%p,ref=%x)!\n",
589                         T,T->ref_bitmap);
590                 return 1;
591         } /* for cycle */
592
593         /* nothing found */
594         unlock(&(hash_table->entrys[hash_index].mutex));
595         DBG("DEBUG: t_reply_matching: no matching transaction exists\n");
596
597 nomatch2:
598         DBG("DEBUG: t_reply_matching: failure to match a transaction\n");
599         *p_branch = -1;
600         T = 0;
601         return -1;
602 }
603
604
605
606
607 /* Functions update T (T gets either a valid pointer in it or it equals zero) if no transaction
608   * for current message exists;
609   * it returns 1 if found, 0 if not found, -1 on error
610   */
611 int t_check( struct sip_msg* p_msg , int *param_branch, int *param_cancel)
612 {
613         int local_branch;
614         int local_cancel;
615
616         /* is T still up-to-date ? */
617         DBG("DEBUG: t_check: msg id=%d global id=%d T start=%p\n", 
618                 p_msg->id,global_msg_id,T);
619         if ( p_msg->id != global_msg_id || T==T_UNDEFINED )
620         {
621                 global_msg_id = p_msg->id;
622                 T = T_UNDEFINED;
623                 /* transaction lookup */
624                 if ( p_msg->first_line.type==SIP_REQUEST ) {
625                         /* force parsing all the needed headers*/
626                         if (parse_headers(p_msg, HDR_EOH )==-1)
627                                 return -1;
628                         t_lookup_request( p_msg , 0 /* unlock before returning */ );
629                 } else {
630                         if ( parse_headers(p_msg, HDR_VIA1|HDR_TO|HDR_CSEQ )==-1
631                         || !p_msg->via1 || !p_msg->to || !p_msg->cseq )
632                                 return -1;
633                         t_reply_matching( p_msg ,
634                                 ((param_branch!=0)?(param_branch):(&local_branch)),
635                                 ((param_cancel!=0)?(param_cancel):(&local_cancel)));
636
637                 }
638 #ifdef EXTRA_DEBUG
639                 if ( T && T!=T_UNDEFINED && T->damocles) {
640                         LOG( L_ERR, "ERROR: transaction %p scheduled for deletion "
641                                 "and called from t_check\n", T);
642                         abort();
643                 }
644 #endif
645                 DBG("DEBUG: t_check: msg id=%d global id=%d T end=%p\n",
646                         p_msg->id,global_msg_id,T);
647         } else {
648                 if (T)
649                         DBG("DEBUG: t_check: T alredy found!\n");
650                 else
651                         DBG("DEBUG: t_check: T previously sought and not found\n");
652         }
653
654         return ((T)?1:0) ;
655 }
656
657
658
659 /* append appropriate branch labels for fast reply-transaction matching
660    to outgoing requests
661 */
662 int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
663 {
664         char *begin;
665         int size, orig_size;
666
667         /* this is actually a hack made by Bogdan; I wanted to have a structure
668            to which anybody can append some branch stuff which may be utilizied
669            during reply processing; Bogdan ignored that and resets it all the
670            time to construct multiple branches for multiple via's during
671            forking (otherwise, the next branch would be now appended to
672            previous branch)
673
674            keywords: HACK
675         */
676         
677         p_msg->add_to_branch_len = 0; /*bogdan*/
678
679
680         begin=p_msg->add_to_branch_s+p_msg->add_to_branch_len;
681         orig_size = size=MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len;
682
683 #ifndef USE_SYNONIM
684         if (memcpy(begin,trans->md5,MD5_LEN)) {begin+=MD5_LEN;size-=MD5_LEN;} else return -1;
685         if (size) { *begin=BRANCH_SEPARATOR; begin++; size--; } else return -1;
686 #endif
687         if (int2reverse_hex( &begin, &size, trans->hash_index)==-1) return -1;
688 #ifdef USE_SYNONIM
689         if (size) { *begin=BRANCH_SEPARATOR; begin++; size--; } else return -1;
690         if (int2reverse_hex( &begin, &size, trans->label)==-1) return -1;
691 #endif
692         if (size) { *begin=BRANCH_SEPARATOR; begin++; size--; } else return -1;
693         if (int2reverse_hex( &begin, &size, branch)==-1) return -1;
694
695         p_msg->add_to_branch_len+=(orig_size-size);
696         DBG("DEBUG: XXX branch label created now: %.*s\n",
697                 p_msg->add_to_branch_len, p_msg->add_to_branch_s );
698         return 0;
699
700 }
701
702
703 #ifdef _YOU_DONT_REALLY_WANT_THIS
704
705 /* atomic "add_if_new" construct; it returns:
706         AIN_ERROR       if a fatal error (e.g, parsing) occured
707         AIN_RETR        it's a retransmission
708         AIN_NEW         it's a new request
709         AIN_NEWACK      it's an ACK for which no transaction exists
710         AIN_OLDACK      it's an ACK for an existing transaction
711 */
712 enum addifnew_status t_addifnew( struct sip_msg* p_msg )
713 {
714
715         int ret, lret;
716         struct cell *new_cell;
717
718         /* is T still up-to-date ? */
719         DBG("DEBUG: t_addifnew: msg id=%d , global msg id=%d ,"
720                 " T on entrance=%p\n",p_msg->id,global_msg_id,T);
721         if ( p_msg->id != global_msg_id || T==T_UNDEFINED 
722                 /* if someone tried to do something previously by mistake with
723                    a transaction which did not exist yet, try to look-up
724                    the transacion too */
725                 || T==T_NULL)
726         {
727                 global_msg_id = p_msg->id;
728                 T = T_UNDEFINED;
729                 /* transaction lookup */
730                 /* force parsing all the needed headers*/
731                 if (parse_headers(p_msg, HDR_EOH )==-1)
732                         return AIN_ERROR;
733                 lret = t_lookup_request( p_msg, 1 /* leave locked */ );
734                 if (lret==0) return AIN_ERROR;
735                 if (lret==-1) {
736                         /* transaction not found, it's a new request */
737                         if ( p_msg->REQ_METHOD==METHOD_ACK ) {
738                                 ret=AIN_NEWACK;
739                         } else {
740                                 /* add new transaction */
741                                 new_cell = build_cell( p_msg ) ;
742                                 if  ( !new_cell ){
743                                         LOG(L_ERR, "ERROR: t_addifnew: out of mem:\n");
744                                         ret = AIN_ERROR;
745                                 } else {
746                                         insert_into_hash_table_unsafe( hash_table , new_cell );
747                                         ret = AIN_NEW;
748                                         T=new_cell;
749                                         T_REF(T);
750                                 }
751                         }
752                         unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
753                         return ret;
754                 } else {
755                         /* tramsaction found, it's a retransmission  or ACK */
756                         if (p_msg->REQ_METHOD!=METHOD_ACK)
757                                 return AIN_RETR;
758                         else {
759                                 if (T->uas.isACKed)
760                                         return AIN_RTRACK;
761                                 else
762                                         return AIN_OLDACK;
763                                 }
764                         //return p_msg->REQ_METHOD==METHOD_ACK ? AIN_OLDACK : AIN_RETR;
765                 }
766         } else {
767                 if (T)
768                         LOG(L_ERR, "ERROR: t_addifnew: already "
769                         "processing this message, T found!\n");
770                 else
771                         LOG(L_ERR, "ERROR: t_check_new_request: already "
772                         "processing this message, T not found!\n");
773                 return AIN_ERROR;
774         }
775 }
776
777
778 #endif
779
780
781 /* atomic "new_tran" construct; it returns:
782
783         -1      if      a request matched a transaction
784                 - if that was an ack, the calling function
785                   shall reset timers
786                 - otherwise the calling function shall 
787                   attempt to retransmit
788
789         +1      if a request did not match a transaction
790                 - it that was an ack, the calling function
791                   shall forward statelessy
792                 - otherwise it means, a new transaction was
793                   introduced and the calling function
794                   shall reply/relay/whatever_appropriate
795
796         0 on error
797 */
798 int t_newtran( struct sip_msg* p_msg )
799 {
800
801         int ret, lret;
802         struct cell *new_cell;
803
804         /* is T still up-to-date ? */
805         DBG("DEBUG: t_addifnew: msg id=%d , global msg id=%d ,"
806                 " T on entrance=%p\n",p_msg->id,global_msg_id,T);
807
808         if ( !(p_msg->id != global_msg_id || T==T_UNDEFINED 
809                 /* if someone tried to do something previously by mistake with
810                    a transaction which did not exist yet, try to look-up
811                    the transacion too */
812                 || T==T_NULL)) 
813         {
814                 LOG(L_ERR, "ERROR: t_newtran: alreaddy processing this message"
815                         ", T %s found\n", T ? "" : "not" );
816                 return 0;
817         }
818
819         global_msg_id = p_msg->id;
820         T = T_UNDEFINED;
821         /* transaction lookup */
822         /* force parsing all the needed headers*/
823         if (parse_headers(p_msg, HDR_EOH )==-1)
824                 return 0;
825         lret = t_lookup_request( p_msg, 1 /* leave locked */ );
826         /* on error, pass the error in the stack ... */
827         if (lret==0) return 0;
828         if (lret<0) {
829                 /* transaction not found, it's a new request;
830                    establish a new transaction (unless it is an ACK) */
831                 ret=1;
832                 if ( p_msg->REQ_METHOD!=METHOD_ACK ) {
833                         /* add new transaction */
834                         new_cell = build_cell( p_msg ) ;
835                         if  ( !new_cell ){
836                                 LOG(L_ERR, "ERROR: t_addifnew: out of mem:\n");
837                                 ret = 0;
838                         } else {
839                                 insert_into_hash_table_unsafe( hash_table , new_cell );
840                                 T=new_cell;
841                                 T_REF(T);
842                         }
843                 }
844                 unlock(&(hash_table->entrys[p_msg->hash_index].mutex));
845                 /* it that was a presumable e2e ACK, run a callback */
846                 if (lret==-2) callback_event( TMCB_E2EACK, p_msg );
847                 return ret;
848         } else {
849                 /* transaction found, it's a retransmission  or ACK */
850                         return -1;
851         }
852 }
853
854
855