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