Browse code

- new module for dialog support

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@806 689a6050-402a-0410-94f2-e92a70836424

Bogdan-Andrei Iancu authored on 14/04/2006 11:00:10
Showing 16 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+# $Id$
1
+#
2
+# WARNING: do not run this directly, it should be run by the master Makefile
3
+
4
+include ../../Makefile.defs
5
+auto_gen=
6
+NAME=dialog.so
7
+LIBS= 
8
+
9
+include ../../Makefile.modules
0 10
new file mode 100644
... ...
@@ -0,0 +1,309 @@
0
+
1
+dialog Module
2
+
3
+Bogdan-Andrei Iancu
4
+
5
+   Voice Sistem SRL
6
+
7
+Edited by
8
+
9
+Bogdan-Andrei Iancu
10
+
11
+   Copyright � 2006 voice-system.ro
12
+     _________________________________________________________
13
+
14
+   Table of Contents
15
+   1. User's Guide
16
+
17
+        1.1. Overview
18
+        1.2. How it works
19
+        1.3. Dependencies
20
+
21
+              1.3.1. OpenSER Modules
22
+              1.3.2. External Libraries or Applications
23
+
24
+        1.4. Exported Parameters
25
+
26
+              1.4.1. enable_stats (integer)
27
+              1.4.2. hash_size (integer)
28
+              1.4.3. rr_param (string)
29
+              1.4.4. dlg_flag (integer)
30
+              1.4.5. timeout_avp (string)
31
+              1.4.6. default_timeout (integer)
32
+              1.4.7. use_tight_match (integer)
33
+
34
+        1.5. Exported Functions
35
+        1.6. Exported statistics
36
+
37
+              1.6.1. active_dialogs
38
+              1.6.2. processed_dialogs
39
+              1.6.3. expired_dialogs
40
+
41
+        1.7. Exported pseudo-variables
42
+
43
+              1.7.1. $dlg_count
44
+
45
+   2. Developer's Guide
46
+
47
+        2.1. Available Functions
48
+
49
+              2.1.1. register_dlgcb (dialog, type, cb, param)
50
+
51
+   3. Frequently Asked Questions
52
+
53
+   List of Examples
54
+   1-1. Set enable_stats parameter
55
+   1-2. Set hash_size parameter
56
+   1-3. Set rr_param parameter
57
+   1-4. Set dlg_flag parameter
58
+   1-5. Set timeout_avp parameter
59
+   1-6. Set default_timeout parameter
60
+   1-7. Set use_tight_match parameter
61
+     _________________________________________________________
62
+
63
+Chapter 1. User's Guide
64
+
65
+1.1. Overview
66
+
67
+   The dialog module provides dialog awareness to OpenSER proxy.
68
+   Its functionality is to keep trace of the current dialogs, to
69
+   offer information about them (like how many dialogs are
70
+   active). The module exports no functions that could be used
71
+   directly from scripts.
72
+
73
+   The module, via an internal API, also provide the foundation
74
+   to build on top of it more complex dialog-based
75
+   functionalities via other OpenSER modules.
76
+     _________________________________________________________
77
+
78
+1.2. How it works
79
+
80
+   To create the dialog associated to an initial request, the
81
+   flag "dlg_flag" (Section 1.4.4) must be set before creating
82
+   the corresponding transaction.
83
+
84
+   The dialog is automatically destroyed when a "BYE" is
85
+   received. In case of no "BYE", the dialog lifetime is
86
+   controlled via the default timeout (see "default_timeout" -
87
+   Section 1.4.6) and custom timeout (see "timeout_avp" - Section
88
+   1.4.5). The dialog timeout is reset each time a sequential
89
+   request passes.
90
+     _________________________________________________________
91
+
92
+1.3. Dependencies
93
+
94
+1.3.1. OpenSER Modules
95
+
96
+   The following modules must be loaded before this module:
97
+
98
+     * TM - Transaction module
99
+     * RR - Record-Route module
100
+     _________________________________________________________
101
+
102
+1.3.2. External Libraries or Applications
103
+
104
+   The following libraries or applications must be installed
105
+   before running OpenSER with this module loaded:
106
+
107
+     * None.
108
+     _________________________________________________________
109
+
110
+1.4. Exported Parameters
111
+
112
+1.4.1. enable_stats (integer)
113
+
114
+   If the statistics support should be enabled or not. Via
115
+   statistic variables, the module provide information about the
116
+   dialog processing. Set it to zero to disable or to non-zero to
117
+   enable it.
118
+
119
+   Default value is "1 (enabled)". 
120
+
121
+   Example 1-1. Set enable_stats parameter
122
+...
123
+modparam("dialog", "enable_stats", 0)
124
+...
125
+     _________________________________________________________
126
+
127
+1.4.2. hash_size (integer)
128
+
129
+   The size of the hash table internally used to keep the
130
+   dialogs. A larger table is much faster but consumes more
131
+   memory. The hash size must be a power of 2 number.
132
+
133
+   Default value is "4096". 
134
+
135
+   Example 1-2. Set hash_size parameter
136
+...
137
+modparam("dialog", "hash_size", 1024)
138
+...
139
+     _________________________________________________________
140
+
141
+1.4.3. rr_param (string)
142
+
143
+   Name of the Record-Route parameter to be added with the dialog
144
+   cookie. It is used for fast dialog matching of the sequential
145
+   requests.
146
+
147
+   Default value is "did". 
148
+
149
+   Example 1-3. Set rr_param parameter
150
+...
151
+modparam("dialog", "rr_param", "xyz")
152
+...
153
+     _________________________________________________________
154
+
155
+1.4.4. dlg_flag (integer)
156
+
157
+   Flag to be used for marking if a dialog should be constructed
158
+   for the current request (make sense only for initial
159
+   requests).
160
+
161
+   Default value is "none". 
162
+
163
+   Example 1-4. Set dlg_flag parameter
164
+...
165
+modparam("dialog", "dlg_flag", 4)
166
+...
167
+     _________________________________________________________
168
+
169
+1.4.5. timeout_avp (string)
170
+
171
+   The specification of an AVP to contain a custom timeout (in
172
+   seconds) for the dialog. It may be used only in a request
173
+   (initial or sequential) context
174
+
175
+   Default value is "none". 
176
+
177
+   Example 1-5. Set timeout_avp parameter
178
+...
179
+modparam("usrloc", "timeout_avp", "$avp(i:10)")
180
+...
181
+     _________________________________________________________
182
+
183
+1.4.6. default_timeout (integer)
184
+
185
+   The default dialog timeout (in seconds) if no custom one is
186
+   set.
187
+
188
+   Default value is "43200 (12 hours)". 
189
+
190
+   Example 1-6. Set default_timeout parameter
191
+...
192
+modparam("dialog", "default_timeout", 21600)
193
+...
194
+     _________________________________________________________
195
+
196
+1.4.7. use_tight_match (integer)
197
+
198
+   If tight matching should be use dialog matching of sequential
199
+   requests. By default, the matching is done only on the RR
200
+   cookie; tight matching extra checks the callid. Set it to zero
201
+   to disable or to non-zero to enable it.
202
+
203
+   Default value is "0 (disabled)". 
204
+
205
+   Example 1-7. Set use_tight_match parameter
206
+...
207
+modparam("dialog", "use_tight_match", 1)
208
+...
209
+     _________________________________________________________
210
+
211
+1.5. Exported Functions
212
+
213
+   There are no exported functions that could be used in scripts.
214
+     _________________________________________________________
215
+
216
+1.6. Exported statistics
217
+
218
+1.6.1. active_dialogs
219
+
220
+   Returns the number of current active dialogs (may be confirmed
221
+   or not).
222
+     _________________________________________________________
223
+
224
+1.6.2. processed_dialogs
225
+
226
+   Returns the total number of processed dialogs (terminated,
227
+   expired or active) from the startup.
228
+     _________________________________________________________
229
+
230
+1.6.3. expired_dialogs
231
+
232
+   Returns the total number of expired dialogs from the startup.
233
+     _________________________________________________________
234
+
235
+1.7. Exported pseudo-variables
236
+
237
+1.7.1. $dlg_count
238
+
239
+   Returns the number of current active dialogs (may be confirmed
240
+   or not).
241
+     _________________________________________________________
242
+
243
+Chapter 2. Developer's Guide
244
+
245
+2.1. Available Functions
246
+
247
+2.1.1. register_dlgcb (dialog, type, cb, param)
248
+
249
+   Register a new callback to the dialog.
250
+
251
+   Meaning of the parameters is as follows:
252
+
253
+     * struct dlg_cell* dlg - dialog to register callback to. If
254
+       maybe NULL only for DLG_CREATED callback type, which is
255
+       not a per dialog type.
256
+     * int type - types of callbacks; more types may be register
257
+       for the same callback function; only DLG_CREATED must be
258
+       register alone. Possible types:
259
+          + DLG_CREATED - called when a new dialog is created -
260
+            it's a global type (not associated to any dialog)
261
+          + DLG_FAILED - called when the dialog was negatively
262
+            replied (non-2xx) - it's a per dialog type.
263
+          + DLG_CONFIRMED - called when the dialog is confirmed
264
+            (2xx replied) - it's a per dialog type.
265
+          + DLG_REQ_WITHIN - called when the dialog matches a
266
+            sequential request - it's a per dialog type.
267
+          + DLG_TERMINATED - called when the dialog is terminated
268
+            via BYE - it's a per dialog type.
269
+          + DLG_EXPIRED - called when the dialog expires without
270
+            receiving a BYE - it's a per dialog type.
271
+     * dialog_cb f - callback function to be called. Prototype
272
+       is: "void (dialog_cb) (struct dlg_cell* dlg, int type,
273
+       struct sip_msg* msg, void** param);"
274
+     * void *param - parameter to be passed to the callback
275
+       function.
276
+     _________________________________________________________
277
+
278
+Chapter 3. Frequently Asked Questions
279
+
280
+   3.1. Where can I find more about OpenSER?
281
+   3.2. Where can I post a question about this module?
282
+   3.3. How can I report a bug?
283
+
284
+   3.1. Where can I find more about OpenSER?
285
+
286
+   Take a look at http://openser.org/.
287
+
288
+   3.2. Where can I post a question about this module?
289
+
290
+   First at all check if your question was already answered on
291
+   one of our mailing lists:
292
+
293
+     * User Mailing List -
294
+       http://openser.org/cgi-bin/mailman/listinfo/users
295
+     * Developer Mailing List -
296
+       http://openser.org/cgi-bin/mailman/listinfo/devel
297
+
298
+   E-mails regarding any stable OpenSER release should be sent to
299
+   <users@openser.org> and e-mails regarding development versions
300
+   should be sent to <devel@openser.org>.
301
+
302
+   If you want to keep the mail private, send it to
303
+   <team@openser.org>.
304
+
305
+   3.3. How can I report a bug?
306
+
307
+   Please follow the guidelines provided at:
308
+   http://sourceforge.net/tracker/?group_id=139143.
0 309
new file mode 100644
... ...
@@ -0,0 +1,275 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * dialog module - basic support for dialog tracking
4
+ *
5
+ * Copyright (C) 2006 Voice Sistem SRL
6
+ *
7
+ * This file is part of openser, a free SIP server.
8
+ *
9
+ * openser is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * openser is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License 
20
+ * along with this program; if not, write to the Free Software 
21
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ *
23
+ * History:
24
+ * --------
25
+ *  2006-04-14  initial version (bogdan)
26
+ */
27
+
28
+
29
+#include <stdio.h>
30
+#include <string.h>
31
+#include <stdlib.h>
32
+
33
+#include "../../sr_module.h"
34
+#include "../../dprint.h"
35
+#include "../../error.h"
36
+#include "../../ut.h"
37
+#include "../../items.h"
38
+#include "../../script_cb.h"
39
+#include "../../fifo_server.h"
40
+#include "../../mem/mem.h"
41
+#include "../tm/tm_load.h"
42
+#include "../rr/api.h"
43
+#include "dlg_hash.h"
44
+#include "dlg_timer.h"
45
+#include "dlg_handlers.h"
46
+#include "dlg_load.h"
47
+#include "dlg_cb.h"
48
+
49
+MODULE_VERSION
50
+
51
+
52
+static int mod_init(void);
53
+static void mod_destroy();
54
+
55
+/* module parameter */
56
+static int dlg_hash_size = 4096;
57
+static char* rr_param = "did";
58
+static int dlg_flag = -1;
59
+static char* timeout_spec = 0;
60
+static int default_timeout = 60 * 60 * 12;  /* 12 hours */
61
+static int use_tight_match = 0;
62
+
63
+/* statistic variables */
64
+int dlg_enable_stats = 1;
65
+stat_var *active_dlgs = 0;
66
+stat_var *processed_dlgs = 0;
67
+stat_var *expired_dlgs = 0;
68
+
69
+struct tm_binds d_tmb;
70
+struct rr_binds d_rrb;
71
+xl_spec_t timeout_avp;
72
+
73
+
74
+
75
+
76
+static cmd_export_t cmds[]={
77
+	{"load_dlg",  (cmd_function)load_dlg,   0, 0,  0},
78
+	{0,0,0,0,0}
79
+};
80
+
81
+static param_export_t mod_params[]={
82
+	{ "enable_stats",          INT_PARAM, &dlg_enable_stats       },
83
+	{ "hash_size",             INT_PARAM, &dlg_hash_size          },
84
+	{ "rr_param",              STR_PARAM, &rr_param               },
85
+	{ "dlg_flag",              INT_PARAM, &dlg_flag               },
86
+	{ "timeout_avp",           STR_PARAM, &timeout_spec           },
87
+	{ "default_timeout",       INT_PARAM, &default_timeout        },
88
+	{ "use_tight_match",       INT_PARAM, &use_tight_match        },
89
+	{ 0,0,0 }
90
+};
91
+
92
+
93
+static stat_export_t mod_stats[] = {
94
+	{"active_dialogs" ,     STAT_NO_RESET,  &active_dlgs       },
95
+	{"processed_dialogs" ,  0,              &processed_dlgs    },
96
+	{"expired_dialogs" ,    0,              &expired_dlgs      },
97
+	{0,0,0}
98
+};
99
+
100
+
101
+
102
+struct module_exports exports= {
103
+	"dialog",        /* module's name */
104
+	cmds,            /* exported functions */
105
+	mod_params,      /* param exports */
106
+	mod_stats,       /* exported statistics */
107
+	mod_init,        /* module initialization function */
108
+	0,               /* reply processing function */
109
+	mod_destroy,
110
+	0                /* per-child init function */
111
+};
112
+
113
+
114
+
115
+int load_dlg( struct dlg_binds *dlgb )
116
+{
117
+	dlgb->register_dlgcb = register_dlgcb;
118
+	return 1;
119
+}
120
+
121
+
122
+
123
+int it_get_dlg_count(struct sip_msg *msg, xl_value_t *res, xl_param_t *param,
124
+		int flags)
125
+{
126
+	int n;
127
+	int l;
128
+	char *ch;
129
+
130
+	if(msg==NULL || res==NULL)
131
+		return -1;
132
+
133
+	n = active_dlgs ? get_stat_val(active_dlgs) : 0;
134
+	l = 0;
135
+	ch = int2str( n, &l);
136
+
137
+	res->rs.s = ch;
138
+	res->rs.len = l;
139
+
140
+	res->ri = n;
141
+	res->flags = XL_VAL_STR|XL_VAL_INT|XL_TYPE_INT;
142
+
143
+	return 0;
144
+}
145
+
146
+
147
+
148
+static int mod_init(void)
149
+{
150
+	int n;
151
+
152
+	LOG(L_INFO,"Dialog module - initializing\n");
153
+
154
+	/* param checkings */
155
+	if (dlg_flag==-1) {
156
+		LOG(L_ERR,"ERROR:dialog:mod_init: no dlg flag set!!\n");
157
+		return -1;
158
+	} else if (dlg_flag>=8*sizeof(int)) {
159
+		LOG(L_ERR,"ERROR:dialog:mod_init: invalid dlg flag %d!!\n",dlg_flag);
160
+		return -1;
161
+	}
162
+
163
+	if (rr_param==0 || rr_param[0]==0) {
164
+		LOG(L_ERR,"ERROR:dialog:mod_init: empty rr_param!!\n");
165
+		return -1;
166
+	} else if (strlen(rr_param)>MAX_DLG_RR_PARAM_NAME) {
167
+		LOG(L_ERR,"ERROR:dialog:mod_init: rr_param too long (max=%d)!!\n",
168
+			MAX_DLG_RR_PARAM_NAME);
169
+		return -1;
170
+	}
171
+
172
+	if (timeout_spec) {
173
+		if ( xl_parse_spec(timeout_spec, &timeout_avp, XL_THROW_ERROR
174
+		|XL_DISABLE_MULTI|XL_DISABLE_COLORS)==0 && (timeout_avp.type!=XL_AVP)){
175
+			LOG(L_ERR, "ERROR:dialog:mod_init: malformed or non AVP timeout "
176
+				"AVP definition in '%s'\n", timeout_spec);
177
+			return -1;
178
+		}
179
+	}
180
+
181
+	if (default_timeout<=0) {
182
+		LOG(L_ERR,"ERROR:dialog:mod_init: 0 default_timeout not accepted!!\n");
183
+		return -1;
184
+	}
185
+
186
+	/* if statistics are disabled, prevent their registration to core */
187
+	if (dlg_enable_stats==0)
188
+		exports.stats = 0;
189
+
190
+	/* load the TM API */
191
+	if (load_tm_api(&d_tmb)!=0) {
192
+		LOG(L_ERR, "ERROR:dialog:mod_init: can't load TM API\n");
193
+		return -1;
194
+	}
195
+
196
+	/* load RR API also */
197
+	if (load_rr_api(&d_rrb)!=0) {
198
+		LOG(L_ERR, "ERROR:dialog:mod_init: can't load RR API\n");
199
+		return -1;
200
+	}
201
+
202
+	/* register callbacks*/
203
+	/* listen for all incoming requests  */
204
+	if ( d_tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, dlg_onreq, 0 ) <=0 ) {
205
+		LOG(L_ERR,"ERROR:dialog:mod_init: cannot register TMCB_REQUEST_IN "
206
+			"callback\n");
207
+		return -1;
208
+	}
209
+
210
+	/* listen for all routed requests  */
211
+	if ( d_rrb.register_rrcb( dlg_onroute, 0 ) <0 ) {
212
+		LOG(L_ERR,"ERROR:dialog:mod_init: cannot register RR callback\n");
213
+		return -1;
214
+	}
215
+
216
+	if ( register_timer( dlg_timer_routine, 0, 1)<0 ) {
217
+		LOG(L_ERR,"ERROR:dialog:mod_init: failed to register timer \n");
218
+		return -1;
219
+	}
220
+
221
+	/* init handlers */
222
+	init_dlg_handlers( rr_param, dlg_flag,
223
+		timeout_spec?&timeout_avp:0, default_timeout, use_tight_match);
224
+
225
+	/* init timer */
226
+	if (init_dlg_timer(dlg_ontimeout)!=0) {
227
+		LOG(L_ERR,"ERROR:dialog:mod_init: cannot init timer list\n");
228
+		return -1;
229
+	}
230
+
231
+	/* init callbacks */
232
+	if (init_dlg_callbacks()!=0) {
233
+		LOG(L_ERR,"ERROR:dialog:mod_init: cannot init callbacks\n");
234
+		return -1;
235
+	}
236
+
237
+	/* initialized the hash table */
238
+	for( n=0 ; n<(8*sizeof(n)) ; n++) {
239
+		if (dlg_hash_size==(1<<n))
240
+			break;
241
+		if (dlg_hash_size<(1<<n)) {
242
+			LOG(L_WARN,"WARNING:dialog:mod_init: hash_size is not a power "
243
+				"of 2 as it should be -> rounding from %d to %d\n",
244
+				dlg_hash_size, 1<<(n-1));
245
+			dlg_hash_size = 1<<(n-1);
246
+		}
247
+	}
248
+	if ( init_dlg_table(dlg_hash_size)<0 ) {
249
+		LOG(L_ERR,"ERROR:dialog:mod_init: failed to create hash table\n");
250
+		return -1;
251
+	}
252
+
253
+	if ( register_fifo_cmd( fifo_print_dlgs, "dlg_list",0)<0 ) {
254
+		LOG(L_ERR,"ERROR:dialog:mod_init: failed to register fifo\n");
255
+		return -1;
256
+	}
257
+
258
+	if(xl_add_extra("dlg_count", it_get_dlg_count, 100 )!=0) {
259
+		LOG(L_ERR,"ERROR:dialog:mod_init: failed to register pvar "
260
+			"[dlg_no]\n");
261
+		return -1;
262
+	}
263
+
264
+	return 0;
265
+}
266
+
267
+
268
+static void mod_destroy()
269
+{
270
+	destroy_dlg_timer();
271
+	destroy_dlg_table();
272
+	destroy_dlg_callbacks();
273
+}
274
+
0 275
new file mode 100644
... ...
@@ -0,0 +1,138 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2006 Voice Sistem SRL
4
+ *
5
+ * This file is part of openser, a free SIP server.
6
+ *
7
+ * openser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * openser is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * History:
22
+ * --------
23
+ *  2006-04-14  initial version (bogdan)
24
+ */
25
+
26
+
27
+#include "../../mem/shm_mem.h"
28
+#include "../../dprint.h"
29
+#include "dlg_hash.h"
30
+#include "dlg_cb.h"
31
+
32
+static struct dlg_head_cbl* create_cbs = 0;
33
+
34
+int init_dlg_callbacks()
35
+{
36
+	create_cbs = (struct dlg_head_cbl*)shm_malloc(sizeof(struct dlg_head_cbl));
37
+	if (create_cbs==0) {
38
+		LOG(L_ERR,"ERROR:dialog:init_dlg_callbacks: no more shm mem\n");
39
+		return -1;
40
+	}
41
+	create_cbs->first = 0;
42
+	create_cbs->types = 0;
43
+	return 0;
44
+}
45
+
46
+
47
+void destroy_dlg_callbacks()
48
+{
49
+	struct dlg_callback *cb;
50
+	struct dlg_callback *cb_t;
51
+
52
+	if (create_cbs==0)
53
+		return;
54
+
55
+	cb = create_cbs->first;
56
+	while(cb) {
57
+		cb_t = cb;
58
+		cb = cb->next;
59
+		/* FIXME - what about parameters ? */
60
+		shm_free(cb_t);
61
+	}
62
+	create_cbs = 0;
63
+}
64
+
65
+
66
+int register_dlgcb(struct dlg_cell *dlg, int types, dialog_cb f, void *param )
67
+{
68
+	struct dlg_callback *cb;
69
+
70
+	if ( types&DLG_CREATED ) {
71
+		if (types!=DLG_CREATED) {
72
+			LOG(L_CRIT,"BUG:dialog:register_dlgcb: DLG_CREATED type must be "
73
+				"register alone!\n");
74
+			return -1;
75
+		}
76
+	} else {
77
+		if (dlg==0) {
78
+			LOG(L_CRIT,"BUG:dialog:register_dlgcb: non-DLG_CREATED type must "
79
+				"be register to a dialog (dlg missing)!\n");
80
+			return -1;
81
+		}
82
+	}
83
+	cb = (struct dlg_callback*)shm_malloc(sizeof(struct dlg_callback));
84
+	if (cb==0) {
85
+		LOG(L_ERR,"ERROR:dialog:register_dlgcb: no more shm mem\n");
86
+		return -1;
87
+	}
88
+
89
+	cb->types = types;
90
+	cb->callback = f;
91
+	cb->param = param;
92
+
93
+	if ( types&DLG_CREATED ) {
94
+		cb->next = create_cbs->first;
95
+		create_cbs->first = cb;
96
+		create_cbs->types |= types;
97
+	} else {
98
+		cb->next = dlg->cbs.first;
99
+		dlg->cbs.first = cb;
100
+		dlg->cbs.types |= types;
101
+	}
102
+
103
+	return 0;
104
+}
105
+
106
+
107
+void run_create_callbacks(struct dlg_cell *dlg, struct sip_msg *msg)
108
+{
109
+	struct dlg_callback *cb;
110
+
111
+	if (create_cbs->first==0)
112
+		return;
113
+
114
+	for ( cb=create_cbs->first; cb; cb=cb->next)  {
115
+		DBG("DEBUG:dialog:run_create_callbacks: dialog=%p\n",dlg);
116
+		cb->callback( dlg, DLG_CREATED, msg, &cb->param );
117
+	}
118
+	return;
119
+}
120
+
121
+
122
+void run_dlg_callbacks(int type , struct dlg_cell *dlg, struct sip_msg *msg)
123
+{
124
+	struct dlg_callback *cb;
125
+
126
+	if (dlg->cbs.first==0 || ((dlg->cbs.types)&type)==0 )
127
+		return;
128
+
129
+	for ( cb=dlg->cbs.first; cb; cb=cb->next)  {
130
+		if ( (cb->types)&type ) {
131
+			DBG("DEBUG:dialog:run_create_callbacks: dialog=%p, type=%d\n",
132
+				dlg, type);
133
+			cb->callback( dlg, type, msg, &cb->param );
134
+		}
135
+	}
136
+	return;
137
+}
0 138
new file mode 100644
... ...
@@ -0,0 +1,73 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2006 Voice Sistem SRLs
4
+ *
5
+ * This file is part of openser, a free SIP server.
6
+ *
7
+ * openser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * openser is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * History:
22
+ * --------
23
+ *  2006-04-11  initial version (bogdan)
24
+ */
25
+
26
+#ifndef _DIALOG_DLG_CB_H_
27
+#define _DIALOG_DLG_CB_H_
28
+
29
+#include "../../parser/msg_parser.h"
30
+
31
+struct dlg_cell* dlg;
32
+
33
+/* callback function prototype */
34
+typedef void (dialog_cb) (struct dlg_cell* dlg, int type, struct sip_msg* msg,
35
+		void** param);
36
+/* register callback function prototype */
37
+typedef int (*register_dlgcb_f)(struct dlg_cell* dlg, int cb_types,
38
+		dialog_cb f, void *param);
39
+
40
+
41
+#define DLG_CREATED      (1<<0)
42
+#define DLG_FAILED       (1<<1)
43
+#define DLG_CONFIRMED    (1<<2)
44
+#define DLG_REQ_WITHIN   (1<<3)
45
+#define DLG_TERMINATED   (1<<4)
46
+#define DLG_EXPIRED      (1<<5)
47
+
48
+struct dlg_callback {
49
+	int types;
50
+	dialog_cb* callback;
51
+	void *param;
52
+	struct dlg_callback* next;
53
+};
54
+
55
+
56
+struct dlg_head_cbl {
57
+	struct dlg_callback *first;
58
+	int types;
59
+};
60
+
61
+int init_dlg_callbacks();
62
+
63
+void destroy_dlg_callbacks();
64
+
65
+int register_dlgcb( struct dlg_cell* dlg, int types, dialog_cb f, void *param);
66
+
67
+void run_create_callbacks(struct dlg_cell *dlg, struct sip_msg *msg);
68
+
69
+void run_dlg_callbacks( int type , struct dlg_cell *dlg, struct sip_msg *msg);
70
+
71
+
72
+#endif
0 73
new file mode 100644
... ...
@@ -0,0 +1,386 @@
0
+/*
1
+ * $Id $
2
+ *
3
+ * Copyright (C) 2006 Voice System SRL
4
+ *
5
+ * This file is part of openser, a free SIP server.
6
+ *
7
+ * openser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * openser is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * History:
22
+ * --------
23
+ * 2006-04-14  initial version (bogdan)
24
+ */
25
+
26
+
27
+#include "string.h"
28
+
29
+#include "../../trim.h"
30
+#include "../../items.h"
31
+#include "../../statistics.h"
32
+#include "../../parser/parse_from.h"
33
+#include "../tm/tm_load.h"
34
+#include "../rr/api.h"
35
+#include "dlg_hash.h"
36
+#include "dlg_timer.h"
37
+#include "dlg_cb.h"
38
+#include "dlg_handlers.h"
39
+
40
+static str       rr_param;
41
+static int       dlg_flag;
42
+static xl_spec_t *timeout_avp;
43
+static int       default_timeout;
44
+static int       use_tight_match;
45
+
46
+extern struct tm_binds d_tmb;
47
+extern struct rr_binds d_rrb;
48
+
49
+/* statistic variables */
50
+extern int dlg_enable_stats;
51
+extern stat_var *active_dlgs;
52
+extern stat_var *processed_dlgs;
53
+extern stat_var *expired_dlgs;
54
+
55
+
56
+#define RR_DLG_PARAM_SIZE  (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
57
+#define DLG_SEPARATOR      '.'
58
+
59
+
60
+void init_dlg_handlers(char *rr_param_p, int dlg_flag_p,
61
+		xl_spec_t *timeout_avp_p ,int default_timeout_p, int use_tight_match_p)
62
+{
63
+	rr_param.s = rr_param_p;
64
+	rr_param.len = strlen(rr_param.s);
65
+
66
+	dlg_flag = 1<<dlg_flag_p;
67
+
68
+	timeout_avp = timeout_avp_p;
69
+	default_timeout = default_timeout_p;
70
+	use_tight_match = use_tight_match_p;
71
+}
72
+
73
+
74
+
75
+static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
76
+													unsigned int id)
77
+{
78
+	static char buf[RR_DLG_PARAM_SIZE];
79
+	str s;
80
+	int n;
81
+	char *p;
82
+
83
+	s.s = p = buf;
84
+
85
+	*(p++) = ';';
86
+	memcpy(p, rr_param.s, rr_param.len);
87
+	p += rr_param.len;
88
+	*(p++) = '=';
89
+
90
+	n = RR_DLG_PARAM_SIZE - (p-buf);
91
+	if (int2reverse_hex( &p, &n, entry)==-1)
92
+		return -1;
93
+
94
+	*(p++) = DLG_SEPARATOR;
95
+
96
+	n = RR_DLG_PARAM_SIZE - (p-buf);
97
+	if (int2reverse_hex( &p, &n, id)==-1)
98
+		return -1;
99
+
100
+	s.len = p-buf;
101
+
102
+	if (d_rrb.add_rr_param( req, &s)<0) {
103
+		LOG(L_ERR,"ERROR:dialog:add_dlg_rr_param: failed to add rr param\n");
104
+		return -1;
105
+	}
106
+
107
+	return 0;
108
+}
109
+
110
+
111
+
112
+static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
113
+{
114
+	struct sip_msg *rpl;
115
+	struct dlg_cell *dlg;
116
+	str tag;
117
+
118
+	dlg = (struct dlg_cell *)(*param->param);
119
+	if (dlg==0)
120
+		return;
121
+
122
+	if (type==TMCB_TRANS_DELETED) {
123
+		if (dlg->state == DLG_STATE_UNCONFIRMED) {
124
+			DBG("DEBUG:dialog:dlg_onreply: destroying unused dialog %p\n",dlg);
125
+			unref_dlg(dlg,1,1);
126
+			if_update_stat( dlg_enable_stats, active_dlgs, -1);
127
+		}
128
+		return;
129
+	}
130
+
131
+	if (param->code<200) {
132
+		DBG("DEBUG:dialog:dlg_onreply: dialog %p goes into Early state "
133
+			"with code %d\n", dlg, param->code);
134
+		dlg->state = DLG_STATE_EARLY;
135
+		return;
136
+	}
137
+
138
+	rpl = param->rpl;
139
+
140
+	if (param->code>=300) {
141
+		DBG("DEBUG:dialog:dlg_onreply: destroying unconfirmed dialog "
142
+			"with code %d (%p)\n", param->code, dlg);
143
+
144
+		/* dialog setup not completed (3456XX) */
145
+		run_dlg_callbacks( DLG_FAILED, dlg, rpl);
146
+
147
+		unref_dlg(dlg,1,1);
148
+		if_update_stat( dlg_enable_stats, active_dlgs, -1);
149
+		return;
150
+	}
151
+
152
+	DBG("DEBUG:dialog:dlg_onreply: dialog %p confirmed\n",dlg);
153
+	dlg->state = DLG_STATE_CONFIRMED;
154
+
155
+	if ( (!rpl->to && parse_headers(rpl, HDR_TO_F,0)<0) || !rpl->to ) {
156
+		LOG(L_ERR, "ERROR:dialog:dlg_onreply: bad reply or "
157
+			"missing TO hdr :-/\n");
158
+	} else {
159
+		tag = get_to(rpl)->tag_value;
160
+		if (tag.s!=0 && tag.len!=0)
161
+			dlg_set_totag( dlg, &tag);
162
+	}
163
+
164
+	/* dialog confirmed */
165
+	run_dlg_callbacks( DLG_CONFIRMED, dlg, rpl);
166
+
167
+	insert_dlg_timer( &dlg->tl, dlg->lifetime );
168
+
169
+	*(param->param) = 0;
170
+
171
+	return;
172
+}
173
+
174
+
175
+
176
+inline static int get_dlg_timeout(struct sip_msg *req)
177
+{
178
+	xl_value_t xl_val;
179
+
180
+	if( timeout_avp && xl_get_spec_value( req, timeout_avp, &xl_val, 0)==0
181
+	&& xl_val.flags&XL_VAL_INT && xl_val.ri>0 ) {
182
+		return xl_val.ri;
183
+	}
184
+	return default_timeout;
185
+}
186
+
187
+
188
+
189
+void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
190
+{
191
+	struct dlg_cell *dlg;
192
+	struct sip_msg *req;
193
+	str s;
194
+
195
+	req = param->req;
196
+
197
+	if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
198
+		LOG(L_ERR, "ERROR:dialog:dlg_onreq: bad request or "
199
+			"missing TO hdr :-/\n");
200
+		return;
201
+	}
202
+	s = get_to(req)->tag_value;
203
+	if (s.s!=0 && s.len!=0)
204
+		return;
205
+
206
+	if (req->first_line.u.request.method_value==METHOD_CANCEL)
207
+		return;
208
+
209
+	if ( (req->flags & dlg_flag) != dlg_flag)
210
+		return;
211
+
212
+	if ( parse_from_header(req)) {
213
+		LOG(L_ERR, "ERROR:dialog:dlg_onreq: bad request or "
214
+			"missing FROM hdr :-/\n");
215
+		return;
216
+	}
217
+	if ((!req->callid && parse_headers(req,HDR_CALLID_F,0)<0) || !req->callid){
218
+		LOG(L_ERR, "ERROR:dialog:dlg_onreq: bad request or "
219
+			"missing CALLID hdr :-/\n");
220
+		return;
221
+	}
222
+	s = req->callid->body;
223
+	trim(&s);
224
+
225
+	dlg = build_new_dlg( &s /*callid*/, &(get_from(req)->uri) /*from uri*/,
226
+		&(get_to(req)->uri) /*to uri*/,
227
+		&(get_from(req)->tag_value)/*from_tag*/ );
228
+	if (dlg==0) {
229
+		LOG(L_ERR,"ERROR:dialog:dlg_onreq: failed to create new dialog\n");
230
+		return;
231
+	}
232
+
233
+	/* first INVITE seen (dialog created, unconfirmed) */
234
+	run_create_callbacks( dlg, req);
235
+
236
+	link_dlg( dlg );
237
+
238
+	if ( add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
239
+		LOG(L_ERR,"ERROR:dialog:dlg_onreq: failed to add RR param\n");
240
+		goto error;
241
+	}
242
+
243
+	if ( d_tmb.register_tmcb( 0, t, TMCB_RESPONSE_OUT|TMCB_TRANS_DELETED,
244
+	dlg_onreply, (void*)dlg)<0 ) {
245
+		LOG(L_ERR,"ERROR:dialog:dlg_onreq: failed to register TMCB\n");
246
+		goto error;
247
+	}
248
+
249
+	dlg->lifetime = get_dlg_timeout(req);
250
+
251
+	if_update_stat( dlg_enable_stats, processed_dlgs, 1);
252
+	if_update_stat( dlg_enable_stats, active_dlgs, 1);
253
+
254
+	return;
255
+error:
256
+	unref_dlg(dlg,1,1);
257
+	return;
258
+}
259
+
260
+
261
+
262
+static inline int parse_dlg_rr_param(char *p, char *end,
263
+													int *h_entry, int *h_id)
264
+{
265
+	char *s;
266
+
267
+	for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ );
268
+	if (*p!=DLG_SEPARATOR) {
269
+		LOG(L_ERR,"ERROR:dialog:parse_dlg_rr_param: malformed rr param "
270
+			"'%.*s'\n", end-s, s);
271
+		return -1;
272
+	}
273
+
274
+	if ( (*h_entry=reverse_hex2int( s, p-s))<0 ) {
275
+		LOG(L_ERR,"ERROR:dialog:parse_dlg_rr_param: invalid hash entry "
276
+			"'%.*s'\n", p-s, s);
277
+		return -1;
278
+	}
279
+
280
+	if ( (*h_id=reverse_hex2int( p+1, end-(p+1)))<0 ) {
281
+		LOG(L_ERR,"ERROR:dialog:parse_dlg_rr_param: invalid hash id "
282
+			"'%.*s'\n", end-(p+1), p+1 );
283
+		return -1;
284
+	}
285
+
286
+	return 0;
287
+}
288
+
289
+
290
+
291
+void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
292
+{
293
+	struct dlg_cell *dlg;
294
+	str val;
295
+	str callid;
296
+	int h_entry;
297
+	int h_id;
298
+
299
+
300
+	if (d_rrb.get_route_param( req, &rr_param, &val)!=0) {
301
+		DBG("DEBUG:dialog:dlg_onroute: Route param '%.*s' not found\n",
302
+			rr_param.len,rr_param.s);
303
+		return;
304
+	}
305
+	DBG("DEBUG:dialog:dlg_onroute: route param is '%.*s' (len=%d)\n",
306
+		val.len, val.s, val.len);
307
+
308
+	if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
309
+		return;
310
+
311
+	dlg = lookup_dlg( h_entry, h_id);
312
+	if (dlg==0) {
313
+		LOG(L_WARN,"WARNING:dialog:dlg_onroute: unable to find dialog\n");
314
+		return;
315
+	}
316
+	if (use_tight_match) {
317
+		if ((!req->callid && parse_headers(req,HDR_CALLID_F,0)<0) ||
318
+		!req->callid) {
319
+			LOG(L_ERR, "ERROR:dialog:dlg_onroute: bad request or "
320
+				"missing CALLID hdr :-/\n");
321
+			return;
322
+		}
323
+		callid = req->callid->body;
324
+		trim(&callid);
325
+		if (dlg->callid.len!=callid.len ||
326
+		strncmp(dlg->callid.s,callid.s,callid.len)!=0) {
327
+			LOG(L_WARN,"WARNING:dialog:dlg_onroute: tight matching failed\n");
328
+			return;
329
+		}
330
+	}
331
+
332
+	if (req->first_line.u.request.method_value==METHOD_BYE) {
333
+		if (remove_dlg_timer(&dlg->tl)!=0) {
334
+			unref_dlg( dlg , 1, 0);
335
+			return;
336
+		}
337
+		if (dlg->state!=DLG_STATE_CONFIRMED)
338
+			LOG(L_WARN, "WARNING:dialog:dlg_onroute: BYE for "
339
+				"unconfirmed dialog ?!\n");
340
+
341
+		/* dialog terminated (BYE) */
342
+		run_dlg_callbacks( DLG_TERMINATED, dlg, req);
343
+
344
+		unref_dlg(dlg, 2, 1);
345
+		if_update_stat( dlg_enable_stats, active_dlgs, -1);
346
+		return;
347
+	} else {
348
+		/* within dialog request */
349
+		run_dlg_callbacks( DLG_REQ_WITHIN, dlg, req);
350
+	}
351
+
352
+	if (req->first_line.u.request.method_value!=METHOD_ACK) {
353
+		dlg->lifetime = get_dlg_timeout(req);
354
+		update_dlg_timer( &dlg->tl, dlg->lifetime );
355
+	}
356
+
357
+	unref_dlg( dlg , 1, 0);
358
+	return;
359
+}
360
+
361
+
362
+
363
+#define get_dlg_tl_payload(_tl_)  ((struct dlg_cell*)((char *)(_tl_)- \
364
+		(unsigned long)(&((struct dlg_cell*)0)->tl)))
365
+
366
+void dlg_ontimeout( struct dlg_tl *tl)
367
+{
368
+	struct dlg_cell *dlg;
369
+
370
+	dlg = get_dlg_tl_payload(tl);
371
+
372
+	DBG("DEBUG:dialog:dlg_timeout: dlg %p timeout at %d\n",
373
+		dlg, tl->timeout);
374
+
375
+	/* dialog timeout */
376
+	run_dlg_callbacks( DLG_EXPIRED, dlg, 0);
377
+
378
+	unref_dlg(dlg, 1, 1);
379
+
380
+	if_update_stat( dlg_enable_stats, expired_dlgs, 1);
381
+	if_update_stat( dlg_enable_stats, active_dlgs, -1);
382
+
383
+	return;
384
+}
385
+
0 386
new file mode 100644
... ...
@@ -0,0 +1,48 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2006 Voice System SRL
4
+ *
5
+ * This file is part of openser, a free SIP server.
6
+ *
7
+ * openser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * openser is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * History:
22
+ * --------
23
+ * 2006-04-14  initial version (bogdan)
24
+ */
25
+
26
+
27
+#ifndef _DIALOG_DLG_HANDLERS_H_
28
+#define _DIALOG_DLG_HANDLERS_H_
29
+
30
+#include "../../parser/msg_parser.h"
31
+#include "../../str.h"
32
+#include "../../items.h"
33
+#include "../tm/t_hooks.h"
34
+#include "dlg_timer.h"
35
+
36
+#define MAX_DLG_RR_PARAM_NAME 32
37
+
38
+void init_dlg_handlers(char *rr_param, int dlg_flag,
39
+		xl_spec_t *timeout_avp, int default_timeout, int use_tight_match);
40
+
41
+void dlg_onreq(struct cell* t, int type, struct tmcb_params *param);
42
+
43
+void dlg_onroute(struct sip_msg* req, str *rr_param, void *param);
44
+
45
+void dlg_ontimeout( struct dlg_tl *tl);
46
+
47
+#endif
0 48
new file mode 100644
... ...
@@ -0,0 +1,362 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2006 Voice System SRL
4
+ *
5
+ * This file is part of openser, a free SIP server.
6
+ *
7
+ * openser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * openser is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License 
18
+ * along with this program; if not, write to the Free Software 
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * History:
22
+ * --------
23
+ * 2006-04-14  initial version (bogdan)
24
+ */
25
+
26
+#include <stdlib.h>
27
+#include <string.h>
28
+
29
+#include "../../dprint.h"
30
+#include "../../ut.h"
31
+#include "../../hash_func.h"
32
+#include "../../fifo_server.h"
33
+#include "dlg_hash.h"
34
+
35
+
36
+#define MAX_LDG_LOCKS  2048
37
+#define MIN_LDG_LOCKS  2
38
+
39
+
40
+static struct dlg_table *d_table = 0;
41
+
42
+#define dlg_lock(_table, _entry) \
43
+		lock_set_get( (_table)->locks, (_entry)->lock_idx);
44
+#define dlg_unlock(_table, _entry) \
45
+		lock_set_release( (_table)->locks, (_entry)->lock_idx);
46
+
47
+
48
+int init_dlg_table(unsigned int size)
49
+{
50
+	int n;
51
+	int i;
52
+
53
+	d_table = (struct dlg_table*)shm_malloc
54
+		( sizeof(struct dlg_table) + size*sizeof(struct dlg_entry));
55
+	if (d_table==0) {
56
+		LOG(L_ERR, "ERROR:dialog:init_dlg_table: no more shm mem (1)\n");
57
+		goto error0;
58
+	}
59
+
60
+	memset( d_table, 0, sizeof(struct dlg_table) );
61
+	d_table->size = size;
62
+	d_table->entries = (struct dlg_entry*)(d_table+1);
63
+
64
+	n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
65
+	for(  ; n>=MIN_LDG_LOCKS ; n-- ) {
66
+		d_table->locks = lock_set_alloc(n);
67
+		if (d_table->locks==0)
68
+			continue;
69
+		if (lock_set_init(d_table->locks)==0) {
70
+			lock_set_dealloc(d_table->locks);
71
+			d_table->locks = 0;
72
+			continue;
73
+		}
74
+		d_table->locks_no = n;
75
+		break;
76
+	}
77
+
78
+	if (d_table->locks==0) {
79
+		LOG(L_ERR,"ERROR:dialog:init_dlg_table: unable to allocted at least "
80
+			"%d locks for the hash table\n",MIN_LDG_LOCKS);
81
+		goto error1;
82
+	}
83
+
84
+	for( i=0 ; i<size; i++ ) {
85
+		memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
86
+		d_table->entries[i].next_id = rand();
87
+		d_table->entries[i].lock_idx = i % d_table->locks_no;
88
+	}
89
+
90
+	return 0;
91
+error1:
92
+	shm_free( d_table );
93
+error0:
94
+	return -1;
95
+}
96
+
97
+
98
+
99
+static inline void destroy_dlg(struct dlg_cell *dlg)
100
+{
101
+	DBG("DBUG:dialog:destroy_dlg: destroing dialog %p\n",dlg);
102
+	if (dlg->to_tag.s && dlg->to_tag.len)
103
+		shm_free(dlg->to_tag.s);
104
+	shm_free(dlg);
105
+}
106
+
107
+
108
+
109
+void destroy_dlg_table()
110
+{
111
+	struct dlg_cell *dlg, *l_dlg;
112
+	int i;
113
+
114
+	if (d_table==0)
115
+		return;
116
+
117
+	if (d_table->locks) {
118
+		lock_set_destroy(d_table->locks);
119
+		lock_set_dealloc(d_table->locks);
120
+	}
121
+
122
+	for( i=0 ; i<d_table->size; i++ ) {
123
+		dlg = d_table->entries[i].first;
124
+		while (dlg) {
125
+			l_dlg = dlg;
126
+			dlg = dlg->next;
127
+			destroy_dlg(l_dlg);
128
+		}
129
+
130
+	}
131
+
132
+	shm_free(d_table);
133
+	d_table = 0;
134
+
135
+	return;
136
+}
137
+
138
+
139
+
140
+struct dlg_cell* build_new_dlg( str *callid, str *from_uri, str *to_uri,
141
+												str *from_tag)
142
+{
143
+	struct dlg_cell *dlg;
144
+	int len;
145
+	char *p;
146
+
147
+	len = sizeof(struct dlg_cell) + callid->len + from_uri->len +
148
+		to_uri->len + from_tag->len;
149
+	dlg = (struct dlg_cell*)shm_malloc( len );
150
+	if (dlg==0) {
151
+		LOG(L_ERR,"ERROR:dialog:build_new_dlg: no more shm mem (%d)\n",len);
152
+		return 0;
153
+	}
154
+
155
+	memset( dlg, 0, len);
156
+	dlg->state = DLG_STATE_UNCONFIRMED;
157
+
158
+	dlg->h_entry = core_hash( from_tag, callid, d_table->size);
159
+	DBG("DEBUG:dialog:build_new_dlg: new dialog on hash %u\n",dlg->h_entry);
160
+
161
+	p = (char*)(dlg+1);
162
+
163
+	dlg->callid.s = p;