Browse code

raw dialog support added (untested !!)

Jan Janak authored on 01/04/2003 06:36:55
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,715 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * History:
5
+ * -------
6
+ * 2003-03-29 Created by janakj
7
+ */
8
+
9
+
10
+#include <stdio.h>
11
+#include <string.h>
12
+#include "../../mem/mem.h"
13
+#include "../../dprint.h"
14
+#include "../../parser/contact/parse_contact.h"
15
+#include "../../parser/parse_to.h"
16
+#include "../../parser/parse_from.h"
17
+#include "../../trim.h"
18
+#include "../../ut.h"
19
+#include "dlg.h"
20
+
21
+
22
+#define NORMAL_ORDER 0  /* Create route set in normal order - UAS */
23
+#define REVERSE_ORDER 1 /* Create route set in reverse order - UAC */
24
+
25
+
26
+/*
27
+ * Make a copy of a str structure using pkg_malloc
28
+ */
29
+static inline int str_duplicate(str* _d, str* _s)
30
+{
31
+	_d->s = pkg_malloc(_s->len);
32
+	if (!_d->s) {
33
+		LOG(L_ERR, "str_duplicate(): No memory left\n");
34
+		return -1;
35
+	}
36
+	
37
+	memcpy(_d->s, _s->s, _s->len);
38
+	_d->len = _s->len;
39
+	return 0;
40
+}
41
+
42
+
43
+/*
44
+ * Create a new dialog
45
+ */
46
+int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d)
47
+{
48
+	dlg_t* res;
49
+
50
+	if (!_cid || !_ltag || !_luri || !_ruri || !_d) {
51
+		LOG(L_ERR, "new_dlg_uac(): Invalid parameter value\n");
52
+		return -1;
53
+	}
54
+
55
+	res = (dlg_t*)pkg_malloc(sizeof(dlg_t));
56
+	if (res == 0) {
57
+		LOG(L_ERR, "new_dlg_uac(): No memory left\n");
58
+		return -2;
59
+	}
60
+	     /* Clear everything */
61
+	memset(res, 0, sizeof(dlg_t));
62
+	
63
+	     /* Make a copy of Call-ID */
64
+	if (str_duplicate(&res->id.call_id, _cid) < 0) return -3;
65
+	     /* Make a copy of local tag (usually From tag) */
66
+	if (str_duplicate(&res->id.loc_tag, _ltag) < 0) return -4;
67
+	     /* Make a copy of local URI (usually From) */
68
+	if (str_duplicate(&res->loc_uri, _luri) < 0) return -5;
69
+	     /* Make a copy of remote URI (usually To) */
70
+	if (str_duplicate(&res->rem_uri, _ruri) < 0) return -6;
71
+	     /* Make a copy of local sequence (usually CSeq) */
72
+	res->loc_seq.value = _lseq;
73
+	     /* And mark it as set */
74
+	res->loc_seq.is_set = 1;
75
+
76
+	*_d = res;
77
+	return 0;
78
+}
79
+
80
+
81
+/*
82
+ * Parse Contact header field body and extract URI
83
+ * Does not parse headers !!
84
+ */
85
+static inline int get_contact_uri(struct sip_msg* _m, str* _uri)
86
+{
87
+	contact_t* c;
88
+
89
+	_uri->len = 0;
90
+
91
+	if (!_m->contact) return 0;
92
+
93
+	if (parse_contact(_m->contact) < 0) {
94
+		LOG(L_ERR, "get_contact_uri(): Error while parsing Contact body\n");
95
+		return -2;
96
+	}
97
+
98
+	c = ((contact_body_t*)_m->contact->parsed)->contacts;
99
+
100
+	if (!c) {
101
+		LOG(L_ERR, "get_contact_uri(): Empty body or * contact\n");
102
+		return -3;
103
+	}
104
+
105
+	     /* FIXME: c->uri may contain name-addr !! */
106
+	_uri->s = c->uri.s;
107
+	_uri->len = c->uri.len;
108
+	return 0;
109
+}
110
+
111
+
112
+/*
113
+ * Extract tag from To header field of a response
114
+ * Doesn't parse message headers !!
115
+ */
116
+static inline int get_to_tag(struct sip_msg* _m, str* _tag)
117
+{
118
+	if (!_m->to) {
119
+		LOG(L_ERR, "get_to_tag(): To header field missing\n");
120
+		return -1;
121
+	}
122
+
123
+	if (get_to(_m)->tag_value.len) {
124
+		_tag->s = get_to(_m)->tag_value.s;
125
+		_tag->len = get_to(_m)->tag_value.len;
126
+	} else {
127
+		_tag->len = 0;
128
+	}
129
+
130
+	return 0;
131
+}
132
+
133
+
134
+/*
135
+ * Extract tag from From header field of a request
136
+ */
137
+static inline int get_from_tag(struct sip_msg* _m, str* _tag)
138
+{
139
+	if (parse_from_header(_m) == -1) {
140
+		LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");
141
+		return -1;
142
+	}
143
+
144
+	if (get_from(_m)->tag_value.len) {
145
+		_tag->s = get_from(_m)->tag_value.s;
146
+		_tag->len = get_from(_m)->tag_value.len;
147
+	} else {
148
+		_tag->len = 0;
149
+	}
150
+
151
+	return 0;
152
+}
153
+
154
+
155
+/*
156
+ * Extract Call-ID value
157
+ * Doesn't parse headers !!
158
+ */
159
+static inline int get_callid(struct sip_msg* _m, str* _cid)
160
+{
161
+	if (_m->callid == 0) {
162
+		LOG(L_ERR, "get_callid(): Call-ID not found\n");
163
+		return -1;
164
+	}
165
+
166
+	_cid->s = _m->callid->body.s;
167
+	_cid->len = _m->callid->body.len;
168
+	trim(_cid);
169
+	return 0;
170
+}
171
+
172
+
173
+/*
174
+ * Create a copy of route set either in normal or reverse order
175
+ */
176
+static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order)
177
+{
178
+	struct hdr_field* ptr;
179
+	rr_t* last, *p, *t;
180
+	
181
+	last = 0;
182
+
183
+	ptr = _m->record_route;
184
+	while(ptr) {
185
+		if (ptr->type == HDR_RECORDROUTE) {
186
+			if (parse_rr(ptr) < 0) {
187
+				LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n");
188
+				goto error;
189
+			}
190
+
191
+			p = (rr_t*)ptr->parsed;
192
+			while(p) {
193
+				if (duplicate_rr(_m, &t, p) < 0) {
194
+					LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n");
195
+					goto error;
196
+				}
197
+				
198
+				if (_order == NORMAL_ORDER) {
199
+					if (!*_rs) *_rs = t;
200
+					if (last) last->next = t;
201
+					last = t;
202
+				} else {
203
+					t->next = *_rs;
204
+					*_rs = t;
205
+				}
206
+
207
+				p = p->next;
208
+			}
209
+			
210
+		}
211
+		ptr = ptr->next;
212
+	}
213
+	
214
+	return 0;
215
+
216
+ error:
217
+        free_rr(_rs);
218
+	return -1;
219
+}
220
+
221
+
222
+/*
223
+ * Extract all necessarry information from a response and put it
224
+ * in a dialog structure
225
+ */
226
+static inline int response2dlg(struct sip_msg* _m, dlg_t* _d)
227
+{
228
+	str contact, rtag;
229
+
230
+	     /* Parse the whole message, we will need all Record-Route headers */
231
+	if (parse_headers(_m, HDR_EOH, 0) == -1) {
232
+		LOG(L_ERR, "dlg_new_resp_uac(): Error while parsing headers\n");
233
+		return -1;
234
+	}
235
+	
236
+	if (get_contact_uri(_m, &contact) < 0) return -2;
237
+	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
238
+	
239
+	if (get_to_tag(_m, &rtag) < 0) goto err1;
240
+	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
241
+	
242
+	if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2;
243
+
244
+	return 0;
245
+ err2:
246
+	if (_d->id.rem_tag.s) pkg_free(_d->id.rem_tag.s);
247
+	_d->id.rem_tag.s = 0;
248
+	_d->id.rem_tag.len = 0;
249
+
250
+ err1:
251
+	if (_d->rem_target.s) pkg_free(_d->rem_target.s);
252
+	_d->rem_target.s = 0;
253
+	_d->rem_target.len = 0;
254
+	return -4;
255
+}
256
+
257
+
258
+/*
259
+ * Handle dialog in DLG_NEW state, we will be processing the
260
+ * first response
261
+ */
262
+static inline int dlg_new_resp_uac(dlg_t* _d, struct sip_msg* _m)
263
+{
264
+	int code;
265
+	     /*
266
+	      * Dialog is in DLG_NEW state, we will copy remote
267
+	      * target URI, remote tag if present, and route-set 
268
+	      * if present. And we will transit into DLG_CONFIRMED 
269
+	      * if the response was 2xx and to DLG_DESTROYED if the 
270
+	      * request was a negative final response.
271
+	      */
272
+
273
+	code = _m->first_line.u.reply.statuscode;
274
+
275
+	if (code < 200) {
276
+		     /* A provisional response, do nothing, we could
277
+		      * update remote tag and route set but we will do that
278
+		      * for a positive final response anyway and I don't want
279
+		      * bet on presence of these fields in provisional responses
280
+		      *
281
+		      * Send a request to jan@iptel.org if you need to update
282
+		      * the structures here
283
+		      */
284
+	} else if ((code >= 200) && (code < 299)) {
285
+		     /* A final response, update the structures and transit
286
+		      * into DLG_CONFIRMED
287
+		      */
288
+		if (response2dlg(_m, _d) < 0) return -1;
289
+		_d->state = DLG_CONFIRMED;
290
+	} else {
291
+		     /* 
292
+		      * A negative final response, mark the dialog as destroyed
293
+		      * Again, I do not update the structures here becuase it
294
+		      * makes no sense to me, a dialog shouldn't be used after
295
+		      * it is destroyed
296
+		      */
297
+		_d->state = DLG_DESTROYED;
298
+		     /* Signalize the termination with positive return value */
299
+		return 1;
300
+	}
301
+
302
+	return 0;
303
+}
304
+
305
+
306
+/*
307
+ * Handle dialog in DLG_EARLY state, we will be processing either
308
+ * next provisional response or a final response
309
+ */
310
+static inline int dlg_early_resp_uac(dlg_t* _d, struct sip_msg* _m)
311
+{
312
+	int code;
313
+	code = _m->first_line.u.reply.statuscode;	
314
+
315
+	if (code < 200) {
316
+		     /* We are in early state already, do nothing
317
+		      */
318
+	} else if ((code >= 200) && (code <= 299)) {
319
+		     /* Same as in dlg_new_resp_uac */
320
+		     /* A final response, update the structures and transit
321
+		      * into DLG_CONFIRMED
322
+		      */
323
+		if (response2dlg(_m, _d) < 0) return -1;
324
+		_d->state = DLG_CONFIRMED;
325
+	} else {
326
+		     /* Else terminate the dialog */
327
+		_d->state = DLG_DESTROYED;
328
+		     /* Signalize the termination with positive return value */
329
+		return 1;
330
+	}
331
+
332
+	return 0;
333
+}
334
+
335
+
336
+/*
337
+ * Extract method from CSeq header field
338
+ */
339
+static inline int get_cseq_method(struct sip_msg* _m, str* _method)
340
+{
341
+	if (!_m->cseq && ((parse_headers(_m, HDR_CSEQ, 0) == -1) || !_m->cseq)) {
342
+		LOG(L_ERR, "get_cseq_method(): Error while parsing CSeq\n");
343
+		return -1;
344
+	}
345
+
346
+	_method->s = get_cseq(_m)->method.s;
347
+	_method->len = get_cseq(_m)->method.len;
348
+	return 0;
349
+}
350
+
351
+
352
+/*
353
+ * Handle dialog in DLG_CONFIRMED state, we will be processing
354
+ * a response to a request sent within a dialog
355
+ */
356
+static inline int dlg_confirmed_resp_uac(dlg_t* _d, struct sip_msg* _m)
357
+{
358
+	int code;
359
+	str method, contact;
360
+
361
+	code = _m->first_line.u.reply.statuscode;	
362
+
363
+	     /* Dialog has been already confirmed, that means we received
364
+	      * a response to a request sent within the dialog. We will
365
+	      * update remote target URI if and only if the message sent was
366
+	      * a target refresher. 
367
+	      */
368
+
369
+	     /* FIXME: Currently we support only INVITEs as target refreshers,
370
+	      * this should be generalized
371
+	      */
372
+
373
+	     /* IF we receive a 481 response, terminate the dialog because
374
+	      * the remote peer indicated that it didn't have the dialog
375
+	      * state anymore, signal this termination with a positive return
376
+	      * value
377
+	      */
378
+	if (code == 481) {
379
+		_d->state = DLG_DESTROYED;
380
+		return 1;
381
+	}
382
+
383
+	     /* Do nothing if not 2xx */
384
+	if ((code < 200) || (code >= 300)) return 0;
385
+	
386
+	if (get_cseq_method(_m, &method) < 0) return -1;
387
+	if ((method.len == 6) && !memcmp("INVITE", method.s, 6)) {
388
+		     /* Get contact if any and update remote target */
389
+		if (parse_headers(_m, HDR_CONTACT, 0) == -1) {
390
+			LOG(L_ERR, "dlg_confirmed_resp_uac(): Error while parsing headers\n");
391
+			return -2;
392
+		}
393
+
394
+		     /* Try to extract contact URI */
395
+		if (get_contact_uri(_m, &contact) < 0) return -3;
396
+		     /* If there is a contact URI */
397
+		if (contact.len) {
398
+			     /* Free old remote target if any */
399
+			if (_d->rem_target.s) pkg_free(_d->rem_target.s);
400
+			     /* Duplicate new remote target */
401
+			if (str_duplicate(&_d->rem_target, &contact) < 0) return -4;
402
+		}
403
+	}
404
+
405
+	return 0;
406
+}
407
+
408
+
409
+/*
410
+ * A response arrived, update dialog
411
+ */
412
+int dlg_response_uac(dlg_t* _d, struct sip_msg* _m)
413
+{
414
+	if (!_d || !_m) {
415
+		LOG(L_ERR, "dlg_response_uac(): Invalid parameter value\n");
416
+		return -1;
417
+	}
418
+
419
+	     /* The main dispatcher */
420
+	switch(_d->state) {
421
+	case DLG_NEW:       
422
+		return dlg_new_resp_uac(_d, _m);
423
+
424
+	case DLG_EARLY:     
425
+		return dlg_early_resp_uac(_d, _m);
426
+
427
+	case DLG_CONFIRMED: 
428
+		return dlg_confirmed_resp_uac(_d, _m);
429
+
430
+	case DLG_DESTROYED:
431
+		LOG(L_ERR, "dlg_response_uac(): Cannot handle destroyed dialog\n");
432
+		return -2;
433
+	}
434
+
435
+	LOG(L_ERR, "dlg_response_uac(): Error in switch statement\n");
436
+	return -3;
437
+}
438
+
439
+
440
+/*
441
+ * Get CSeq number
442
+ * Does not parse headers !!
443
+ */
444
+static inline int get_cseq_value(struct sip_msg* _m, unsigned int* _cs)
445
+{
446
+	str num;
447
+
448
+	if (_m->cseq == 0) {
449
+		LOG(L_ERR, "get_cseq_value(): CSeq header not found\n");
450
+		return -1;
451
+	}
452
+
453
+	num.s = get_cseq(_m)->number.s;
454
+	num.len = get_cseq(_m)->number.len;
455
+
456
+	trim_leading(&num);
457
+	if (str2int(&num, _cs) < 0) {
458
+		LOG(L_ERR, "get_cseq_value(): Error while converting cseq number\n");
459
+		return -2;
460
+	}
461
+	return 0;
462
+}
463
+
464
+
465
+/*
466
+ * Copy To or From URI without tag parameter
467
+ */
468
+static inline int get_dlg_uri(struct hdr_field* _h, str* _s)
469
+{
470
+	struct to_param* ptr;
471
+	struct to_body* body;
472
+	char* tag = 0; /* Makes gcc happy */
473
+	int tag_len = 0, len;
474
+
475
+	if (!_h) {
476
+		LOG(L_ERR, "get_dlg_uri(): Header field not found\n");
477
+		return -1;
478
+	}
479
+
480
+	     /* From was already parsed when extracting tag
481
+	      * and To is parsed by default
482
+	      */
483
+	
484
+	body = (struct to_body*)_h->parsed;
485
+
486
+	ptr = body->param_lst;
487
+	while(ptr) {
488
+		if (ptr->type == TAG_PARAM) break;
489
+		ptr = ptr->next;
490
+	}
491
+
492
+	if (ptr) {
493
+	     /* Tag param found */
494
+		tag = ptr->name.s;
495
+		if (ptr->next) {
496
+			tag_len = ptr->next->name.s - tag;
497
+		} else {
498
+			tag_len = body->body.s + body->body.len - tag;
499
+		}
500
+	}
501
+
502
+	_s->s = pkg_malloc(body->body.len - tag_len);
503
+	if (!_s->s) {
504
+		LOG(L_ERR, "get_dlg_uri(): No memory left\n");
505
+		return -1;
506
+	}
507
+
508
+	if (tag_len) {
509
+		len = tag - body->body.s;
510
+		memcpy(_s->s, body->body.s, len);
511
+		memcpy(_s->s + len, tag + tag_len, body->body.len - len - tag_len);
512
+		_s->len = body->body.len - tag_len;
513
+	} else {
514
+		memcpy(_s->s, body->body.s, body->body.len);
515
+		_s->len = body->body.len;
516
+	}
517
+
518
+	return 0;
519
+}
520
+
521
+
522
+/*
523
+ * Extract all information from a request 
524
+ * and update a dialog structure
525
+ */
526
+static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
527
+{
528
+	str contact, rtag, callid;
529
+
530
+	if (parse_headers(_m, HDR_EOH, 0) == -1) {
531
+		LOG(L_ERR, "request2dlg(): Error while parsing headers");
532
+		return -1;
533
+	}
534
+
535
+	if (get_contact_uri(_m, &contact) < 0) return -2;
536
+	if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3;
537
+	
538
+	if (get_from_tag(_m, &rtag) < 0) goto err1;
539
+	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;
540
+
541
+	if (get_callid(_m, &callid) < 0) goto err2;
542
+	if (callid.len && str_duplicate(&_d->id.call_id, &callid) < 0) goto err2;
543
+
544
+	if (get_cseq_value(_m, &_d->rem_seq.value) < 0) goto err3;
545
+	_d->rem_seq.is_set = 1;
546
+
547
+	if (get_dlg_uri(_m->from, &_d->rem_uri) < 0) goto err3;
548
+	if (get_dlg_uri(_m->to, &_d->loc_uri) < 0) goto err4;
549
+
550
+	if (get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0) goto err5;	
551
+
552
+	return 0;
553
+ err5:
554
+	if (_d->loc_uri.s) pkg_free(_d->loc_uri.s);
555
+	_d->loc_uri.s = 0;
556
+	_d->loc_uri.len = 0;
557
+ err4:
558
+	if (_d->rem_uri.s) pkg_free(_d->rem_uri.s);
559
+	_d->rem_uri.s = 0;
560
+	_d->rem_uri.len = 0;
561
+ err3:
562
+	if (_d->id.call_id.s) pkg_free(_d->id.call_id.s);
563
+	_d->id.call_id.s = 0;
564
+	_d->id.call_id.len = 0;
565
+ err2:
566
+	if (_d->id.rem_tag.s) pkg_free(_d->id.rem_tag.s);
567
+	_d->id.rem_tag.s = 0;
568
+	_d->id.rem_tag.len = 0;
569
+ err1:
570
+	if (_d->rem_target.s) pkg_free(_d->rem_target.s);
571
+	_d->rem_target.s = 0;
572
+	_d->rem_target.len = 0;
573
+	return -4;
574
+}
575
+
576
+
577
+/*
578
+ * Establishing a new dialog, UAS side
579
+ */
580
+int new_dlg_uas(struct sip_msg* _req, int _code, str* _tag, dlg_t** _d)
581
+{
582
+	dlg_t* res;
583
+
584
+	if (!_req || !_tag || !_d) {
585
+		LOG(L_ERR, "new_dlg_uas(): Invalid parameter value\n");
586
+		return -1;
587
+	}
588
+
589
+	if ((_code < 200) || (_code > 299)) {
590
+		DBG("new_dlg_uas(): Not a 2xx, no dialog created\n");
591
+		return -2;
592
+	}
593
+
594
+	res = (dlg_t*)pkg_malloc(sizeof(dlg_t));
595
+	if (res == 0) {
596
+		LOG(L_ERR, "new_dlg_uac(): No memory left\n");
597
+		return -3;
598
+	}
599
+	     /* Clear everything */
600
+	memset(res, 0, sizeof(dlg_t));	
601
+
602
+	if (request2dlg(_req, res) < 0) {
603
+		LOG(L_ERR, "new_dlg_uas(): Error while converting request to dialog\n");
604
+		return -4;
605
+	}
606
+
607
+	if (_tag->len) {
608
+		if (str_duplicate(&res->id.loc_tag, _tag) < 0) {
609
+			free_dlg(res);
610
+			return -5;
611
+		}
612
+	}
613
+
614
+	*_d = res;
615
+	return 0;
616
+}
617
+
618
+
619
+/*
620
+ * UAS side - update a dialog from a request
621
+ */
622
+int dlg_request_uas(dlg_t* _d, struct sip_msg* _m)
623
+{
624
+	str contact;
625
+	int cseq;
626
+
627
+	if (!_d || !_m) {
628
+		LOG(L_ERR, "dlg_request_uas(): Invalid parameter value\n");
629
+		return -1;
630
+	}
631
+
632
+	     /* We must check if the request is not out of order or retransmission
633
+	      * first, if so then we will not update anything
634
+	      */
635
+	if (parse_headers(_m, HDR_CSEQ, 0) == -1) {
636
+		LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
637
+		return -2;
638
+	}
639
+	if (get_cseq_value(_m, &cseq) < 0) return -3;
640
+	if (_d->rem_seq.is_set && (cseq <= _d->rem_seq.value)) return 0;
641
+
642
+	     /* Neither out of order nor retransmission -> update */
643
+	_d->rem_seq.value = cseq;
644
+	_d->rem_seq.is_set = 1;
645
+	
646
+	     /* We will als update remote target URI if the message 
647
+	      * is target refresher
648
+	      */
649
+	if (_m->first_line.u.request.method_value == METHOD_INVITE) {
650
+		     /* target refresher */
651
+		if (parse_headers(_m, HDR_CONTACT, 0) == -1) {
652
+			LOG(L_ERR, "dlg_request_uas(): Error while parsing headers\n");
653
+			return -4;
654
+		}
655
+		
656
+		if (get_contact_uri(_m, &contact) < 0) return -5;
657
+		if (contact.len) {
658
+			if (_d->rem_target.s) pkg_free(_d->rem_target.s);
659
+			if (str_duplicate(&_d->rem_target, &contact) < 0) return -6;
660
+		}
661
+	}
662
+
663
+	return 0;
664
+}
665
+
666
+
667
+/*
668
+ * Destroy a dialog state
669
+ */
670
+void free_dlg(dlg_t* _d)
671
+{
672
+        if (!_d) return;
673
+
674
+	if (_d->id.call_id.s) pkg_free(_d->id.call_id.s);
675
+	if (_d->id.rem_tag.s) pkg_free(_d->id.rem_tag.s);
676
+	if (_d->id.loc_tag.s) pkg_free(_d->id.loc_tag.s);
677
+
678
+	if (_d->loc_uri.s) pkg_free(_d->loc_uri.s);
679
+	if (_d->rem_uri.s) pkg_free(_d->rem_uri.s);
680
+	if (_d->rem_target.s) pkg_free(_d->rem_target.s);
681
+
682
+	     /* Free all routes in the route set */
683
+	free_rr(&_d->route_set);
684
+	pkg_free(_d);
685
+}
686
+
687
+
688
+/*
689
+ * Print a dialog structure, just for debugging
690
+ */
691
+void print_dlg(dlg_t* _d)
692
+{
693
+	printf("====dlg_t===\n");
694
+	printf("id.call_id    : '%.*s'\n", _d->id.call_id.len, _d->id.call_id.s);
695
+	printf("id.rem_tag    : '%.*s'\n", _d->id.rem_tag.len, _d->id.rem_tag.s);
696
+	printf("id.loc_tag    : '%.*s'\n", _d->id.loc_tag.len, _d->id.loc_tag.s);
697
+	printf("loc_seq.value : %d\n", _d->loc_seq.value);
698
+	printf("loc_seq.is_set: %s\n", _d->loc_seq.is_set ? "YES" : "NO");
699
+	printf("rem_seq.value : %d\n", _d->rem_seq.value);
700
+	printf("rem_seq.is_set: %s\n", _d->rem_seq.is_set ? "YES" : "NO");
701
+	printf("loc_uri       : '%.*s'\n", _d->loc_uri.len, _d->loc_uri.s);
702
+	printf("rem_uri       : '%.*s'\n", _d->rem_uri.len, _d->rem_uri.s);
703
+	printf("rem_target    : '%.*s'\n", _d->rem_target.len, _d->rem_target.s);
704
+	printf("secure:       : %d\n", _d->secure);
705
+	printf("state         : ");
706
+	switch(_d->state) {
707
+	case DLG_NEW:       printf("DLG_NEW");       break;
708
+	case DLG_EARLY:     printf("DLG_EARLY");     break;
709
+	case DLG_CONFIRMED: printf("DLG_CONFIRMED"); break;
710
+	case DLG_DESTROYED: printf("DLG_DESTROYED"); break;
711
+	}
712
+	
713
+	print_rr(_d->route_set);
714
+	printf("====dlg_t====\n");
715
+}
0 716
new file mode 100644
... ...
@@ -0,0 +1,100 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * History:
5
+ * -------
6
+ * 2003-03-29 Created by janakj
7
+ */
8
+
9
+#ifndef DLG_H
10
+#define DLG_H
11
+
12
+
13
+#include "../../str.h"
14
+#include "../../parser/parse_rr.h"
15
+#include "../../parser/msg_parser.h"
16
+
17
+
18
+/*
19
+ * Dialog sequence
20
+ */
21
+typedef struct dlg_seq {
22
+	unsigned int value;    /* Sequence value */
23
+	unsigned char is_set;  /* is_set flag */
24
+} dlg_seq_t;
25
+
26
+
27
+/*
28
+ * Dialog state
29
+ */
30
+typedef enum dlg_state {
31
+	DLG_NEW = 0,   /* New dialog, no reply received yet */
32
+	DLG_EARLY,     /* Early dialog, provisional response received */
33
+	DLG_CONFIRMED, /* Confirmed dialog, 2xx received */
34
+	DLG_DESTROYED  /* Destroyed dialog */
35
+} dlg_state_t;
36
+
37
+
38
+/*
39
+ * Structure describing a dialog identifier
40
+ */
41
+typedef struct dlg_id {
42
+	str call_id;    /* Call-ID */
43
+	str rem_tag;    /* Remote tag of the dialog */
44
+	str loc_tag;    /* Local tag of the dialog */
45
+} dlg_id_t;
46
+
47
+
48
+/*
49
+ * Structure representing dialog state
50
+ */
51
+typedef struct dlg {
52
+	dlg_id_t id;            /* Dialog identifier */
53
+	dlg_seq_t loc_seq;      /* Local sequence number */
54
+	dlg_seq_t rem_seq;      /* Remote sequence number */
55
+	str loc_uri;            /* Local URI */
56
+	str rem_uri;            /* Remote URI */
57
+	str rem_target;         /* Remote target URI */
58
+	unsigned char secure;   /* Secure flag -- currently not used */
59
+	dlg_state_t state;      /* State of the dialog */
60
+	rr_t* route_set;        /* Route set */
61
+} dlg_t;
62
+
63
+
64
+/*
65
+ * Create a new dialog
66
+ */
67
+int new_dlg_uac(str* _cid, str* _ltag, unsigned int _lseq, str* _luri, str* _ruri, dlg_t** _d);
68
+
69
+
70
+/*
71
+ * A response arrived, update dialog
72
+ */
73
+int dlg_response_uac(dlg_t* _d, struct sip_msg* _m);
74
+
75
+
76
+/*
77
+ * Establishing a new dialog, UAS side
78
+ */
79
+int new_dlg_uas(struct sip_msg* _req, int _code, str* _tag, dlg_t** _d);
80
+
81
+
82
+/*
83
+ * UAS side - update a dialog from a request
84
+ */
85
+int dlg_request_uas(dlg_t* _d, struct sip_msg* _m);
86
+
87
+
88
+/*
89
+ * Destroy a dialog state
90
+ */
91
+void free_dlg(dlg_t* _d);
92
+
93
+
94
+/*
95
+ * Print a dialog structure, just for debugging
96
+ */
97
+void print_dlg(dlg_t* _d);
98
+
99
+
100
+#endif /* DLG_H */