- patch from Miklos Tirpak <miklos@iptel.org>:
[sip-router] / modules / tm / dlg.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *   info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  * History:
28  * -------
29  * 2003-03-29 Created by janakj
30  * 2003-07-08 added wrapper to calculate_hooks, needed by b2bua (dcm)
31  */
32
33
34 #include <string.h>
35 #include "../../mem/shm_mem.h"
36 #include "../../dprint.h"
37 #include "../../parser/contact/parse_contact.h"
38 #include "../../parser/parse_to.h"
39 #include "../../parser/parse_from.h"
40 #include "../../parser/parse_uri.h"
41 #include "../../trim.h"
42 #include "../../ut.h"
43 #include "../../config.h"
44 #include "dlg.h"
45 #include "t_reply.h"
46 #include "../../parser/parser_f.h"
47
48 /* next added to allow automatical tag generation */
49 #include "callid.h"
50 #include "uac.h"
51
52 #define NORMAL_ORDER 0  /* Create route set in normal order - UAS */
53 #define REVERSE_ORDER 1 /* Create route set in reverse order - UAC */
54
55 #define ROUTE_PREFIX "Route: "
56 #define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX) - 1)
57
58 #define ROUTE_SEPARATOR "," CRLF "       "
59 #define ROUTE_SEPARATOR_LEN (sizeof(ROUTE_SEPARATOR) - 1)
60
61
62 /*** Temporary hack ! */
63 /*
64  * This function skips name part
65  * uri parsed by parse_contact must be used
66  * (the uri must not contain any leading or
67  *  trailing part and if angle bracket were
68  *  used, right angle bracket must be the
69  *  last character in the string)
70  *
71  * _s will be modified so it should be a tmp
72  * copy
73  */
74 void get_raw_uri(str* _s)
75 {
76         char* aq;
77         
78         if (_s->s[_s->len - 1] == '>') {
79                 aq = find_not_quoted(_s, '<');
80                 _s->len -= aq - _s->s + 2;
81                 _s->s = aq + 1;
82         }
83 }
84
85
86 /*
87  * Make a copy of a str structure using shm_malloc
88  */
89 static inline int str_duplicate(str* _d, str* _s)
90 {
91         _d->s = shm_malloc(_s->len);
92         if (!_d->s) {
93                 LOG(L_ERR, "str_duplicate(): No memory left\n");
94                 return -1;
95         }
96         
97         memcpy(_d->s, _s->s, _s->len);
98         _d->len = _s->len;
99         return 0;
100 }
101
102
103 /*
104  * Calculate dialog hooks
105  */
106 static inline int calculate_hooks(dlg_t* _d)
107 {
108         str* uri;
109         struct sip_uri puri;
110         param_hooks_t hooks;
111         param_t* params;
112
113         if (_d->route_set) {
114                 uri = &_d->route_set->nameaddr.uri;
115                 if (parse_uri(uri->s, uri->len, &puri) < 0) {
116                         LOG(L_ERR, "calculate_hooks(): Error while parsing URI\n");
117                         return -1;
118                 }
119
120                 if (parse_params(&puri.params, CLASS_URI, &hooks, &params) < 0) {
121                         LOG(L_ERR, "calculate_hooks(): Error while parsing parameters\n");
122                         return -2;
123                 }
124                 free_params(params);
125                 
126                 if (hooks.uri.lr) {
127                         if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
128                         else _d->hooks.request_uri = &_d->rem_uri;
129                         _d->hooks.next_hop = &_d->route_set->nameaddr.uri;
130                         _d->hooks.first_route = _d->route_set;
131                 } else {
132                         _d->hooks.request_uri = &_d->route_set->nameaddr.uri;
133                         _d->hooks.next_hop = _d->hooks.request_uri;
134                         _d->hooks.first_route = _d->route_set->next;
135                         if (_d->rem_target.len > 0) 
136                                 _d->hooks.last_route = &_d->rem_target;
137                         else 
138                                 _d->hooks.last_route = NULL; /* ? */
139                 }
140         } else {
141                 if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
142                 else _d->hooks.request_uri = &_d->rem_uri;
143                 
144                 if (_d->dst_uri.s) _d->hooks.next_hop = &_d->dst_uri;
145                 else _d->hooks.next_hop = _d->hooks.request_uri;
146         }
147
148         if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) {
149                 _d->hooks.ru.s = _d->hooks.request_uri->s;
150                 _d->hooks.ru.len = _d->hooks.request_uri->len;
151                 _d->hooks.request_uri = &_d->hooks.ru;
152                 get_raw_uri(_d->hooks.request_uri);
153         }
154         if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) {
155                 _d->hooks.nh.s = _d->hooks.next_hop->s;
156                 _d->hooks.nh.len = _d->hooks.next_hop->len;
157                 _d->hooks.next_hop = &_d->hooks.nh;
158                 get_raw_uri(_d->hooks.next_hop);
159         }
160
161         return 0;
162 }
163
164 /*
165  * wrapper to calculate_hooks
166  * added by dcm
167  */
168 int w_calculate_hooks(dlg_t* _d)
169 {
170         return calculate_hooks(_d);
171 }
172
173 /*
174  * Create a new dialog
175  */
176 int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d)
177 {
178         dlg_t* res;
179         str generated_cid;
180         str generated_ltag;
181
182         if (!_cid) { /* if not given, compute new one */
183                 generate_callid(&generated_cid);
184                 _cid = &generated_cid;
185         }
186         if (_cid && (!_ltag)) { /* if not given, compute new one */
187                 generate_fromtag(&generated_ltag, _cid);
188                 _ltag = &generated_ltag;
189         }
190         if (_lseq == 0) _lseq = DEFAULT_CSEQ;
191
192         if (!_cid || !_ltag || !_luri || !_ruri || !_d) {
193                 LOG(L_ERR, "new_dlg_uac(): Invalid parameter value\n");
194                 return -1;
195         }
196
197         res = (dlg_t*)shm_malloc(sizeof(dlg_t));
198         if (res == 0) {
199                 LOG(L_ERR, "new_dlg_uac(): No memory left\n");
200                 return -2;
201         }
202
203              /* Clear everything */     
204         memset(res, 0, sizeof(dlg_t));
205         
206              /* Make a copy of Call-ID */
207         if (str_duplicate(&res->id.call_id, _cid) < 0) return -3;
208              /* Make a copy of local tag (usually From tag) */
209         if (str_duplicate(&res->id.loc_tag, _ltag) < 0) return -4;
210              /* Make a copy of local URI (usually From) */
211         if (str_duplicate(&res->loc_uri, _luri) < 0) return -5;
212              /* Make a copy of remote URI (usually To) */
213         if (str_duplicate(&res->rem_uri, _ruri) < 0) return -6;
214              /* Make a copy of local sequence (usually CSeq) */
215         res->loc_seq.value = _lseq;
216              /* And mark it as set */
217         res->loc_seq.is_set = 1;
218
219         *_d = res;
220
221         if (calculate_hooks(*_d) < 0) {
222                 LOG(L_ERR, "new_dlg_uac(): Error while calculating hooks\n");
223                 /* FIXME: free everything here */
224                 shm_free(res);
225                 return -2;
226         }
227         
228         return 0;
229 }
230
231
232 /*
233  * Parse Contact header field body and extract URI
234  * Does not parse headers !!
235  */
236 static inline int get_contact_uri(struct sip_msg* _m, str* _uri)
237 {
238         contact_t* c;
239
240         _uri->len = 0;
241         _uri->s = 0;
242
243         if (!_m->contact) return 1;
244
245         if (parse_contact(_m->contact) < 0) {
246                 LOG(L_ERR, "get_contact_uri(): Error while parsing Contact body\n");
247                 return -2;
248         }
249
250         c = ((contact_body_t*)_m->contact->parsed)->contacts;
251
252         if (!c) {
253                 LOG(L_ERR, "get_contact_uri(): Empty body or * contact\n");
254                 return -3;
255         }
256
257         _uri->s = c->uri.s;
258         _uri->len = c->uri.len;
259         return 0;
260 }
261
262
263 /*
264  * Extract tag from To header field of a response
265  * Doesn't parse message headers !!
266  */
267 static inline int get_to_tag(struct sip_msg* _m, str* _tag)
268 {
269         if (!_m->to) {
270                 LOG(L_ERR, "get_to_tag(): To header field missing\n");
271                 return -1;
272         }
273
274         if (get_to(_m)->tag_value.len) {
275                 _tag->s = get_to(_m)->tag_value.s;
276                 _tag->len = get_to(_m)->tag_value.len;
277         } else {
278                 _tag->len = 0;
279         }
280
281         return 0;
282 }
283
284
285 /*
286  * Extract tag from From header field of a request
287  */
288 static inline int get_from_tag(struct sip_msg* _m, str* _tag)
289 {
290         if (parse_from_header(_m) == -1) {
291                 LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");
292                 return -1;
293         }
294
295         if (get_from(_m)->tag_value.len) {
296                 _tag->s = get_from(_m)->tag_value.s;
297                 _tag->len = get_from(_m)->tag_value.len;
298         } else {
299                 _tag->len = 0;
300         }
301
302         return 0;
303 }
304
305
306 /*
307  * Extract Call-ID value
308  * Doesn't parse headers !!
309  */
310 static inline int get_callid(struct sip_msg* _m, str* _cid)
311 {
312         if (_m->callid == 0) {
313                 LOG(L_ERR, "get_callid(): Call-ID not found\n");
314                 return -1;
315         }
316
317         _cid->s = _m->callid->body.s;
318         _cid->len = _m->callid->body.len;
319         trim(_cid);
320         return 0;
321 }
322
323 static rr_t *revert_route(rr_t *r)
324 {
325         rr_t *a, *b;
326
327         a = NULL;
328
329         while (r) {
330                 b = r->next;
331                 r->next = a;
332                 a = r;
333                 r = b;
334         }
335
336         return a;
337 }
338
339 /*
340  * Create a copy of route set either in normal or reverse order
341  */
342 static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order)
343 {
344         struct hdr_field* ptr;
345         rr_t* last, *p, *t;
346         
347         last = 0;
348
349         ptr = _m->record_route;
350         while(ptr) {
351                 if (ptr->type == HDR_RECORDROUTE_T) {
352                         if (parse_rr(ptr) < 0) {
353                                 LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n");
354                                 goto error;
355                         }
356
357                         p = (rr_t*)ptr->parsed;
358                         if (shm_duplicate_rr(&t, p) < 0) {
359                                 LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
360                                 goto error;
361                         }
362                         if (!*_rs) *_rs = t;
363                         if (last) last->next = t;
364                         last = t;
365                         while (last->next) last = last->next; /* !!! there may be more routes in one hdr field !!! */
366
367                 }
368                 ptr = ptr->next;
369         }
370         if ((*_rs) && (_order != NORMAL_ORDER)) {
371                 /* better to revert the route outside of cycle above */
372                 *_rs = revert_route(*_rs);
373         }
374         
375         return 0;
376
377  error:
378         shm_free_rr(_rs);
379         return -1;
380 }
381
382 /*
383  * Extract method from CSeq header field
384  */
385 static inline int get_cseq_method(struct sip_msg* _m, str* _method)
386 {
387         if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ_F, 0) == -1) || !_m->cseq)) {
388                 LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
389                 return -1;
390         }
391
392         _method->s = get_cseq(_m)->method.s;
393         _method->len = get_cseq(_m)->method.len;
394         return 0;
395 }
396
397
398 static inline int refresh_dialog_resp(struct sip_msg* _m, 
399                 target_refresh_t is_target_refresh)
400 {
401         str method;
402         
403         switch (is_target_refresh) {
404                 case IS_NOT_TARGET_REFRESH: 
405                         return 0;
406                 case IS_TARGET_REFRESH: 
407                         return 1;
408                 case TARGET_REFRESH_UNKNOWN: 
409                         if (get_cseq_method(_m, &method) < 0) return 0; /* error */
410                         if ((method.len == 6) && !memcmp("INVITE", method.s, 6)) 
411                                 return 1;
412                         else return 0;
413         }
414         return 0;
415 }
416                 
417 static inline int refresh_dialog_req(struct sip_msg* _m, target_refresh_t is_target_refresh)
418 {
419         switch (is_target_refresh) {
420                 case IS_NOT_TARGET_REFRESH: 
421                         return 0;
422                 case IS_TARGET_REFRESH: 
423                         return 1;
424                 case TARGET_REFRESH_UNKNOWN: 
425                         return (_m->first_line.u.request.method_value == METHOD_INVITE);
426                         break;
427         }
428         return 0;
429 }
430
431 /*
432  * Extract all necessary information from a response and put it
433  * in a dialog structure
434  */
435 static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
436 {
437         str contact, rtag;
438
439              /* Parse the whole message, we will need all Record-Route headers */
440         if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
441                 LOG(L_ERR, "response2dlg(): Error while parsing headers\n");
442                 return -1;
443         }
444         
445         if (get_contact_uri(_m, &contact) < 0) return -2;
446         if (_d->rem_target.s) {
447                 shm_free(_d->rem_target.s);
448                 _d->rem_target.s = 0; 
449                 _d->rem_target.len = 0;
450         }
451         if (_d->dst_uri.s) {
452                 shm_free(_d->dst_uri.s);
453                 _d->dst_uri.s = 0; 
454                 _d->dst_uri.len = 0;
455         }
456         if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
457         
458         if (get_to_tag(_m, &rtag) < 0) goto err1;
459         if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
460         
461         if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2;
462
463         return 0;
464  err2:
465         if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
466         _d->id.rem_tag.s = 0;
467         _d->id.rem_tag.len = 0;
468
469  err1:
470         if (_d->rem_target.s) shm_free(_d->rem_target.s);
471         _d->rem_target.s = 0;
472         _d->rem_target.len = 0;
473         return -4;
474 }
475
476
477 /*
478  * Handle dialog in DLG_NEW state, we will be processing the
479  * first response
480  */
481 static inline int dlg_new_resp_uac(dlg_t* _d, struct sip_msg* _m)
482 {
483         int code;
484              /*
485               * Dialog is in DLG_NEW state, we will copy remote
486               * target URI, remote tag if present, and route-set 
487               * if present. And we will transit into DLG_CONFIRMED 
488               * if the response was 2xx and to DLG_DESTROYED if the 
489               * request was a negative final response.
490               */
491
492         code = _m->first_line.u.reply.statuscode;
493
494         if (code < 200) {
495                      /* A provisional response, do nothing, we could
496                       * update remote tag and route set but we will do that
497                       * for a positive final response anyway and I don't want
498                       * bet on presence of these fields in provisional responses
499                       *
500                       * Send a request to jan@iptel.org if you need to update
501                       * the structures here
502                       */
503         } else if ((code >= 200) && (code < 299)) {
504                      /* A final response, update the structures and transit
505                       * into DLG_CONFIRMED
506                       */
507                 if (response2dlg(_m, _d) < 0) return -1;
508                 _d->state = DLG_CONFIRMED;
509
510                 if (calculate_hooks(_d) < 0) {
511                         LOG(L_ERR, "dlg_new_resp_uac(): Error while calculating hooks\n");
512                         return -2;
513                 }
514         } else {
515                      /* 
516                       * A negative final response, mark the dialog as destroyed
517                       * Again, I do not update the structures here because it
518                       * makes no sense to me, a dialog shouldn't be used after
519                       * it is destroyed
520                       */
521                 _d->state = DLG_DESTROYED;
522                      /* Signalize the termination with positive return value */
523                 return 1;
524         }
525
526         return 0;
527 }
528
529
530 /*
531  * Handle dialog in DLG_EARLY state, we will be processing either
532  * next provisional response or a final response
533  */
534 static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
535 {
536         int code;
537         code = _m->first_line.u.reply.statuscode;       
538
539         if (code < 200) {
540                      /* We are in early state already, do nothing
541                       */
542         } else if ((code >= 200) && (code <= 299)) {
543                 /* Warning - we can handle here response for non-initial request (for
544                  * example UPDATE within early INVITE/BYE dialog) and move into
545                  * confirmed state may be error! But this depends on dialog type... */
546                 
547                      /* Same as in dlg_new_resp_uac */
548                      /* A final response, update the structures and transit
549                       * into DLG_CONFIRMED
550                       */
551                 if (response2dlg(_m, _d) < 0) return -1;
552                 _d->state = DLG_CONFIRMED;
553
554                 if (calculate_hooks(_d) < 0) {
555                         LOG(L_ERR, "dlg_early_resp_uac(): Error while calculating hooks\n");
556                         return -2;
557                 }
558         } else {
559                      /* Else terminate the dialog */
560                 _d->state = DLG_DESTROYED;
561                      /* Signalize the termination with positive return value */
562                 return 1;
563         }
564
565         return 0;
566 }
567
568
569 /*
570  * Handle dialog in DLG_CONFIRMED state, we will be processing
571  * a response to a request sent within a dialog
572  */
573 static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m, 
574                 target_refresh_t is_target_refresh)
575 {
576         int code;
577         str contact;
578
579         code = _m->first_line.u.reply.statuscode;       
580
581              /* Dialog has been already confirmed, that means we received
582               * a response to a request sent within the dialog. We will
583               * update remote target URI if and only if the message sent was
584               * a target refresher. 
585               */
586
587              /* IF we receive a 481 response, terminate the dialog because
588               * the remote peer indicated that it didn't have the dialog
589               * state anymore, signal this termination with a positive return
590               * value
591               */
592         if (code == 481) {
593                 _d->state = DLG_DESTROYED;
594                 return 1;
595         }
596
597              /* Do nothing if not 2xx */
598         if ((code < 200) || (code >= 300)) return 0;
599         
600         if (refresh_dialog_resp(_m, is_target_refresh)) {
601                      /* Get contact if any and update remote target */
602                 if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
603                         LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
604                         return -2;
605                 }
606
607                      /* Try to extract contact URI */
608                 if (get_contact_uri(_m, &contact) < 0) return -3;
609                      /* If there is a contact URI */
610                 if (contact.len) {
611                              /* Free old remote target and destination uri if any */
612                         if (_d->rem_target.s) shm_free(_d->rem_target.s);
613                         if (_d->dst_uri.s) {
614                                 shm_free(_d->dst_uri.s);
615                                 _d->dst_uri.s = 0;
616                                 _d->dst_uri.len = 0;
617                         }
618                                 
619                              /* Duplicate new remote target */
620                         if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
621                 }
622
623                 calculate_hooks(_d);
624         }
625
626         return 0;
627 }
628
629
630 /*
631  * A response arrived, update dialog
632  */
633 int dlg_response_uac(dlg_t* _d, struct sip_msg* _m, 
634                 target_refresh_t is_target_refresh)
635 {
636         if (!_d || !_m) {
637                 LOG(L_ERR, "dlg_response_uac(): Invalid parameter value\n");
638                 return -1;
639         }
640
641              /* The main dispatcher */
642         switch(_d->state) {
643         case DLG_NEW:       
644                 return dlg_new_resp_uac(_d, _m);
645
646         case DLG_EARLY:     
647                 return dlg_early_resp_uac(_d, _m);
648
649         case DLG_CONFIRMED: 
650                 return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
651
652         case DLG_DESTROYED:
653                 LOG(L_DBG, "dlg_response_uac(): Cannot handle destroyed dialog\n");
654                 return -2;
655         }
656
657         LOG(L_ERR, "dlg_response_uac(): Error in switch statement\n");
658         return -3;
659 }
660
661
662 /*
663  * Get CSeq number
664  * Does not parse headers !!
665  */
666 static inline int get_cseq_value(struct sip_msg* _m, unsigned int* _cs)
667 {
668         str num;
669
670         if (_m->cseq == 0) {
671                 LOG(L_ERR, "get_cseq_value(): CSeq header not found\n");
672                 return -1;
673         }
674
675         num.s = get_cseq(_m)->number.s;
676         num.len = get_cseq(_m)->number.len;
677
678         trim_leading(&num);
679         if (str2int(&num, _cs) < 0) {
680                 LOG(L_ERR, "get_cseq_value(): Error while converting cseq number\n");
681                 return -2;
682         }
683         return 0;
684 }
685
686
687 /*
688  * Copy To or From URI without tag parameter
689  */
690 static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
691 {
692         struct to_param* ptr, *prev;
693         struct to_body* body;
694         char* tag = 0; /* Makes gcc happy */
695         int tag_len = 0, len;
696
697         if (!_h) {
698                 LOG(L_ERR, "get_dlg_uri(): Header field not found\n");
699                 return -1;
700         }
701
702              /* From was already parsed when extracting tag
703               * and To is parsed by default
704               */
705         
706         body = (struct to_body*)_h->parsed;
707
708         ptr = body->param_lst;
709         prev = 0;
710         while(ptr) {
711                 if (ptr->type == TAG_PARAM) break;
712                 prev = ptr;
713                 ptr = ptr->next;
714         }
715
716         if (ptr) {
717                      /* Tag param found */
718                 if (prev) {
719                         tag = prev->value.s + prev->value.len;
720                 } else {
721                         tag = body->body.s + body->body.len;
722                 }
723                 
724                 if (ptr->next) {
725                         tag_len = ptr->value.s + ptr->value.len - tag;
726                 } else {
727                         tag_len = _h->body.s + _h->body.len - tag;
728                 }
729         }
730
731         _s->s = shm_malloc(_h->body.len - tag_len);
732         if (!_s->s) {
733                 LOG(L_ERR, "get_dlg_uri(): No memory left\n");
734                 return -1;
735         }
736
737         if (tag_len) {
738                 len = tag - _h->body.s;
739                 memcpy(_s->s, _h->body.s, len);
740                 memcpy(_s->s + len, tag + tag_len, _h->body.len - len - tag_len);
741                 _s->len = _h->body.len - tag_len;
742         } else {
743                 memcpy(_s->s, _h->body.s, _h->body.len);
744                 _s->len = _h->body.len;
745         }
746
747         return 0;
748 }
749
750
751 /*
752  * Extract all information from a request 
753  * and update a dialog structure
754  */
755 static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
756 {
757         str contact, rtag, callid;
758
759         if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
760                 LOG(L_ERR, "request2dlg(): Error while parsing headers");
761                 return -1;
762         }
763
764         if (get_contact_uri(_m, &contact) < 0) return -2;
765         if (contact.len) {
766                 if (_d->rem_target.s) shm_free(_d->rem_target.s);
767                 if (_d->dst_uri.s) {
768                         shm_free(_d->dst_uri.s);
769                         _d->dst_uri.s = 0;
770                         _d->dst_uri.len = 0;
771                 }
772                 if (str_duplicate(&_d->rem_target, &contact) < 0) return -3;
773         }
774         
775         if (get_from_tag(_m, &rtag) < 0) goto err1;
776         if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
777
778         if (get_callid(_m, &callid) < 0) goto err2;
779         if (callid.len && str_duplicate(&_d->id.call_id, &callid) < 0) goto err2;
780
781         if (get_cseq_value(_m, &_d->rem_seq.value) < 0) goto err3;
782         _d->rem_seq.is_set = 1;
783
784         if (get_dlg_uri(_m->from, &_d->rem_uri) < 0) goto err3;
785         if (get_dlg_uri(_m->to, &_d->loc_uri) < 0) goto err4;
786
787         if (get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0) goto err5;     
788
789         return 0;
790  err5:
791         if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
792         _d->loc_uri.s = 0;
793         _d->loc_uri.len = 0;
794  err4:
795         if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
796         _d->rem_uri.s = 0;
797         _d->rem_uri.len = 0;
798  err3:
799         if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
800         _d->id.call_id.s = 0;
801         _d->id.call_id.len = 0;
802  err2:
803         if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
804         _d->id.rem_tag.s = 0;
805         _d->id.rem_tag.len = 0;
806  err1:
807         if (_d->rem_target.s) shm_free(_d->rem_target.s);
808         _d->rem_target.s = 0;
809         _d->rem_target.len = 0;
810         return -4;
811 }
812
813
814 /*
815  * Establishing a new dialog, UAS side
816  */
817 int new_dlg_uas(struct sip_msg* _req, int _code, /*str* _tag,*/ dlg_t** _d)
818 {
819         dlg_t* res;
820         str tag;
821
822         if (!_req || /*!_tag ||*/ !_d) {
823                 LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n");
824                 return -1;
825         }
826
827         if (_code > 299) {
828                 DBG("new_dlg_uas(): Status code >= 300, no dialog created\n");
829         }
830
831         res = (dlg_t*)shm_malloc(sizeof(dlg_t));
832         if (res == 0) {
833                 LOG(L_ERR, "new_dlg_uac(): No memory left\n");
834                 return -3;
835         }
836              /* Clear everything */
837         memset(res, 0, sizeof(dlg_t));  
838
839         if (request2dlg(_req, res) < 0) {
840                 LOG(L_ERR, "new_dlg_uas(): Error while converting request to dialog\n");
841                 free_dlg(res);
842                 return -4;
843         }
844
845         if (_code > 100) {
846                 tag.s = tm_tags;
847                 tag.len = TOTAG_VALUE_LEN;
848                 calc_crc_suffix(_req, tm_tag_suffix);
849                 if (str_duplicate(&res->id.loc_tag, &tag) < 0) {
850                         free_dlg(res);
851                         return -5;
852                 }
853         }
854         
855         *_d = res;
856
857         if (_code < 100)
858                 (*_d)->state = DLG_NEW;
859         else if (_code < 200)
860                 (*_d)->state = DLG_EARLY;
861         else
862                 (*_d)->state = DLG_CONFIRMED;
863
864         if (calculate_hooks(*_d) < 0) {
865                 LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n");
866                 free_dlg(res);
867                 return -6;
868         }
869
870         return 0;
871 }
872
873 /*
874  * UAS side - update dialog state and to tag
875  */
876 int update_dlg_uas(dlg_t *_d, int _code, str* _tag)
877 {
878         if (_d->state == DLG_CONFIRMED) {
879                 LOG(L_ERR, "update_dlg_uas(): Dialog is already confirmed\n");
880                 return -1;
881         } else if (_d->state == DLG_DESTROYED) {
882                 LOG(L_ERR, "update_dlg_uas(): Dialog is already destroyed\n");
883                 return -2;
884         }
885
886         if (_tag && _tag->s) {
887                 if (_d->id.loc_tag.s) {
888                         if ((_tag->len == _d->id.loc_tag.len)
889                         && (!memcmp(_tag->s, _d->id.loc_tag.s, _tag->len))) {
890                                 LOG(L_DBG, "update_dlg_uas(): Local tag is already set\n");
891                         } else {
892                                 LOG(L_ERR, "update_dlg_uas(): ERROR: trying to rewrite local tag\n");
893                                 return -3;
894                         }
895                 } else {
896                         if (str_duplicate(&_d->id.loc_tag, _tag) < 0) {
897                                 LOG(L_ERR, "update_dlg_uas(): Not enough memory\n");
898                                 return -4;
899                         }
900                 }
901         }
902
903         if ((100 < _code) && (_code < 200))
904                 _d->state = DLG_EARLY;
905         else if (_code < 300)
906                 _d->state = DLG_CONFIRMED;
907         else
908                 _d->state = DLG_DESTROYED;
909
910         return 0;
911 }
912
913 /*
914  * UAS side - update a dialog from a request
915  */
916 int dlg_request_uas(dlg_t* _d, struct sip_msg* _m, target_refresh_t is_target_refresh)
917 {
918         str contact;
919         int cseq;
920
921         if (!_d || !_m) {
922                 LOG(L_ERR, "dlg_request_uas(): Invalid parameter value\n");
923                 return -1;
924         }
925
926              /* We must check if the request is not out of order or retransmission
927               * first, if so then we will not update anything
928               */
929         if (parse_headers(_m, HDR_CSEQ_F, 0) == -1) {
930                 LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
931                 return -2;
932         }
933         if (get_cseq_value(_m, (unsigned int*)&cseq) < 0) return -3;
934         if (_d->rem_seq.is_set && (cseq <= _d->rem_seq.value)) return 0;
935
936              /* Neither out of order nor retransmission -> update */
937         _d->rem_seq.value = cseq;
938         _d->rem_seq.is_set = 1;
939         
940              /* We will als update remote target URI if the message 
941               * is target refresher
942               */
943         if (refresh_dialog_req(_m, is_target_refresh)) { /* target refresher */
944                 if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
945                         LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
946                         return -4;
947                 }
948                 
949                 if (get_contact_uri(_m, &contact) < 0) return -5;
950                 if (contact.len) {
951                         if (_d->rem_target.s) shm_free(_d->rem_target.s);
952                         if (_d->dst_uri.s) {
953                                 shm_free(_d->dst_uri.s);
954                                 _d->dst_uri.s = 0;
955                                 _d->dst_uri.len = 0;
956                         }
957                         if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
958                 }
959
960                 calculate_hooks(_d);
961                 
962         }
963
964         return 0;
965 }
966
967
968 /*
969  * Calculate length of the route set
970  */
971 int calculate_routeset_length(dlg_t* _d)
972 {
973         int len;
974         rr_t* ptr;
975
976         len = 0;
977         ptr = _d->hooks.first_route;
978
979         if (ptr) {
980                 len = ROUTE_PREFIX_LEN;
981                 len += CRLF_LEN;
982         }
983
984         while(ptr) {
985                 len += ptr->len;
986                 ptr = ptr->next;
987                 if (ptr) len += ROUTE_SEPARATOR_LEN;
988         } 
989
990         if (_d->hooks.last_route) {
991                 len += ROUTE_SEPARATOR_LEN + 2; /* < > */
992                 len += _d->hooks.last_route->len;
993         }
994
995         return len;
996 }
997
998
999 /*
1000  *
1001  * Print the route set
1002  */
1003 char* print_routeset(char* buf, dlg_t* _d)
1004 {
1005         rr_t* ptr;
1006
1007         ptr = _d->hooks.first_route;
1008
1009         if (ptr || _d->hooks.last_route) {
1010                 memcpy(buf, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
1011                 buf += ROUTE_PREFIX_LEN;
1012         }
1013
1014         while(ptr) {
1015                 memcpy(buf, ptr->nameaddr.name.s, ptr->len);
1016                 buf += ptr->len;
1017
1018                 ptr = ptr->next;
1019                 if (ptr) {
1020                         memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
1021                         buf += ROUTE_SEPARATOR_LEN;
1022                 }
1023         } 
1024
1025         if (_d->hooks.last_route) {
1026                 if (_d->hooks.first_route) {
1027                         memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
1028                         buf += ROUTE_SEPARATOR_LEN;
1029                 }
1030                 memcpy(buf, "<", 1);
1031                 buf++;
1032                 memcpy(buf, _d->hooks.last_route->s, _d->hooks.last_route->len);
1033                 buf += _d->hooks.last_route->len;
1034                 *buf = '>';
1035                 buf++;
1036         }
1037
1038         if (_d->hooks.first_route || _d->hooks.last_route) {
1039                 memcpy(buf, CRLF, CRLF_LEN);
1040                 buf += CRLF_LEN;
1041         }
1042
1043         return buf;
1044 }
1045
1046
1047 /*
1048  * Destroy a dialog state
1049  */
1050 void free_dlg(dlg_t* _d)
1051 {
1052         if (!_d) return;
1053
1054         if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
1055         if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
1056         if (_d->id.loc_tag.s) shm_free(_d->id.loc_tag.s);
1057
1058         if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
1059         if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
1060         if (_d->rem_target.s) shm_free(_d->rem_target.s);
1061         if (_d->dst_uri.s) shm_free(_d->dst_uri.s);
1062
1063              /* Free all routes in the route set */
1064         shm_free_rr(&_d->route_set);
1065         shm_free(_d);
1066 }
1067
1068
1069 /*
1070  * Print a dialog structure, just for debugging
1071  */
1072 void print_dlg(FILE* out, dlg_t* _d)
1073 {
1074         fprintf(out, "====dlg_t===\n");
1075         fprintf(out, "id.call_id    : '%.*s'\n", _d->id.call_id.len, _d->id.call_id.s);
1076         fprintf(out, "id.rem_tag    : '%.*s'\n", _d->id.rem_tag.len, _d->id.rem_tag.s);
1077         fprintf(out, "id.loc_tag    : '%.*s'\n", _d->id.loc_tag.len, _d->id.loc_tag.s);
1078         fprintf(out, "loc_seq.value : %d\n", _d->loc_seq.value);
1079         fprintf(out, "loc_seq.is_set: %s\n", _d->loc_seq.is_set ? "YES" : "NO");
1080         fprintf(out, "rem_seq.value : %d\n", _d->rem_seq.value);
1081         fprintf(out, "rem_seq.is_set: %s\n", _d->rem_seq.is_set ? "YES" : "NO");
1082         fprintf(out, "loc_uri       : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
1083         fprintf(out, "rem_uri       : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
1084         fprintf(out, "rem_target    : '%.*s'\n", _d->rem_target.len, _d->rem_target.s);
1085         fprintf(out, "dst_uri       : '%.*s'\n", _d->dst_uri.len, _d->dst_uri.s);
1086         fprintf(out, "secure:       : %d\n", _d->secure);
1087         fprintf(out, "state         : ");
1088         switch(_d->state) {
1089         case DLG_NEW:       fprintf(out, "DLG_NEW\n");       break;
1090         case DLG_EARLY:     fprintf(out, "DLG_EARLY\n");     break;
1091         case DLG_CONFIRMED: fprintf(out, "DLG_CONFIRMED\n"); break;
1092         case DLG_DESTROYED: fprintf(out, "DLG_DESTROYED\n"); break;
1093         }
1094         print_rr(out, _d->route_set);
1095         if (_d->hooks.request_uri) 
1096                 fprintf(out, "hooks.request_uri: '%.*s'\n", _d->hooks.request_uri->len, _d->hooks.request_uri->s);
1097         if (_d->hooks.next_hop) 
1098                 fprintf(out, "hooks.next_hop   : '%.*s'\n", _d->hooks.next_hop->len, _d->hooks.next_hop->s);
1099         if (_d->hooks.first_route) 
1100                 fprintf(out, "hooks.first_route: '%.*s'\n", _d->hooks.first_route->len, _d->hooks.first_route->nameaddr.name.s);
1101         if (_d->hooks.last_route)
1102                 fprintf(out, "hooks.last_route : '%.*s'\n", _d->hooks.last_route->len, _d->hooks.last_route->s);
1103         
1104         fprintf(out, "====dlg_t====\n");
1105 }
1106
1107 /*
1108  * set dialog's request uri and destination uri (optional)
1109  */
1110 int set_dlg_target(dlg_t* _d, str* _ruri, str* _duri) {
1111
1112         if (!_d || !_ruri) {
1113                 LOG(L_ERR, "set_dlg_target(): Invalid parameter value\n");
1114                 return -1;
1115         }
1116
1117         if (_d->rem_target.s) shm_free(_d->rem_target.s);
1118         if (_d->dst_uri.s) {
1119                 shm_free(_d->dst_uri.s);
1120                 _d->dst_uri.s = 0;
1121                 _d->dst_uri.len = 0;
1122         }
1123
1124         if (str_duplicate(&_d->rem_target, _ruri)) return -1;
1125         if (_duri && _duri->len) {
1126                 if (str_duplicate(&_d->dst_uri, _duri)) return -1;
1127         }
1128
1129         if (calculate_hooks(_d)) {
1130                 LOG(L_ERR, "set_dlg_target(): Error while calculating hooks\n");
1131                 return -1;
1132         }
1133
1134         return 0;
1135 }