Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1286 +0,0 @@
1
-/*
2
- * Copyright (C) 2001-2003 FhG Fokus
3
- *
4
- * This file is part of Kamailio, a free SIP server.
5
- *
6
- * Kamailio is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version
10
- *
11
- * Kamailio is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
- *
20
- */
21
-
22
-/*!
23
- * \file 
24
- * \brief TM :: 
25
- * \ingroup tm
26
- */
27
-
28
-
29
-#include <string.h>
30
-#include "../../mem/shm_mem.h"
31
-#include "../../dprint.h"
32
-#include "../../parser/contact/parse_contact.h"
33
-#include "../../parser/parse_to.h"
34
-#include "../../parser/parse_from.h"
35
-#include "../../parser/parse_uri.h"
36
-#include "../../trim.h"
37
-#include "../../ut.h"
38
-#include "../../config.h"
39
-#include "dlg.h"
40
-#include "t_reply.h"
41
-#include "../../parser/parser_f.h"
42
-
43
-/* next added to allow automatical tag generation */
44
-#include "callid.h"
45
-#include "uac.h"
46
-
47
-#define NORMAL_ORDER 0  /* Create route set in normal order - UAS */
48
-#define REVERSE_ORDER 1 /* Create route set in reverse order - UAC */
49
-
50
-
51
-#ifdef DIALOG_CALLBACKS
52
-
53
-struct new_dlg_cb{
54
-	int types;
55
-	struct new_dlg_cb* next;
56
-	dialog_cb* callback;
57
-	void* param;
58
-};
59
-
60
-static struct new_dlg_cb* new_dlg_cb_list=0;
61
-/* callbacks for new dialogs (called each time a new dialog (uas or uac) is
62
- * created)
63
- * params: type - DLG_CB_UAC or DLG_CB_UAS
64
- *            f - callback function
65
- *        param - parameter passed to the callback; if allocated it must
66
- *                  be allocated in shared mem.
67
- * returns < 0 on error
68
- * WARNING: this callbacks can be registered only before forking (in mod_init)
69
- */
70
-int register_new_dlg_cb(int type, dialog_cb f, void* param)
71
-{
72
-	struct new_dlg_cb* dlg_cb;
73
-	
74
-	dlg_cb=shm_malloc(sizeof(struct new_dlg_cb));
75
-	if (dlg_cb==0)
76
-		return E_OUT_OF_MEM;
77
-	dlg_cb->types=type;
78
-	dlg_cb->callback=f;
79
-	dlg_cb->param=param;
80
-	dlg_cb->next=new_dlg_cb_list;
81
-	new_dlg_cb_list=dlg_cb;
82
-	return 0;
83
-}
84
-
85
-
86
-void destroy_new_dlg_cbs()
87
-{
88
-	struct new_dlg_cb* c;
89
-	struct new_dlg_cb* n;
90
-
91
-	c=new_dlg_cb_list;
92
-	while(c){
93
-		n=c->next;
94
-		shm_free(c);
95
-		c=n;
96
-	}
97
-	new_dlg_cb_list=0;
98
-}
99
-
100
-
101
-static void run_new_dlg_callbacks(int type, dlg_t* dlg, struct sip_msg* msg)
102
-{
103
-	struct new_dlg_cb* c;
104
-	for (c=new_dlg_cb_list; c; c=c->next){
105
-		if (c->types & type)
106
-			c->callback(type, dlg, msg);
107
-	}
108
-}
109
-
110
-
111
-int register_dlg_tmcb(int types, dlg_t* dlg, transaction_cb f, void* param)
112
-{
113
-	/* only TMCB_DLG bad TMCB_DESTROY allowed */
114
-	if ((types&(TMCB_DLG|TMCB_DESTROY))!=types){
115
-		LOG(L_CRIT, "BUG: tm: register_dlg_tmcb: bad types %d\n", types);
116
-		return E_BUG;
117
-	}
118
-	if (f==0){
119
-		LOG(L_CRIT, "BUG: tm: register_dlg_tmcb: null callback function");
120
-		return E_BUG;
121
-	}
122
-	return insert_tmcb(&dlg->dlg_callbacks, types, f, param, NULL);
123
-}
124
-
125
-
126
-/* per dialog callbacks receive only the transaction, send buffer, destination
127
- * and the retr. buff */
128
-void run_trans_dlg_callbacks(dlg_t* dlg, struct cell* trans,
129
-								struct retr_buf* rbuf)
130
-{
131
-	struct tmcb_params params;
132
-	
133
-	if (dlg->dlg_callbacks.first==0)
134
-		return;
135
-	memset(&params, 0, sizeof(params));
136
-	if (rbuf){
137
-		params.t_rbuf=rbuf;
138
-		params.dst=&rbuf->dst;
139
-		params.send_buf.s=rbuf->buffer;
140
-		params.send_buf.len=rbuf->buffer_len;
141
-	}
142
-	
143
-	run_trans_callbacks_internal(&dlg->dlg_callbacks, TMCB_DLG, trans, 
144
-									&params);
145
-}
146
-
147
-/* TMCB_DESTROY per dialog callbacks */
148
-static void destroy_trans_dlg_callbacks(dlg_t* dlg)
149
-{
150
-	struct tmcb_params params;
151
-	struct tm_callback* cbp;
152
-	
153
-	if ((dlg->dlg_callbacks.first==0) || 
154
-			((dlg->dlg_callbacks.reg_types&TMCB_DESTROY)==0) )
155
-		return;
156
-	memset(&params, 0, sizeof(params));
157
-	for (cbp=(struct tm_callback*)dlg->dlg_callbacks.first;cbp;cbp=cbp->next){
158
-		if (cbp->types & TMCB_DESTROY){
159
-			params.param=&(cbp->param);
160
-			cbp->callback(0, 0, &params);
161
-		}
162
-	}
163
-}
164
-#endif /* DIALOG_CALLBACKS */
165
-
166
-/*** Temporary hack ! */
167
-/*
168
- * This function skips name part
169
- * uri parsed by parse_contact must be used
170
- * (the uri must not contain any leading or
171
- *  trailing part and if angle bracket were
172
- *  used, right angle bracket must be the
173
- *  last character in the string)
174
- *
175
- * _s will be modified so it should be a tmp
176
- * copy
177
- */
178
-void get_raw_uri(str* _s)
179
-{
180
-        char* aq;
181
-        
182
-        if (_s->s[_s->len - 1] == '>') {
183
-                aq = find_not_quoted(_s, '<');
184
-                _s->len -= aq - _s->s + 2;
185
-                _s->s = aq + 1;
186
-        }
187
-}
188
-
189
-
190
-/*
191
- * Make a copy of a str structure using shm_malloc
192
- */
193
-static inline int str_duplicate(str* _d, str* _s)
194
-{
195
-	_d->s = shm_malloc(_s->len);
196
-	if (!_d->s) {
197
-		LOG(L_ERR, "str_duplicate(): No memory left\n");
198
-		return -1;
199
-	}
200
-	
201
-	memcpy(_d->s, _s->s, _s->len);
202
-	_d->len = _s->len;
203
-	return 0;
204
-}
205
-
206
-
207
-/*
208
- * Calculate dialog hooks
209
- * @return:
210
- *  negative : error
211
- *  0 : no routes present
212
- *  F_RB_NH_LOOSE : routes present, next hop is loose router
213
- *  F_RB_NH_STRICT: next hop is strict.
214
- */
215
-static inline int calculate_hooks(dlg_t* _d)
216
-{
217
-	str* uri;
218
-	struct sip_uri puri;
219
-	int nhop;
220
-
221
-	/* we might re-calc. some existing hooks =>
222
-	 * reset all the hooks to 0 */
223
-	memset(&_d->hooks, 0, sizeof(_d->hooks));
224
-	if (_d->route_set) {
225
-		uri = &_d->route_set->nameaddr.uri;
226
-		if (parse_uri(uri->s, uri->len, &puri) < 0) {
227
-			LOG(L_ERR, "calculate_hooks(): Error while parsing URI\n");
228
-			return -1;
229
-		}
230
-		
231
-		if (puri.lr.s) {
232
-			if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
233
-			else _d->hooks.request_uri = &_d->rem_uri;
234
-			_d->hooks.next_hop = &_d->route_set->nameaddr.uri;
235
-			_d->hooks.first_route = _d->route_set;
236
-			nhop = F_RB_NH_LOOSE;
237
-		} else {
238
-			_d->hooks.request_uri = &_d->route_set->nameaddr.uri;
239
-			_d->hooks.next_hop = _d->hooks.request_uri;
240
-			_d->hooks.first_route = _d->route_set->next;
241
-			if (_d->rem_target.len > 0) 
242
-				_d->hooks.last_route = &_d->rem_target;
243
-			else 
244
-				_d->hooks.last_route = NULL; /* ? */
245
-			nhop = F_RB_NH_STRICT;
246
-		}
247
-	} else {
248
-		if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target;
249
-		else _d->hooks.request_uri = &_d->rem_uri;
250
-		
251
-		if (_d->dst_uri.s) _d->hooks.next_hop = &_d->dst_uri;
252
-		else _d->hooks.next_hop = _d->hooks.request_uri;
253
-
254
-		nhop = 0;
255
-		/*
256
-		 * the routes in the hooks need to be reset because if the route_set 
257
-		 * was dropped somewhere else then these will remain set without the
258
-		 * actual routes existing any more
259
-		 */
260
-		_d->hooks.first_route = 0;
261
-		_d->hooks.last_route = 0;
262
-	}
263
-
264
-	if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) {
265
-		_d->hooks.ru.s = _d->hooks.request_uri->s;
266
-		_d->hooks.ru.len = _d->hooks.request_uri->len;
267
-		_d->hooks.request_uri = &_d->hooks.ru;
268
-		get_raw_uri(_d->hooks.request_uri);
269
-	}
270
-	if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) {
271
-		_d->hooks.nh.s = _d->hooks.next_hop->s;
272
-		_d->hooks.nh.len = _d->hooks.next_hop->len;
273
-		_d->hooks.next_hop = &_d->hooks.nh;
274
-		get_raw_uri(_d->hooks.next_hop);
275
-	}
276
-
277
-	return nhop;
278
-}
279
-
280
-/*
281
- * wrapper to calculate_hooks
282
- * added by dcm
283
- */
284
-int w_calculate_hooks(dlg_t* _d)
285
-{
286
-	return calculate_hooks(_d);
287
-}
288
-
289
-/*
290
- * Create a new dialog
291
- */
292
-int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d)
293
-{
294
-	dlg_t* res;
295
-	str generated_cid;
296
-	str generated_ltag;
297
-
298
-	if (!_cid) { /* if not given, compute new one */
299
-		generate_callid(&generated_cid);
300
-		_cid = &generated_cid;
301
-	}
302
-	if (_cid && (!_ltag)) { /* if not given, compute new one */
303
-		generate_fromtag(&generated_ltag, _cid);
304
-		_ltag = &generated_ltag;
305
-	}
306
-	if (_lseq == 0) _lseq = DEFAULT_CSEQ;
307
-
308
-	if (!_cid || !_ltag || !_luri || !_ruri || !_d) {
309
-		LOG(L_ERR, "new_dlg_uac(): Invalid parameter value\n");
310
-		return -1;
311
-	}
312
-
313
-	res = (dlg_t*)shm_malloc(sizeof(dlg_t));
314
-	if (res == 0) {
315
-		LOG(L_ERR, "new_dlg_uac(): No memory left\n");
316
-		return -2;
317
-	}
318
-
319
-	     /* Clear everything */	
320
-	memset(res, 0, sizeof(dlg_t));
321
-	
322
-	     /* Make a copy of Call-ID */
323
-	if (str_duplicate(&res->id.call_id, _cid) < 0) return -3;
324
-	     /* Make a copy of local tag (usually From tag) */
325
-	if (str_duplicate(&res->id.loc_tag, _ltag) < 0) return -4;
326
-	     /* Make a copy of local URI (usually From) */
327
-	if (str_duplicate(&res->loc_uri, _luri) < 0) return -5;
328
-	     /* Make a copy of remote URI (usually To) */
329
-	if (str_duplicate(&res->rem_uri, _ruri) < 0) return -6;
330
-	     /* Make a copy of local sequence (usually CSeq) */
331
-	res->loc_seq.value = _lseq;
332
-	     /* And mark it as set */
333
-	res->loc_seq.is_set = 1;
334
-
335
-	*_d = res;
336
-
337
-	if (calculate_hooks(*_d) < 0) {
338
-		LOG(L_ERR, "new_dlg_uac(): Error while calculating hooks\n");
339
-		/* FIXME: free everything here */
340
-		shm_free(res);
341
-		return -2;
342
-	}
343
-#ifdef DIALOG_CALLBACKS
344
-	run_new_dlg_callbacks(DLG_CB_UAC, res, 0);
345
-#endif
346
-	
347
-	return 0;
348
-}
349
-
350
-/**
351
- * @brief Store display names into a dialog
352
- * @param _d - dialog structure
353
- * @param _ldname - local party display name
354
- * @param _rdname - remote party dispaly name
355
- * @return 0 on success; negative on error
356
- */
357
-
358
-int dlg_add_extra(dlg_t* _d, str* _ldname, str* _rdname)
359
-{
360
-	if(!_d || !_ldname || !_rdname)
361
-	{
362
-		LM_ERR("Invalid parameters\n");
363
-		return -1;
364
-	}
365
-
366
-	/* Make a copy of local Display Name */
367
-	if(shm_str_dup(&_d->loc_dname, _ldname) < 0) return -2;
368
-	/* Make a copy of remote Display Name */
369
-	if(shm_str_dup(&_d->rem_dname, _rdname) < 0) return -3;
370
-
371
-	return 0;
372
-}
373
-
374
-/*
375
- * Parse Contact header field body and extract URI
376
- * Does not parse headers !!
377
- */
378
-static inline int get_contact_uri(struct sip_msg* _m, str* _uri)
379
-{
380
-	contact_t* c;
381
-
382
-	_uri->len = 0;
383
-	_uri->s = 0;
384
-
385
-	if (!_m->contact) return 1;
386
-
387
-	if (parse_contact(_m->contact) < 0) {
388
-		LOG(L_ERR, "get_contact_uri(): Error while parsing Contact body\n");
389
-		return -2;
390
-	}
391
-
392
-	c = ((contact_body_t*)_m->contact->parsed)->contacts;
393
-
394
-	if (!c) {
395
-		LOG(L_ERR, "get_contact_uri(): Empty body or * contact\n");
396
-		return -3;
397
-	}
398
-
399
-	_uri->s = c->uri.s;
400
-	_uri->len = c->uri.len;
401
-	return 0;
402
-}
403
-
404
-
405
-/*
406
- * Extract tag from To header field of a response
407
- * Doesn't parse message headers !!
408
- */
409
-static inline int get_to_tag(struct sip_msg* _m, str* _tag)
410
-{
411
-	if (!_m->to) {
412
-		LOG(L_ERR, "get_to_tag(): To header field missing\n");
413
-		return -1;
414
-	}
415
-
416
-	if (get_to(_m)->tag_value.len) {
417
-		_tag->s = get_to(_m)->tag_value.s;
418
-		_tag->len = get_to(_m)->tag_value.len;
419
-	} else {
420
-		_tag->len = 0;
421
-	}
422
-
423
-	return 0;
424
-}
425
-
426
-
427
-/*
428
- * Extract tag from From header field of a request
429
- */
430
-static inline int get_from_tag(struct sip_msg* _m, str* _tag)
431
-{
432
-	if (parse_from_header(_m) == -1) {
433
-		LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");
434
-		return -1;
435
-	}
436
-
437
-	if (get_from(_m)->tag_value.len) {
438
-		_tag->s = get_from(_m)->tag_value.s;
439
-		_tag->len = get_from(_m)->tag_value.len;
440
-	} else {
441
-		_tag->len = 0;
442
-	}
443
-
444
-	return 0;
445
-}
446
-
447
-
448
-/*
449
- * Extract Call-ID value
450
- * Doesn't parse headers !!
451
- */
452
-static inline int get_callid(struct sip_msg* _m, str* _cid)
453
-{
454
-	if (_m->callid == 0) {
455
-		LOG(L_ERR, "get_callid(): Call-ID not found\n");
456
-		return -1;
457
-	}
458
-
459
-	_cid->s = _m->callid->body.s;
460
-	_cid->len = _m->callid->body.len;
461
-	trim(_cid);
462
-	return 0;
463
-}
464
-
465
-static rr_t *revert_route(rr_t *r)
466
-{
467
-	rr_t *a, *b;
468
-
469
-	a = NULL;
470
-
471
-	while (r) {
472
-		b = r->next;
473
-		r->next = a;
474
-		a = r;
475
-		r = b;
476
-	}
477
-
478
-	return a;
479
-}
480
-
481
-/*
482
- * Create a copy of route set either in normal or reverse order
483
- */
484
-static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order)
485
-{
486
-	struct hdr_field* ptr;
487
-	rr_t* last, *p, *t;
488
-	
489
-	last = 0;
490
-
491
-	ptr = _m->record_route;
492
-	while(ptr) {
493
-		if (ptr->type == HDR_RECORDROUTE_T) {
494
-			if (parse_rr(ptr) < 0) {
495
-				LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n");
496
-				goto error;
497
-			}
498
-
499
-			p = (rr_t*)ptr->parsed;
500
-			if (shm_duplicate_rr(&t, p) < 0) {
501
-				LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
502
-				goto error;
503
-			}
504
-			if (!*_rs) *_rs = t;
505
-			if (last) last->next = t;
506
-			last = t;
507
-			while (last->next) last = last->next; /* !!! there may be more routes in one hdr field !!! */
508
-
509
-		}
510
-		ptr = ptr->next;
511
-	}
512
-	if ((*_rs) && (_order != NORMAL_ORDER)) {
513
-		/* better to revert the route outside of cycle above */
514
-		*_rs = revert_route(*_rs);
515
-	}
516
-	
517
-	return 0;
518
-
519
- error:
520
-	shm_free_rr(_rs);
521
-	return -1;
522
-}
523
-
524
-/*
525
- * Extract method from CSeq header field
526
- */
527
-static inline int get_cseq_method(struct sip_msg* _m, str* _method)
528
-{
529
-	if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ_F, 0) == -1) || !_m->cseq)) {
530
-		LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
531
-		return -1;
532
-	}
533
-
534
-	_method->s = get_cseq(_m)->method.s;
535
-	_method->len = get_cseq(_m)->method.len;
536
-	return 0;
537
-}
538
-
539
-
540
-static inline int refresh_dialog_resp(struct sip_msg* _m, 
541
-		target_refresh_t is_target_refresh)
542
-{
543
-	str method;
544
-	
545
-	switch (is_target_refresh) {
546
-		case IS_NOT_TARGET_REFRESH: 
547
-			return 0;
548
-		case IS_TARGET_REFRESH: 
549
-			return 1;
550
-		case TARGET_REFRESH_UNKNOWN: 
551
-			if (get_cseq_method(_m, &method) < 0) return 0; /* error */
552
-			if ((method.len == 6) && !memcmp("INVITE", method.s, 6)) 
553
-				return 1;
554
-			else return 0;
555
-	}
556
-	return 0;
557
-}
558
-		
559
-static inline int refresh_dialog_req(struct sip_msg* _m, target_refresh_t is_target_refresh)
560
-{
561
-	switch (is_target_refresh) {
562
-		case IS_NOT_TARGET_REFRESH: 
563
-			return 0;
564
-		case IS_TARGET_REFRESH: 
565
-			return 1;
566
-		case TARGET_REFRESH_UNKNOWN: 
567
-			return (_m->first_line.u.request.method_value == METHOD_INVITE);
568
-			break;
569
-	}
570
-	return 0;
571
-}
572
-
573
-/*
574
- * Extract all necessary information from a response and put it
575
- * in a dialog structure
576
- */
577
-static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
578
-{
579
-	str contact, rtag;
580
-
581
-	     /* Parse the whole message, we will need all Record-Route headers */
582
-	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
583
-		LOG(L_ERR, "response2dlg(): Error while parsing headers\n");
584
-		return -1;
585
-	}
586
-	
587
-	if (get_contact_uri(_m, &contact) < 0) return -2;
588
-	if (_d->rem_target.s) {
589
-		shm_free(_d->rem_target.s);
590
-		_d->rem_target.s = 0; 
591
-		_d->rem_target.len = 0;
592
-	}
593
-	if (_d->dst_uri.s) {
594
-		shm_free(_d->dst_uri.s);
595
-		_d->dst_uri.s = 0; 
596
-		_d->dst_uri.len = 0;
597
-	}
598
-	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
599
-	
600
-	if (get_to_tag(_m, &rtag) < 0) goto err1;
601
-	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
602
-	
603
-	if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2;
604
-
605
-	return 0;
606
- err2:
607
-	if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
608
-	_d->id.rem_tag.s = 0;
609
-	_d->id.rem_tag.len = 0;
610
-
611
- err1:
612
-	if (_d->rem_target.s) shm_free(_d->rem_target.s);
613
-	_d->rem_target.s = 0;
614
-	_d->rem_target.len = 0;
615
-	return -4;
616
-}
617
-
618
-
619
-/*
620
- * Handle dialog in DLG_NEW state, we will be processing the
621
- * first response
622
- */
623
-static inline int dlg_new_resp_uac(dlg_t* _d, struct sip_msg* _m)
624
-{
625
-	int code;
626
-	     /*
627
-	      * Dialog is in DLG_NEW state, we will copy remote
628
-	      * target URI, remote tag if present, and route-set 
629
-	      * if present. And we will transit into DLG_CONFIRMED 
630
-	      * if the response was 2xx and to DLG_DESTROYED if the 
631
-	      * request was a negative final response.
632
-	      */
633
-
634
-	code = _m->first_line.u.reply.statuscode;
635
-
636
-	if (code < 200) {
637
-		     /* A provisional response, do nothing, we could
638
-		      * update remote tag and route set but we will do that
639
-		      * for a positive final response anyway and I don't want
640
-		      * bet on presence of these fields in provisional responses
641
-		      *
642
-		      * Send a request to jan@iptel.org if you need to update
643
-		      * the structures here
644
-		      */
645
-	} else if ((code >= 200) && (code < 299)) {
646
-		     /* A final response, update the structures and transit
647
-		      * into DLG_CONFIRMED
648
-		      */
649
-		if (response2dlg(_m, _d) < 0) return -1;
650
-		_d->state = DLG_CONFIRMED;
651
-
652
-		if (calculate_hooks(_d) < 0) {
653
-			LOG(L_ERR, "dlg_new_resp_uac(): Error while calculating hooks\n");
654
-			return -2;
655
-		}
656
-	} else {
657
-		     /* 
658
-		      * A negative final response, mark the dialog as destroyed
659
-		      * Again, I do not update the structures here because it
660
-		      * makes no sense to me, a dialog shouldn't be used after
661
-		      * it is destroyed
662
-		      */
663
-		_d->state = DLG_DESTROYED;
664
-		     /* Signalize the termination with positive return value */
665
-		return 1;
666
-	}
667
-
668
-	return 0;
669
-}
670
-
671
-
672
-/*
673
- * Handle dialog in DLG_EARLY state, we will be processing either
674
- * next provisional response or a final response
675
- */
676
-static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
677
-{
678
-	int code;
679
-	code = _m->first_line.u.reply.statuscode;	
680
-
681
-	if (code < 200) {
682
-		     /* We are in early state already, do nothing
683
-		      */
684
-	} else if ((code >= 200) && (code <= 299)) {
685
-		/* Warning - we can handle here response for non-initial request (for
686
-		 * example UPDATE within early INVITE/BYE dialog) and move into
687
-		 * confirmed state may be error! But this depends on dialog type... */
688
-		
689
-		     /* Same as in dlg_new_resp_uac */
690
-		     /* A final response, update the structures and transit
691
-		      * into DLG_CONFIRMED
692
-		      */
693
-		if (response2dlg(_m, _d) < 0) return -1;
694
-		_d->state = DLG_CONFIRMED;
695
-
696
-		if (calculate_hooks(_d) < 0) {
697
-			LOG(L_ERR, "dlg_early_resp_uac(): Error while calculating hooks\n");
698
-			return -2;
699
-		}
700
-	} else {
701
-		     /* Else terminate the dialog */
702
-		_d->state = DLG_DESTROYED;
703
-		     /* Signalize the termination with positive return value */
704
-		return 1;
705
-	}
706
-
707
-	return 0;
708
-}
709
-
710
-
711
-/*
712
- * Handle dialog in DLG_CONFIRMED state, we will be processing
713
- * a response to a request sent within a dialog
714
- */
715
-static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m, 
716
-		target_refresh_t is_target_refresh)
717
-{
718
-	int code;
719
-	str contact;
720
-
721
-	code = _m->first_line.u.reply.statuscode;	
722
-
723
-	     /* Dialog has been already confirmed, that means we received
724
-	      * a response to a request sent within the dialog. We will
725
-	      * update remote target URI if and only if the message sent was
726
-	      * a target refresher. 
727
-	      */
728
-
729
-	     /* IF we receive a 481 response, terminate the dialog because
730
-	      * the remote peer indicated that it didn't have the dialog
731
-	      * state anymore, signal this termination with a positive return
732
-	      * value
733
-	      */
734
-	if (code == 481) {
735
-		_d->state = DLG_DESTROYED;
736
-		return 1;
737
-	}
738
-
739
-	     /* Do nothing if not 2xx */
740
-	if ((code < 200) || (code >= 300)) return 0;
741
-	
742
-	if (refresh_dialog_resp(_m, is_target_refresh)) {
743
-		     /* Get contact if any and update remote target */
744
-		if (parse_headers(_m, HDR_CONTACT_F, 0) == -1) {
745
-			LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
746
-			return -2;
747
-		}
748
-
749
-		     /* Try to extract contact URI */
750
-		if (get_contact_uri(_m, &contact) < 0) return -3;
751
-		     /* If there is a contact URI */
752
-		if (contact.len) {
753
-			     /* Free old remote target and destination uri if any */
754
-			if (_d->rem_target.s) shm_free(_d->rem_target.s);
755
-			if (_d->dst_uri.s) {
756
-				shm_free(_d->dst_uri.s);
757
-				_d->dst_uri.s = 0;
758
-				_d->dst_uri.len = 0;
759
-			}
760
-				
761
-			     /* Duplicate new remote target */
762
-			if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
763
-		}
764
-
765
-		if (calculate_hooks(_d) < 0)
766
-			return -1;
767
-	}
768
-
769
-	return 0;
770
-}
771
-
772
-
773
-/*
774
- * A response arrived, update dialog
775
- */
776
-int dlg_response_uac(dlg_t* _d, struct sip_msg* _m, 
777
-		target_refresh_t is_target_refresh)
778
-{
779
-	if (!_d || !_m) {
780
-		LOG(L_ERR, "dlg_response_uac(): Invalid parameter value\n");
781
-		return -1;
782
-	}
783
-
784
-	     /* The main dispatcher */
785
-	switch(_d->state) {
786
-	case DLG_NEW:       
787
-		return dlg_new_resp_uac(_d, _m);
788
-
789
-	case DLG_EARLY:     
790
-		return dlg_early_resp_uac(_d, _m);
791
-
792
-	case DLG_CONFIRMED: 
793
-		return dlg_confirmed_resp_uac(_d, _m, is_target_refresh);
794
-
795
-	case DLG_DESTROYED:
796
-		LOG(L_DBG, "dlg_response_uac(): Cannot handle destroyed dialog\n");
797
-		return -2;
798
-	}
799
-
800
-	LOG(L_ERR, "dlg_response_uac(): Error in switch statement\n");
801
-	return -3;
802
-}
803
-
804
-
805
-/*
806
- * Get CSeq number
807
- * Does not parse headers !!
808
- */
809
-static inline int get_cseq_value(struct sip_msg* _m, unsigned int* _cs)
810
-{
811
-	str num;
812
-
813
-	if (_m->cseq == 0) {
814
-		LOG(L_ERR, "get_cseq_value(): CSeq header not found\n");
815
-		return -1;
816
-	}
817
-
818
-	num.s = get_cseq(_m)->number.s;
819
-	num.len = get_cseq(_m)->number.len;
820
-
821
-	trim_leading(&num);
822
-	if (str2int(&num, _cs) < 0) {
823
-		LOG(L_ERR, "get_cseq_value(): Error while converting cseq number\n");
824
-		return -2;
825
-	}
826
-	return 0;
827
-}
828
-
829
-
830
-/*
831
- * Copy To or From URI without tag parameter
832
- */
833
-static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
834
-{
835
-	struct to_param* ptr, *prev;
836
-	struct to_body* body;
837
-	char* tag = 0; /* Makes gcc happy */
838
-	int tag_len = 0, len;
839
-
840
-	if (!_h) {
841
-		LOG(L_ERR, "get_dlg_uri(): Header field not found\n");
842
-		return -1;
843
-	}
844
-
845
-	     /* From was already parsed when extracting tag
846
-	      * and To is parsed by default
847
-	      */
848
-	
849
-	body = (struct to_body*)_h->parsed;
850
-
851
-	ptr = body->param_lst;
852
-	prev = 0;
853
-	while(ptr) {
854
-		if (ptr->type == TAG_PARAM) break;
855
-		prev = ptr;
856
-		ptr = ptr->next;
857
-	}
858
-
859
-	if (ptr) {
860
-		     /* Tag param found */
861
-		if (prev) {
862
-			tag = prev->value.s + prev->value.len;
863
-		} else {
864
-			tag = body->body.s + body->body.len;
865
-		}
866
-		
867
-		if (ptr->next) {
868
-			tag_len = ptr->value.s + ptr->value.len - tag;
869
-		} else {
870
-			tag_len = _h->body.s + _h->body.len - tag;
871
-		}
872
-	}
873
-
874
-	_s->s = shm_malloc(_h->body.len - tag_len);
875
-	if (!_s->s) {
876
-		LOG(L_ERR, "get_dlg_uri(): No memory left\n");
877
-		return -1;
878
-	}
879
-
880
-	if (tag_len) {
881
-		len = tag - _h->body.s;
882
-		memcpy(_s->s, _h->body.s, len);
883
-		memcpy(_s->s + len, tag + tag_len, _h->body.len - len - tag_len);
884
-		_s->len = _h->body.len - tag_len;
885
-	} else {
886
-		memcpy(_s->s, _h->body.s, _h->body.len);
887
-		_s->len = _h->body.len;
888
-	}
889
-
890
-	return 0;
891
-}
892
-
893
-
894
-/*
895
- * Extract all information from a request 
896
- * and update a dialog structure
897
- */
898
-static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
899
-{
900
-	str contact, rtag, callid;
901
-
902
-	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
903
-		LOG(L_ERR, "request2dlg(): Error while parsing headers");
904
-		return -1;
905
-	}
906