c7244dd12d36bc1f4d6ccccd12236c87a77ed574
[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  */
31
32
33 #include <string.h>
34 #include "../../mem/shm_mem.h"
35 #include "../../dprint.h"
36 #include "../../parser/contact/parse_contact.h"
37 #include "../../parser/parse_to.h"
38 #include "../../parser/parse_from.h"
39 #include "../../parser/parse_uri.h"
40 #include "../../trim.h"
41 #include "../../ut.h"
42 #include "../../config.h"
43 #include "dlg.h"
44
45
46 #define NORMAL_ORDER 0  /* Create route set in normal order - UAS */
47 #define REVERSE_ORDER 1 /* Create route set in reverse order - UAC */
48
49 #define ROUTE_PREFIX "Route: "
50 #define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX) - 1)
51
52 #define ROUTE_SEPARATOR "," CRLF "       "
53 #define ROUTE_SEPARATOR_LEN (sizeof(ROUTE_SEPARATOR) - 1)
54
55
56 /*
57  * Make a copy of a str structure using shm_malloc
58  */
59 static inline int str_duplicate(str* _d, str* _s)
60 {
61         _d->s = shm_malloc(_s->len);
62         if (!_d->s) {
63                 LOG(L_ERR, "str_duplicate(): No memory left\n");
64                 return -1;
65         }
66         
67         memcpy(_d->s, _s->s, _s->len);
68         _d->len = _s->len;
69         return 0;
70 }
71
72
73 /*
74  * Calculate dialog hooks
75  */
76 static inline int calculate_hooks(dlg_t* _d)
77 {
78         str* uri;
79         struct sip_uri puri;
80         param_hooks_t hooks;
81         param_t* params;
82
83         if (_d->route_set) {
84                 uri = &_d->route_set->nameaddr.uri;
85                 if (parse_uri(uri->s, uri->len, &puri) < 0) {
86                         LOG(L_ERR, "calculate_hooks(): Error while parsing URI\n");
87                         return -1;
88                 }
89
90                 if (parse_params(&puri.params, CLASS_URI, &hooks, &params) < 0) {
91                         LOG(L_ERR, "calculate_hooks(): Error while parsing parameters\n");
92                         return -2;
93                 }
94                 free_params(params);
95                 
96                 if (hooks.uri.lr) {
97                         if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
98                         else _d->hooks.request_uri = &_d->rem_uri;
99                         _d->hooks.next_hop = &_d->route_set->nameaddr.uri;
100                         _d->hooks.first_route = _d->route_set;
101                 } else {
102                         _d->hooks.request_uri = &_d->route_set->nameaddr.uri;
103                         _d->hooks.next_hop = _d->hooks.request_uri;
104                         _d->hooks.first_route = _d->route_set->next;
105                         _d->hooks.last_route = &_d->rem_target;
106                 }
107         } else {
108                 if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
109                 else _d->hooks.request_uri = &_d->rem_uri;
110                 _d->hooks.next_hop = _d->hooks.request_uri;
111         }
112
113         return 0;
114 }
115
116
117 /*
118  * Create a new dialog
119  */
120 int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d)
121 {
122         dlg_t* res;
123
124         if (!_cid || !_ltag || !_luri || !_ruri || !_d) {
125                 LOG(L_ERR, "new_dlg_uac(): Invalid parameter value\n");
126                 return -1;
127         }
128
129         res = (dlg_t*)shm_malloc(sizeof(dlg_t));
130         if (res == 0) {
131                 LOG(L_ERR, "new_dlg_uac(): No memory left\n");
132                 return -2;
133         }
134              /* Clear everything */
135         memset(res, 0, sizeof(dlg_t));
136         
137              /* Make a copy of Call-ID */
138         if (str_duplicate(&res->id.call_id, _cid) < 0) return -3;
139              /* Make a copy of local tag (usually From tag) */
140         if (str_duplicate(&res->id.loc_tag, _ltag) < 0) return -4;
141              /* Make a copy of local URI (usually From) */
142         if (str_duplicate(&res->loc_uri, _luri) < 0) return -5;
143              /* Make a copy of remote URI (usually To) */
144         if (str_duplicate(&res->rem_uri, _ruri) < 0) return -6;
145              /* Make a copy of local sequence (usually CSeq) */
146         res->loc_seq.value = _lseq;
147              /* And mark it as set */
148         res->loc_seq.is_set = 1;
149
150         *_d = res;
151
152         if (calculate_hooks(*_d) < 0) {
153                 LOG(L_ERR, "new_dlg_uac(): Error while calculating hooks\n");
154                 shm_free(res);
155                 return -2;
156         }
157
158         return 0;
159 }
160
161
162 /*
163  * Parse Contact header field body and extract URI
164  * Does not parse headers !!
165  */
166 static inline int get_contact_uri(struct sip_msg* _m, str* _uri)
167 {
168         contact_t* c;
169
170         _uri->len = 0;
171
172         if (!_m->contact) return 0;
173
174         if (parse_contact(_m->contact) < 0) {
175                 LOG(L_ERR, "get_contact_uri(): Error while parsing Contact body\n");
176                 return -2;
177         }
178
179         c = ((contact_body_t*)_m->contact->parsed)->contacts;
180
181         if (!c) {
182                 LOG(L_ERR, "get_contact_uri(): Empty body or * contact\n");
183                 return -3;
184         }
185
186              /* FIXME: c->uri may contain name-addr !! */
187         _uri->s = c->uri.s;
188         _uri->len = c->uri.len;
189         return 0;
190 }
191
192
193 /*
194  * Extract tag from To header field of a response
195  * Doesn't parse message headers !!
196  */
197 static inline int get_to_tag(struct sip_msg* _m, str* _tag)
198 {
199         if (!_m->to) {
200                 LOG(L_ERR, "get_to_tag(): To header field missing\n");
201                 return -1;
202         }
203
204         if (get_to(_m)->tag_value.len) {
205                 _tag->s = get_to(_m)->tag_value.s;
206                 _tag->len = get_to(_m)->tag_value.len;
207         } else {
208                 _tag->len = 0;
209         }
210
211         return 0;
212 }
213
214
215 /*
216  * Extract tag from From header field of a request
217  */
218 static inline int get_from_tag(struct sip_msg* _m, str* _tag)
219 {
220         if (parse_from_header(_m) == -1) {
221                 LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");
222                 return -1;
223         }
224
225         if (get_from(_m)->tag_value.len) {
226                 _tag->s = get_from(_m)->tag_value.s;
227                 _tag->len = get_from(_m)->tag_value.len;
228         } else {
229                 _tag->len = 0;
230         }
231
232         return 0;
233 }
234
235
236 /*
237  * Extract Call-ID value
238  * Doesn't parse headers !!
239  */
240 static inline int get_callid(struct sip_msg* _m, str* _cid)
241 {
242         if (_m->callid == 0) {
243                 LOG(L_ERR, "get_callid(): Call-ID not found\n");
244                 return -1;
245         }
246
247         _cid->s = _m->callid->body.s;
248         _cid->len = _m->callid->body.len;
249         trim(_cid);
250         return 0;
251 }
252
253
254 /*
255  * Create a copy of route set either in normal or reverse order
256  */
257 static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order)
258 {
259         struct hdr_field* ptr;
260         rr_t* last, *p, *t;
261         
262         last = 0;
263
264         ptr = _m->record_route;
265         while(ptr) {
266                 if (ptr->type == HDR_RECORDROUTE) {
267                         if (parse_rr(ptr) < 0) {
268                                 LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n");
269                                 goto error;
270                         }
271
272                         p = (rr_t*)ptr->parsed;
273                         while(p) {
274                                 if (shm_duplicate_rr(_m, &t, p) < 0) {
275                                         LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
276                                         goto error;
277                                 }
278                                 
279                                 if (_order == NORMAL_ORDER) {
280                                         if (!*_rs) *_rs = t;
281                                         if (last) last->next = t;
282                                         last = t;
283                                 } else {
284                                         t->next = *_rs;
285                                         *_rs = t;
286                                 }
287
288                                 p = p->next;
289                         }
290                         
291                 }
292                 ptr = ptr->next;
293         }
294         
295         return 0;
296
297  error:
298         shm_free_rr(_rs);
299         return -1;
300 }
301
302
303 /*
304  * Extract all necessarry information from a response and put it
305  * in a dialog structure
306  */
307 static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
308 {
309         str contact, rtag;
310
311              /* Parse the whole message, we will need all Record-Route headers */
312         if (parse_headers(_m, HDR_EOH, 0) == -1) {
313                 LOG(L_ERR, "dlg_new_resp_uac(): Error while parsing headers\n");
314                 return -1;
315         }
316         
317         if (get_contact_uri(_m, &contact) < 0) return -2;
318         if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
319         
320         if (get_to_tag(_m, &rtag) < 0) goto err1;
321         if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
322         
323         if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2;
324
325         return 0;
326  err2:
327         if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
328         _d->id.rem_tag.s = 0;
329         _d->id.rem_tag.len = 0;
330
331  err1:
332         if (_d->rem_target.s) shm_free(_d->rem_target.s);
333         _d->rem_target.s = 0;
334         _d->rem_target.len = 0;
335         return -4;
336 }
337
338
339 /*
340  * Handle dialog in DLG_NEW state, we will be processing the
341  * first response
342  */
343 static inline int dlg_new_resp_uac(dlg_t* _d, struct sip_msg* _m)
344 {
345         int code;
346              /*
347               * Dialog is in DLG_NEW state, we will copy remote
348               * target URI, remote tag if present, and route-set 
349               * if present. And we will transit into DLG_CONFIRMED 
350               * if the response was 2xx and to DLG_DESTROYED if the 
351               * request was a negative final response.
352               */
353
354         code = _m->first_line.u.reply.statuscode;
355
356         if (code < 200) {
357                      /* A provisional response, do nothing, we could
358                       * update remote tag and route set but we will do that
359                       * for a positive final response anyway and I don't want
360                       * bet on presence of these fields in provisional responses
361                       *
362                       * Send a request to jan@iptel.org if you need to update
363                       * the structures here
364                       */
365         } else if ((code >= 200) && (code < 299)) {
366                      /* A final response, update the structures and transit
367                       * into DLG_CONFIRMED
368                       */
369                 if (response2dlg(_m, _d) < 0) return -1;
370                 _d->state = DLG_CONFIRMED;
371
372                 if (calculate_hooks(_d) < 0) {
373                         LOG(L_ERR, "dlg_new_resp_uac(): Error while calculating hooks\n");
374                         return -2;
375                 }
376         } else {
377                      /* 
378                       * A negative final response, mark the dialog as destroyed
379                       * Again, I do not update the structures here becuase it
380                       * makes no sense to me, a dialog shouldn't be used after
381                       * it is destroyed
382                       */
383                 _d->state = DLG_DESTROYED;
384                      /* Signalize the termination with positive return value */
385                 return 1;
386         }
387
388         return 0;
389 }
390
391
392 /*
393  * Handle dialog in DLG_EARLY state, we will be processing either
394  * next provisional response or a final response
395  */
396 static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
397 {
398         int code;
399         code = _m->first_line.u.reply.statuscode;       
400
401         if (code < 200) {
402                      /* We are in early state already, do nothing
403                       */
404         } else if ((code >= 200) && (code <= 299)) {
405                      /* Same as in dlg_new_resp_uac */
406                      /* A final response, update the structures and transit
407                       * into DLG_CONFIRMED
408                       */
409                 if (response2dlg(_m, _d) < 0) return -1;
410                 _d->state = DLG_CONFIRMED;
411
412                 if (calculate_hooks(_d) < 0) {
413                         LOG(L_ERR, "dlg_early_resp_uac(): Error while calculating hooks\n");
414                         return -2;
415                 }
416         } else {
417                      /* Else terminate the dialog */
418                 _d->state = DLG_DESTROYED;
419                      /* Signalize the termination with positive return value */
420                 return 1;
421         }
422
423         return 0;
424 }
425
426
427 /*
428  * Extract method from CSeq header field
429  */
430 static inline int get_cseq_method(struct sip_msg* _m, str* _method)
431 {
432         if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ, 0) == -1) || !_m->cseq)) {
433                 LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
434                 return -1;
435         }
436
437         _method->s = get_cseq(_m)->method.s;
438         _method->len = get_cseq(_m)->method.len;
439         return 0;
440 }
441
442
443 /*
444  * Handle dialog in DLG_CONFIRMED state, we will be processing
445  * a response to a request sent within a dialog
446  */
447 static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
448 {
449         int code;
450         str method, contact;
451
452         code = _m->first_line.u.reply.statuscode;       
453
454              /* Dialog has been already confirmed, that means we received
455               * a response to a request sent within the dialog. We will
456               * update remote target URI if and only if the message sent was
457               * a target refresher. 
458               */
459
460              /* FIXME: Currently we support only INVITEs as target refreshers,
461               * this should be generalized
462               */
463
464              /* IF we receive a 481 response, terminate the dialog because
465               * the remote peer indicated that it didn't have the dialog
466               * state anymore, signal this termination with a positive return
467               * value
468               */
469         if (code == 481) {
470                 _d->state = DLG_DESTROYED;
471                 return 1;
472         }
473
474              /* Do nothing if not 2xx */
475         if ((code < 200) || (code >= 300)) return 0;
476         
477         if (get_cseq_method(_m, &method) < 0) return -1;
478         if ((method.len == 6) && !memcmp("INVITE", method.s, 6)) {
479                      /* Get contact if any and update remote target */
480                 if (parse_headers(_m, HDR_CONTACT, 0) == -1) {
481                         LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
482                         return -2;
483                 }
484
485                      /* Try to extract contact URI */
486                 if (get_contact_uri(_m, &contact) < 0) return -3;
487                      /* If there is a contact URI */
488                 if (contact.len) {
489                              /* Free old remote target if any */
490                         if (_d->rem_target.s) shm_free(_d->rem_target.s);
491                              /* Duplicate new remote target */
492                         if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
493                 }
494         }
495
496         return 0;
497 }
498
499
500 /*
501  * A response arrived, update dialog
502  */
503 int dlg_response_uac(dlg_t* _d, struct sip_msg* _m)
504 {
505         if (!_d || !_m) {
506                 LOG(L_ERR, "dlg_response_uac(): Invalid parameter value\n");
507                 return -1;
508         }
509
510              /* The main dispatcher */
511         switch(_d->state) {
512         case DLG_NEW:       
513                 return dlg_new_resp_uac(_d, _m);
514
515         case DLG_EARLY:     
516                 return dlg_early_resp_uac(_d, _m);
517
518         case DLG_CONFIRMED: 
519                 return dlg_confirmed_resp_uac(_d, _m);
520
521         case DLG_DESTROYED:
522                 LOG(L_ERR, "dlg_response_uac(): Cannot handle destroyed dialog\n");
523                 return -2;
524         }
525
526         LOG(L_ERR, "dlg_response_uac(): Error in switch statement\n");
527         return -3;
528 }
529
530
531 /*
532  * Get CSeq number
533  * Does not parse headers !!
534  */
535 static inline int get_cseq_value(struct sip_msg* _m, unsigned int* _cs)
536 {
537         str num;
538
539         if (_m->cseq == 0) {
540                 LOG(L_ERR, "get_cseq_value(): CSeq header not found\n");
541                 return -1;
542         }
543
544         num.s = get_cseq(_m)->number.s;
545         num.len = get_cseq(_m)->number.len;
546
547         trim_leading(&num);
548         if (str2int(&num, _cs) < 0) {
549                 LOG(L_ERR, "get_cseq_value(): Error while converting cseq number\n");
550                 return -2;
551         }
552         return 0;
553 }
554
555
556 /*
557  * Copy To or From URI without tag parameter
558  */
559 static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
560 {
561         struct to_param* ptr;
562         struct to_body* body;
563         char* tag = 0; /* Makes gcc happy */
564         int tag_len = 0, len;
565
566         if (!_h) {
567                 LOG(L_ERR, "get_dlg_uri(): Header field not found\n");
568                 return -1;
569         }
570
571              /* From was already parsed when extracting tag
572               * and To is parsed by default
573               */
574         
575         body = (struct to_body*)_h->parsed;
576
577         ptr = body->param_lst;
578         while(ptr) {
579                 if (ptr->type == TAG_PARAM) break;
580                 ptr = ptr->next;
581         }
582
583         if (ptr) {
584              /* Tag param found */
585                 tag = ptr->name.s;
586                 if (ptr->next) {
587                         tag_len = ptr->next->name.s - tag;
588                 } else {
589                         tag_len = body->body.s + body->body.len - tag;
590                 }
591         }
592
593         _s->s = shm_malloc(body->body.len - tag_len);
594         if (!_s->s) {
595                 LOG(L_ERR, "get_dlg_uri(): No memory left\n");
596                 return -1;
597         }
598
599         if (tag_len) {
600                 len = tag - body->body.s;
601                 memcpy(_s->s, body->body.s, len);
602                 memcpy(_s->s + len, tag + tag_len, body->body.len - len - tag_len);
603                 _s->len = body->body.len - tag_len;
604         } else {
605                 memcpy(_s->s, body->body.s, body->body.len);
606                 _s->len = body->body.len;
607         }
608
609         return 0;
610 }
611
612
613 /*
614  * Extract all information from a request 
615  * and update a dialog structure
616  */
617 static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
618 {
619         str contact, rtag, callid;
620
621         if (parse_headers(_m, HDR_EOH, 0) == -1) {
622                 LOG(L_ERR, "request2dlg(): Error while parsing headers");
623                 return -1;
624         }
625
626         if (get_contact_uri(_m, &contact) < 0) return -2;
627         if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
628         
629         if (get_from_tag(_m, &rtag) < 0) goto err1;
630         if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
631
632         if (get_callid(_m, &callid) < 0) goto err2;
633         if (callid.len && str_duplicate(&_d->id.call_id, &callid) < 0) goto err2;
634
635         if (get_cseq_value(_m, &_d->rem_seq.value) < 0) goto err3;
636         _d->rem_seq.is_set = 1;
637
638         if (get_dlg_uri(_m->from, &_d->rem_uri) < 0) goto err3;
639         if (get_dlg_uri(_m->to, &_d->loc_uri) < 0) goto err4;
640
641         if (get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0) goto err5;     
642
643         return 0;
644  err5:
645         if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
646         _d->loc_uri.s = 0;
647         _d->loc_uri.len = 0;
648  err4:
649         if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
650         _d->rem_uri.s = 0;
651         _d->rem_uri.len = 0;
652  err3:
653         if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
654         _d->id.call_id.s = 0;
655         _d->id.call_id.len = 0;
656  err2:
657         if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
658         _d->id.rem_tag.s = 0;
659         _d->id.rem_tag.len = 0;
660  err1:
661         if (_d->rem_target.s) shm_free(_d->rem_target.s);
662         _d->rem_target.s = 0;
663         _d->rem_target.len = 0;
664         return -4;
665 }
666
667
668 /*
669  * Establishing a new dialog, UAS side
670  */
671 int new_dlg_uas(struct sip_msg* _req, int _code, str* _tag, dlg_t** _d)
672 {
673         dlg_t* res;
674
675         if (!_req || !_tag || !_d) {
676                 LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n");
677                 return -1;
678         }
679
680         if ((_code < 200) || (_code > 299)) {
681                 DBG("new_dlg_uas(): Not a 2xx, no dialog created\n");
682                 return -2;
683         }
684
685         res = (dlg_t*)shm_malloc(sizeof(dlg_t));
686         if (res == 0) {
687                 LOG(L_ERR, "new_dlg_uac(): No memory left\n");
688                 return -3;
689         }
690              /* Clear everything */
691         memset(res, 0, sizeof(dlg_t));  
692
693         if (request2dlg(_req, res) < 0) {
694                 LOG(L_ERR, "new_dlg_uas(): Error while converting request to dialog\n");
695                 return -4;
696         }
697
698         if (_tag->len) {
699                 if (str_duplicate(&res->id.loc_tag, _tag) < 0) {
700                         free_dlg(res);
701                         return -5;
702                 }
703         }
704         
705         *_d = res;
706
707         (*_d)->state = DLG_CONFIRMED;
708         if (calculate_hooks(*_d) < 0) {
709                 LOG(L_ERR, "new_dlg_uas(): Error while calculating hooks\n");
710                 shm_free(*_d);
711                 return -6;
712         }
713
714         return 0;
715 }
716
717
718 /*
719  * UAS side - update a dialog from a request
720  */
721 int dlg_request_uas(dlg_t* _d, struct sip_msg* _m)
722 {
723         str contact;
724         int cseq;
725
726         if (!_d || !_m) {
727                 LOG(L_ERR, "dlg_request_uas(): Invalid parameter value\n");
728                 return -1;
729         }
730
731              /* We must check if the request is not out of order or retransmission
732               * first, if so then we will not update anything
733               */
734         if (parse_headers(_m, HDR_CSEQ, 0) == -1) {
735                 LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
736                 return -2;
737         }
738         if (get_cseq_value(_m, &cseq) < 0) return -3;
739         if (_d->rem_seq.is_set && (cseq <= _d->rem_seq.value)) return 0;
740
741              /* Neither out of order nor retransmission -> update */
742         _d->rem_seq.value = cseq;
743         _d->rem_seq.is_set = 1;
744         
745              /* We will als update remote target URI if the message 
746               * is target refresher
747               */
748         if (_m->first_line.u.request.method_value == METHOD_INVITE) {
749                      /* target refresher */
750                 if (parse_headers(_m, HDR_CONTACT, 0) == -1) {
751                         LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
752                         return -4;
753                 }
754                 
755                 if (get_contact_uri(_m, &contact) < 0) return -5;
756                 if (contact.len) {
757                         if (_d->rem_target.s) shm_free(_d->rem_target.s);
758                         if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
759                 }
760         }
761
762         return 0;
763 }
764
765
766 /*
767  * Calculate length of the route set
768  */
769 int calculate_routeset_length(dlg_t* _d)
770 {
771         int len;
772         rr_t* ptr;
773
774         len = 0;
775         ptr = _d->hooks.first_route;
776
777         if (ptr) {
778                 len = ROUTE_PREFIX_LEN;
779                 len += CRLF_LEN;
780         }
781
782         while(ptr) {
783                 len += ptr->len;
784                 ptr = ptr->next;
785                 if (ptr) len += ROUTE_SEPARATOR_LEN;
786         } 
787
788         if (_d->hooks.last_route) {
789                 len += ROUTE_SEPARATOR_LEN + 2; /* < > */
790                 len += _d->hooks.last_route->len;
791         }
792
793         return len;
794 }
795
796
797 /*
798  *
799  * Print the route set
800  */
801 char* print_routeset(char* buf, dlg_t* _d)
802 {
803         rr_t* ptr;
804
805         ptr = _d->hooks.first_route;
806
807         if (ptr) {
808                 memcpy(buf, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
809                 buf += ROUTE_PREFIX_LEN;
810         }
811
812         while(ptr) {
813                 memcpy(buf, ptr->nameaddr.name.s, ptr->len);
814                 buf += ptr->len;
815
816                 ptr = ptr->next;
817                 if (ptr) {
818                         memcpy(buf, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);
819                         buf += ROUTE_SEPARATOR_LEN;
820                 }
821         } 
822
823         if (_d->hooks.last_route) {
824                 memcpy(buf, ROUTE_SEPARATOR "<", ROUTE_SEPARATOR_LEN + 1);
825                 buf += ROUTE_SEPARATOR_LEN + 1;
826                 memcpy(buf, _d->hooks.last_route->s, _d->hooks.last_route->len);
827                 buf += _d->hooks.last_route->len;
828                 *buf = '>';
829                 buf++;
830         }
831
832         if (_d->hooks.first_route) {
833                 memcpy(buf, CRLF, CRLF_LEN);
834                 buf += CRLF_LEN;
835         }
836
837         return buf;
838 }
839
840
841 /*
842  * Destroy a dialog state
843  */
844 void free_dlg(dlg_t* _d)
845 {
846         if (!_d) return;
847
848         if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
849         if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
850         if (_d->id.loc_tag.s) shm_free(_d->id.loc_tag.s);
851
852         if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
853         if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
854         if (_d->rem_target.s) shm_free(_d->rem_target.s);
855
856              /* Free all routes in the route set */
857         shm_free_rr(&_d->route_set);
858         shm_free(_d);
859 }
860
861
862 /*
863  * Print a dialog structure, just for debugging
864  */
865 void print_dlg(FILE* out, dlg_t* _d)
866 {
867         fprintf(out, "====dlg_t===\n");
868         fprintf(out, "id.call_id    : '%.*s'\n", _d->id.call_id.len, _d->id.call_id.s);
869         fprintf(out, "id.rem_tag    : '%.*s'\n", _d->id.rem_tag.len, _d->id.rem_tag.s);
870         fprintf(out, "id.loc_tag    : '%.*s'\n", _d->id.loc_tag.len, _d->id.loc_tag.s);
871         fprintf(out, "loc_seq.value : %d\n", _d->loc_seq.value);
872         fprintf(out, "loc_seq.is_set: %s\n", _d->loc_seq.is_set ? "YES" : "NO");
873         fprintf(out, "rem_seq.value : %d\n", _d->rem_seq.value);
874         fprintf(out, "rem_seq.is_set: %s\n", _d->rem_seq.is_set ? "YES" : "NO");
875         fprintf(out, "loc_uri       : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
876         fprintf(out, "rem_uri       : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
877         fprintf(out, "rem_target    : '%.*s'\n", _d->rem_target.len, _d->rem_target.s);
878         fprintf(out, "secure:       : %d\n", _d->secure);
879         fprintf(out, "state         : ");
880         switch(_d->state) {
881         case DLG_NEW:       fprintf(out, "DLG_NEW\n");       break;
882         case DLG_EARLY:     fprintf(out, "DLG_EARLY\n");     break;
883         case DLG_CONFIRMED: fprintf(out, "DLG_CONFIRMED\n"); break;
884         case DLG_DESTROYED: fprintf(out, "DLG_DESTROYED\n"); break;
885         }
886         print_rr(out, _d->route_set);
887         if (_d->hooks.request_uri) 
888                 fprintf(out, "hooks.request_uri: '%.*s'\n", _d->hooks.request_uri->len, _d->hooks.request_uri->s);
889         if (_d->hooks.next_hop) 
890                 fprintf(out, "hooks.next_hop   : '%.*s'\n", _d->hooks.next_hop->len, _d->hooks.next_hop->s);
891         if (_d->hooks.first_route) 
892                 fprintf(out, "hooks.first_route: '%.*s'\n", _d->hooks.first_route->len, _d->hooks.first_route->nameaddr.name.s);
893         if (_d->hooks.last_route)
894                 fprintf(out, "hooks.last_route : '%.*s'\n", _d->hooks.last_route->len, _d->hooks.last_route->s);
895         
896         fprintf(out, "====dlg_t====\n");
897 }