Browse code

modules_k/*: moved k modules in directory modules/

Daniel-Constantin Mierla authored on 20/01/2013 11:57:52
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1126 +0,0 @@
1
-/**
2
- * $Id$
3
- *
4
- * dispatcher module -- stateless load balancing
5
- *
6
- * Copyright (C) 2004-2005 FhG Fokus
7
- * Copyright (C) 2006 Voice Sistem SRL
8
- *
9
- * This file is part of Kamailio, a free SIP server.
10
- *
11
- * Kamailio is free software; you can redistribute it and/or modify
12
- * it under the terms of the GNU General Public License as published by
13
- * the Free Software Foundation; either version 2 of the License, or
14
- * (at your option) any later version
15
- *
16
- * Kamailio is distributed in the hope that it will be useful,
17
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
- * GNU General Public License for more details.
20
- *
21
- * You should have received a copy of the GNU General Public License 
22
- * along with this program; if not, write to the Free Software 
23
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
- *
25
- * History
26
- * -------
27
- * 2004-07-31  first version, by daniel
28
- * 2007-01-11  Added a function to check if a specific gateway is in a group
29
- *				(carsten - Carsten Bock, BASIS AudioNet GmbH)
30
- * 2007-02-09  Added active probing of failed destinations and automatic
31
- *				re-enabling of destinations (carsten)
32
- * 2007-05-08  Ported the changes to SVN-Trunk and renamed ds_is_domain
33
- *				to ds_is_from_list.  (carsten)
34
- * 2007-07-18  Added support for load/reload groups from DB 
35
- * 			   reload triggered from ds_reload MI_Command (ancuta)
36
- */
37
-
38
-/*! \file
39
- * \ingroup dispatcher
40
- * \brief Dispatcher :: Dispatch
41
- */
42
-
43
-/*! \defgroup dispatcher Dispatcher :: Load balancing and failover module
44
- * 	The dispatcher module implements a set of functions for distributing SIP requests on a 
45
- *	set of servers, but also grouping of server resources.
46
- *
47
- *	- The module has an internal API exposed to other modules.
48
- *	- The module implements a couple of MI functions for managing the list of server resources
49
- */
50
-
51
-#include <stdio.h>
52
-#include <string.h>
53
-#include <stdlib.h>
54
-#include <sys/types.h>
55
-#include <unistd.h>
56
-
57
-#include "../../lib/kmi/mi.h"
58
-#include "../../sr_module.h"
59
-#include "../../dprint.h"
60
-#include "../../error.h"
61
-#include "../../ut.h"
62
-#include "../../route.h"
63
-#include "../../mem/mem.h"
64
-#include "../../mod_fix.h"
65
-#include "../../rpc.h"
66
-#include "../../rpc_lookup.h"
67
-
68
-#include "ds_ht.h"
69
-#include "dispatch.h"
70
-#include "config.h"
71
-#include "api.h"
72
-
73
-MODULE_VERSION
74
-
75
-#define DS_SET_ID_COL			"setid"
76
-#define DS_DEST_URI_COL			"destination"
77
-#define DS_DEST_FLAGS_COL		"flags"
78
-#define DS_DEST_PRIORITY_COL	"priority"
79
-#define DS_DEST_ATTRS_COL		"attrs"
80
-#define DS_TABLE_NAME			"dispatcher"
81
-
82
-/** parameters */
83
-char *dslistfile = CFG_DIR"dispatcher.list";
84
-int  ds_force_dst   = 1;
85
-int  ds_flags       = 0; 
86
-int  ds_use_default = 0; 
87
-static str dst_avp_param = {NULL, 0};
88
-static str grp_avp_param = {NULL, 0};
89
-static str cnt_avp_param = {NULL, 0};
90
-static str dstid_avp_param = {NULL, 0};
91
-static str attrs_avp_param = {NULL, 0};
92
-str hash_pvar_param = {NULL, 0};
93
-
94
-int_str dst_avp_name;
95
-unsigned short dst_avp_type;
96
-int_str grp_avp_name;
97
-unsigned short grp_avp_type;
98
-int_str cnt_avp_name;
99
-unsigned short cnt_avp_type;
100
-int_str dstid_avp_name;
101
-unsigned short dstid_avp_type;
102
-int_str attrs_avp_name;
103
-unsigned short attrs_avp_type;
104
-
105
-pv_elem_t * hash_param_model = NULL;
106
-
107
-int probing_threshhold = 1; /* number of failed requests, before a destination
108
-							   is taken into probing */
109
-str ds_ping_method = {"OPTIONS",7};
110
-str ds_ping_from   = {"sip:dispatcher@localhost", 24};
111
-static int ds_ping_interval = 0;
112
-int ds_probing_mode  = DS_PROBE_NONE;
113
-
114
-static str ds_ping_reply_codes_str= {NULL, 0};
115
-static int** ds_ping_reply_codes = NULL;
116
-static int* ds_ping_reply_codes_cnt;
117
-
118
-int ds_hash_size = 0;
119
-int ds_hash_expire = 7200;
120
-int ds_hash_initexpire = 7200;
121
-int ds_hash_check_interval = 30;
122
-
123
-str ds_outbound_proxy = {0, 0};
124
-
125
-/* tm */
126
-struct tm_binds tmb;
127
-
128
-/*db */
129
-str ds_db_url            = {NULL, 0};
130
-str ds_set_id_col        = str_init(DS_SET_ID_COL);
131
-str ds_dest_uri_col      = str_init(DS_DEST_URI_COL);
132
-str ds_dest_flags_col    = str_init(DS_DEST_FLAGS_COL);
133
-str ds_dest_priority_col = str_init(DS_DEST_PRIORITY_COL);
134
-str ds_dest_attrs_col    = str_init(DS_DEST_ATTRS_COL);
135
-str ds_table_name        = str_init(DS_TABLE_NAME);
136
-
137
-str ds_setid_pvname   = {NULL, 0};
138
-pv_spec_t ds_setid_pv;
139
-
140
-/** module functions */
141
-static int mod_init(void);
142
-static int child_init(int);
143
-
144
-static int ds_parse_reply_codes();
145
-static int ds_init_rpc(void);
146
-
147
-static int w_ds_select_dst(struct sip_msg*, char*, char*);
148
-static int w_ds_select_domain(struct sip_msg*, char*, char*);
149
-static int w_ds_next_dst(struct sip_msg*, char*, char*);
150
-static int w_ds_next_domain(struct sip_msg*, char*, char*);
151
-static int w_ds_mark_dst0(struct sip_msg*, char*, char*);
152
-static int w_ds_mark_dst1(struct sip_msg*, char*, char*);
153
-static int w_ds_load_unset(struct sip_msg*, char*, char*);
154
-static int w_ds_load_update(struct sip_msg*, char*, char*);
155
-
156
-static int w_ds_is_from_list0(struct sip_msg*, char*, char*);
157
-static int w_ds_is_from_list1(struct sip_msg*, char*, char*);
158
-
159
-static void destroy(void);
160
-
161
-static int ds_warn_fixup(void** param, int param_no);
162
-
163
-static struct mi_root* ds_mi_set(struct mi_root* cmd, void* param);
164
-static struct mi_root* ds_mi_list(struct mi_root* cmd, void* param);
165
-static struct mi_root* ds_mi_reload(struct mi_root* cmd_tree, void* param);
166
-static int mi_child_init(void);
167
-
168
-static cmd_export_t cmds[]={
169
-	{"ds_select_dst",    (cmd_function)w_ds_select_dst,    2,
170
-		fixup_igp_igp, 0, REQUEST_ROUTE|FAILURE_ROUTE},
171
-	{"ds_select_domain", (cmd_function)w_ds_select_domain, 2,
172
-		fixup_igp_igp, 0, REQUEST_ROUTE|FAILURE_ROUTE},
173
-	{"ds_next_dst",      (cmd_function)w_ds_next_dst,      0,
174
-		ds_warn_fixup, 0, REQUEST_ROUTE|FAILURE_ROUTE},
175
-	{"ds_next_domain",   (cmd_function)w_ds_next_domain,   0,
176
-		ds_warn_fixup, 0, REQUEST_ROUTE|FAILURE_ROUTE},
177
-	{"ds_mark_dst",      (cmd_function)w_ds_mark_dst0,     0,
178
-		ds_warn_fixup, 0, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE},
179
-	{"ds_mark_dst",      (cmd_function)w_ds_mark_dst1,     1,
180
-		ds_warn_fixup, 0, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE},
181
-	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list0, 0,
182
-		0, 0, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE},
183
-	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list1, 1,
184
-		fixup_uint_null, 0, ANY_ROUTE},
185
-	{"ds_load_unset",    (cmd_function)w_ds_load_unset,   0,
186
-		0, 0, ANY_ROUTE},
187
-	{"ds_load_update",   (cmd_function)w_ds_load_update,  0,
188
-		0, 0, ANY_ROUTE},
189
-	{"bind_dispatcher",   (cmd_function)bind_dispatcher,  0,
190
-		0, 0, 0},
191
-	{0,0,0,0,0,0}
192
-};
193
-
194
-
195
-static param_export_t params[]={
196
-	{"list_file",       STR_PARAM, &dslistfile},
197
-	{"db_url",		    STR_PARAM, &ds_db_url.s},
198
-	{"table_name", 	    STR_PARAM, &ds_table_name.s},
199
-	{"setid_col",       STR_PARAM, &ds_set_id_col.s},
200
-	{"destination_col", STR_PARAM, &ds_dest_uri_col.s},
201
-	{"flags_col",       STR_PARAM, &ds_dest_flags_col.s},
202
-	{"priority_col",    STR_PARAM, &ds_dest_priority_col.s},
203
-	{"attrs_col",       STR_PARAM, &ds_dest_attrs_col.s},
204
-	{"force_dst",       INT_PARAM, &ds_force_dst},
205
-	{"flags",           INT_PARAM, &ds_flags},
206
-	{"use_default",     INT_PARAM, &ds_use_default},
207
-	{"dst_avp",         STR_PARAM, &dst_avp_param.s},
208
-	{"grp_avp",         STR_PARAM, &grp_avp_param.s},
209
-	{"cnt_avp",         STR_PARAM, &cnt_avp_param.s},
210
-	{"dstid_avp",       STR_PARAM, &dstid_avp_param.s},
211
-	{"attrs_avp",       STR_PARAM, &attrs_avp_param.s},
212
-	{"hash_pvar",       STR_PARAM, &hash_pvar_param.s},
213
-	{"setid_pvname",    STR_PARAM, &ds_setid_pvname.s},
214
-	{"ds_probing_threshhold", INT_PARAM, &probing_threshhold},
215
-	{"ds_ping_method",     STR_PARAM, &ds_ping_method.s},
216
-	{"ds_ping_from",       STR_PARAM, &ds_ping_from.s},
217
-	{"ds_ping_interval",   INT_PARAM, &ds_ping_interval},
218
-	{"ds_ping_reply_codes", STR_PARAM, &ds_ping_reply_codes_str},
219
-	{"ds_probing_mode",    INT_PARAM, &ds_probing_mode},
220
-	{"ds_hash_size",       INT_PARAM, &ds_hash_size},
221
-	{"ds_hash_expire",     INT_PARAM, &ds_hash_expire},
222
-	{"ds_hash_initexpire", INT_PARAM, &ds_hash_initexpire},
223
-	{"ds_hash_check_interval", INT_PARAM, &ds_hash_check_interval},
224
-	{"outbound_proxy",  STR_PARAM, &ds_outbound_proxy.s},
225
-	{0,0,0}
226
-};
227
-
228
-
229
-static mi_export_t mi_cmds[] = {
230
-	{ "ds_set_state",   ds_mi_set,     0,                 0,  0            },
231
-	{ "ds_list",        ds_mi_list,    MI_NO_INPUT_FLAG,  0,  0            },
232
-	{ "ds_reload",      ds_mi_reload,  0,                 0,  mi_child_init},
233
-	{ 0, 0, 0, 0, 0}
234
-};
235
-
236
-
237
-/** module exports */
238
-struct module_exports exports= {
239
-	"dispatcher",
240
-	DEFAULT_DLFLAGS, /* dlopen flags */
241
-	cmds,
242
-	params,
243
-	0,          /* exported statistics */
244
-	mi_cmds,    /* exported MI functions */
245
-	0,          /* exported pseudo-variables */
246
-	0,          /* extra processes */
247
-	mod_init,   /* module initialization function */
248
-	0,
249
-	(destroy_function) destroy,
250
-	child_init  /* per-child init function */
251
-};
252
-
253
-/**
254
- * init module function
255
- */
256
-static int mod_init(void)
257
-{
258
-	pv_spec_t avp_spec;
259
-
260
-	if(register_mi_mod(exports.name, mi_cmds)!=0)
261
-	{
262
-		LM_ERR("failed to register MI commands\n");
263
-		return -1;
264
-	}
265
-	if(ds_init_rpc()<0)
266
-	{
267
-		LM_ERR("failed to register RPC commands\n");
268
-		return -1;
269
-	}
270
-
271
-	if (dst_avp_param.s)
272
-		dst_avp_param.len = strlen(dst_avp_param.s);
273
-	if (grp_avp_param.s)
274
-		grp_avp_param.len = strlen(grp_avp_param.s);
275
-	if (cnt_avp_param.s)
276
-		cnt_avp_param.len = strlen(cnt_avp_param.s);	
277
-	if (dstid_avp_param.s)
278
-		dstid_avp_param.len = strlen(dstid_avp_param.s);
279
-	if (attrs_avp_param.s)
280
-		attrs_avp_param.len = strlen(attrs_avp_param.s);
281
-	if (hash_pvar_param.s)
282
-		hash_pvar_param.len = strlen(hash_pvar_param.s);
283
-	if (ds_setid_pvname.s)
284
-		ds_setid_pvname.len = strlen(ds_setid_pvname.s);
285
-	if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s);
286
-	if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s);
287
-	if (ds_outbound_proxy.s) ds_outbound_proxy.len = strlen(ds_outbound_proxy.s);
288
-
289
-	if(cfg_declare("dispatcher", dispatcher_cfg_def,
290
-				&default_dispatcher_cfg, cfg_sizeof(dispatcher),
291
-				&dispatcher_cfg)){
292
-		LM_ERR("Fail to declare the configuration\n");
293
-		return -1;
294
-	}
295
-
296
-	/* Initialize the counter */
297
-	ds_ping_reply_codes = (int**)shm_malloc(sizeof(unsigned int*));
298
-	*ds_ping_reply_codes = 0;
299
-	ds_ping_reply_codes_cnt = (int*)shm_malloc(sizeof(int));
300
-	*ds_ping_reply_codes_cnt = 0;
301
-	if(ds_ping_reply_codes_str.s) {
302
-		ds_ping_reply_codes_str.len = strlen(ds_ping_reply_codes_str.s);
303
-		cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str)
304
-			= ds_ping_reply_codes_str;
305
-		if(ds_parse_reply_codes()< 0)
306
-		{
307
-			return -1;
308
-		}
309
-	}	
310
-	/* Copy Threshhold to Config */
311
-	cfg_get(dispatcher, dispatcher_cfg, probing_threshhold)
312
-		= probing_threshhold;
313
-
314
-
315
-	if(init_data()!= 0)
316
-		return -1;
317
-
318
-	if(ds_db_url.s)
319
-	{
320
-		ds_db_url.len     = strlen(ds_db_url.s);
321
-		ds_table_name.len = strlen(ds_table_name.s);
322
-		ds_set_id_col.len        = strlen(ds_set_id_col.s);
323
-		ds_dest_uri_col.len      = strlen(ds_dest_uri_col.s);
324
-		ds_dest_flags_col.len    = strlen(ds_dest_flags_col.s);
325
-		ds_dest_priority_col.len = strlen(ds_dest_priority_col.s);
326
-		ds_dest_attrs_col.len    = strlen(ds_dest_attrs_col.s);
327
-
328
-		if(init_ds_db()!= 0)
329
-		{
330
-			LM_ERR("could not initiate a connect to the database\n");
331
-			return -1;
332
-		}
333
-	} else {
334
-		if(ds_load_list(dslistfile)!=0) {
335
-			LM_ERR("no dispatching list loaded from file\n");
336
-			return -1;
337
-		} else {
338
-			LM_DBG("loaded dispatching list\n");
339
-		}
340
-	}
341
-
342
-	if (dst_avp_param.s && dst_avp_param.len > 0)
343
-	{
344
-		if (pv_parse_spec(&dst_avp_param, &avp_spec)==0
345
-				|| avp_spec.type!=PVT_AVP)
346
-		{
347
-			LM_ERR("malformed or non AVP %.*s AVP definition\n",
348
-					dst_avp_param.len, dst_avp_param.s);
349
-			return -1;
350
-		}
351
-
352
-		if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name, &dst_avp_type)!=0)
353
-		{
354
-			LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len,
355
-					dst_avp_param.s);
356
-			return -1;
357
-		}
358
-	} else {
359
-		dst_avp_name.n = 0;
360
-		dst_avp_type = 0;
361
-	}
362
-	if (grp_avp_param.s && grp_avp_param.len > 0)
363
-	{
364
-		if (pv_parse_spec(&grp_avp_param, &avp_spec)==0
365
-				|| avp_spec.type!=PVT_AVP)
366
-		{
367
-			LM_ERR("malformed or non AVP %.*s AVP definition\n",
368
-					grp_avp_param.len, grp_avp_param.s);
369
-			return -1;
370
-		}
371
-
372
-		if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name, &grp_avp_type)!=0)
373
-		{
374
-			LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len,
375
-					grp_avp_param.s);
376
-			return -1;
377
-		}
378
-	} else {
379
-		grp_avp_name.n = 0;
380
-		grp_avp_type = 0;
381
-	}
382
-	if (cnt_avp_param.s && cnt_avp_param.len > 0)
383
-	{
384
-		if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0
385
-				|| avp_spec.type!=PVT_AVP)
386
-		{
387
-			LM_ERR("malformed or non AVP %.*s AVP definition\n",
388
-					cnt_avp_param.len, cnt_avp_param.s);
389
-			return -1;
390
-		}
391
-
392
-		if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name, &cnt_avp_type)!=0)
393
-		{
394
-			LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len,
395
-					cnt_avp_param.s);
396
-			return -1;
397
-		}
398
-	} else {
399
-		cnt_avp_name.n = 0;
400
-		cnt_avp_type = 0;
401
-	}
402
-	if (dstid_avp_param.s && dstid_avp_param.len > 0)
403
-	{
404
-		if (pv_parse_spec(&dstid_avp_param, &avp_spec)==0
405
-				|| avp_spec.type!=PVT_AVP)
406
-		{
407
-			LM_ERR("malformed or non AVP %.*s AVP definition\n",
408
-					dstid_avp_param.len, dstid_avp_param.s);
409
-			return -1;
410
-		}
411
-
412
-		if(pv_get_avp_name(0, &(avp_spec.pvp), &dstid_avp_name,
413
-					&dstid_avp_type)!=0)
414
-		{
415
-			LM_ERR("[%.*s]- invalid AVP definition\n", dstid_avp_param.len,
416
-					dstid_avp_param.s);
417
-			return -1;
418
-		}
419
-	} else {
420
-		dstid_avp_name.n = 0;
421
-		dstid_avp_type = 0;
422
-	}
423
-
424
-	if (attrs_avp_param.s && attrs_avp_param.len > 0)
425
-	{
426
-		if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0
427
-				|| avp_spec.type!=PVT_AVP)
428
-		{
429
-			LM_ERR("malformed or non AVP %.*s AVP definition\n",
430
-					attrs_avp_param.len, attrs_avp_param.s);
431
-			return -1;
432
-		}
433
-
434
-		if(pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name,
435
-					&attrs_avp_type)!=0)
436
-		{
437
-			LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len,
438
-					attrs_avp_param.s);
439
-			return -1;
440
-		}
441
-	} else {
442
-		attrs_avp_name.n = 0;
443
-		attrs_avp_type = 0;
444
-	}
445
-
446
-	if (hash_pvar_param.s && *hash_pvar_param.s) {
447
-		if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0
448
-				|| hash_param_model==NULL) {
449
-			LM_ERR("malformed PV string: %s\n", hash_pvar_param.s);
450
-			return -1;
451
-		}		
452
-	} else {
453
-		hash_param_model = NULL;
454
-	}
455
-
456
-	if(ds_setid_pvname.s!=0)
457
-	{
458
-		if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL
459
-				|| !pv_is_w(&ds_setid_pv))
460
-		{
461
-			LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s);
462
-			return -1;
463
-		}
464
-	}
465
-	if (dstid_avp_param.s && dstid_avp_param.len > 0)
466
-	{
467
-		if(ds_hash_size>0)
468
-		{
469
-			if(ds_hash_load_init(1<<ds_hash_size, ds_hash_expire,
470
-						ds_hash_initexpire)<0)
471
-				return -1;
472
-			register_timer(ds_ht_timer, NULL, ds_hash_check_interval);
473
-		} else {
474
-			LM_ERR("call load dispatching DSTID_AVP set but no size"
475
-					" for hash table\n");
476
-			return -1;
477
-		}
478
-	}
479
-	/* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */
480
-	if (ds_ping_interval > 0)
481
-	{
482
-		/*****************************************************
483
-		 * TM-Bindings
484
-		 *****************************************************/
485
-		if (load_tm_api( &tmb ) == -1)
486
-		{
487
-			LM_ERR("could not load the TM-functions - disable DS ping\n");
488
-			return -1;
489
-		}
490
-		/*****************************************************
491
-		 * Register the PING-Timer
492
-		 *****************************************************/
493
-		register_timer(ds_check_timer, NULL, ds_ping_interval);
494
-	}
495
-
496
-	return 0;
497
-}
498
-
499
-/*! \brief
500
- * Initialize children
501
- */
502
-static int child_init(int rank)
503
-{
504
-	srand((11+rank)*getpid()*7);
505
-
506
-	return 0;
507
-}
508
-
509
-static int mi_child_init(void)
510
-{
511
-
512
-	if(ds_db_url.s)
513
-		return ds_connect_db();
514
-	return 0;
515
-
516
-}
517
-
518
-/*! \brief
519
- * destroy function
520
- */
521
-static void destroy(void)
522
-{
523
-	ds_destroy_list();
524
-	if(ds_db_url.s)
525
-		ds_disconnect_db();
526
-	ds_hash_load_destroy();
527
-	if(ds_ping_reply_codes)
528
-		shm_free(ds_ping_reply_codes);	
529
-
530
-}
531
-
532
-/**
533
- *
534
- */
535
-static int w_ds_select_dst(struct sip_msg* msg, char* set, char* alg)
536
-{
537
-	int a, s;
538
-
539
-	if(msg==NULL)
540
-		return -1;
541
-	if(fixup_get_ivalue(msg, (gparam_p)set, &s)!=0)
542
-	{
543
-		LM_ERR("no dst set value\n");
544
-		return -1;
545
-	}
546
-	if(fixup_get_ivalue(msg, (gparam_p)alg, &a)!=0)
547
-	{
548
-		LM_ERR("no alg value\n");
549
-		return -1;
550
-	}
551
-
552
-	return ds_select_dst(msg, s, a, 0 /*set dst uri*/);
553
-}
554
-
555
-/**
556
- *
557
- */
558
-static int w_ds_select_domain(struct sip_msg* msg, char* set, char* alg)
559
-{
560
-	int a, s;
561
-	if(msg==NULL)
562
-		return -1;
563
-
564
-	if(fixup_get_ivalue(msg, (gparam_p)set, &s)!=0)
565
-	{
566
-		LM_ERR("no dst set value\n");
567
-		return -1;
568
-	}
569
-	if(fixup_get_ivalue(msg, (gparam_p)alg, &a)!=0)
570
-	{
571
-		LM_ERR("no alg value\n");
572
-		return -1;
573
-	}
574
-
575
-	return ds_select_dst(msg, s, a, 1/*set host port*/);
576
-}
577
-
578
-/**
579
- *
580
- */
581
-static int w_ds_next_dst(struct sip_msg *msg, char *str1, char *str2)
582
-{
583
-	return ds_next_dst(msg, 0/*set dst uri*/);
584
-}
585
-
586
-/**
587
- *
588
- */
589
-static int w_ds_next_domain(struct sip_msg *msg, char *str1, char *str2)
590
-{
591
-	return ds_next_dst(msg, 1/*set host port*/);
592
-}
593
-
594
-/**
595
- *
596
- */
597
-static int w_ds_mark_dst0(struct sip_msg *msg, char *str1, char *str2)
598
-{
599
-	int state;
600
-
601
-	state = DS_INACTIVE_DST;
602
-	if (ds_probing_mode==DS_PROBE_ALL)
603
-		state |= DS_PROBING_DST;
604
-
605
-	return ds_mark_dst(msg, state);
606
-}
607
-
608
-/**
609
- *
610
- */
611
-static int w_ds_mark_dst1(struct sip_msg *msg, char *str1, char *str2)
612
-{
613
-	int state;
614
-	int len;
615
-
616
-	if(str1==NULL)
617
-		return w_ds_mark_dst0(msg, NULL, NULL);
618
-
619
-	len = strlen(str1);
620
-	state = 0;
621
-	if (len>1 && (str1[1]=='p' || str1[1]=='P'))
622
-		state |= DS_PROBING_DST;
623
-
624
-	if(str1[0]=='i' || str1[0]=='I')
625
-		state |= DS_INACTIVE_DST;
626
-	else if(str1[0]=='t' || str1[0]=='T')
627
-		state |= DS_TRYING_DST;
628
-	else if(str1[0]=='d' || str1[0]=='D')
629
-		state = DS_DISABLED_DST;
630
-	else if(str1[0]=='p' || str1[0]=='P')
631
-		state =  DS_INACTIVE_DST|DS_PROBING_DST;
632
-	return ds_mark_dst(msg, state);
633
-}
634
-
635
-
636
-/**
637
- *
638
- */
639
-static int w_ds_load_unset(struct sip_msg *msg, char *str1, char *str2)
640
-{
641
-	if(ds_load_unset(msg)<0)
642
-		return -1;
643
-	return 1;
644
-}
645
-
646
-/**
647
- *
648
- */
649
-static int w_ds_load_update(struct sip_msg *msg, char *str1, char *str2)
650
-{
651
-	if(ds_load_update(msg)<0)
652
-		return -1;
653
-	return 1;
654
-}
655
-
656
-/**
657
- *
658
- */
659
-static int ds_warn_fixup(void** param, int param_no)
660
-{
661
-	if(!dst_avp_param.s || !grp_avp_param.s || !cnt_avp_param.s)
662
-	{
663
-		LM_ERR("failover functions used, but AVPs paraamters required"
664
-				" are NULL -- feature disabled\n");
665
-	}
666
-	return 0;
667
-}
668
-
669
-/************************** MI STUFF ************************/
670
-
671
-static struct mi_root* ds_mi_set(struct mi_root* cmd_tree, void* param)
672
-{
673
-	str sp;
674
-	int ret;
675
-	unsigned int group, state;
676
-	struct mi_node* node;
677
-
678
-	node = cmd_tree->node.kids;
679
-	if(node == NULL)
680
-		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
681
-	sp = node->value;
682
-	if(sp.len<=0 || !sp.s)
683
-	{
684
-		LM_ERR("bad state value\n");
685
-		return init_mi_tree(500, "bad state value", 15);
686
-	}
687
-
688
-	state = 0;
689
-	if(sp.s[0]=='0' || sp.s[0]=='I' || sp.s[0]=='i') {
690
-		/* set inactive */
691
-		state |= DS_INACTIVE_DST;
692
-		if((sp.len>1) && (sp.s[1]=='P' || sp.s[1]=='p'))
693
-			state |= DS_PROBING_DST;
694
-	} else if(sp.s[0]=='1' || sp.s[0]=='A' || sp.s[0]=='a') {
695
-		/* set active */
696
-		if((sp.len>1) && (sp.s[1]=='P' || sp.s[1]=='p'))
697
-			state |= DS_PROBING_DST;
698
-	} else if(sp.s[0]=='2' || sp.s[0]=='D' || sp.s[0]=='d') {
699
-		/* set disabled */
700
-		state |= DS_DISABLED_DST;
701
-	} else if(sp.s[0]=='3' || sp.s[0]=='T' || sp.s[0]=='t') {
702
-		/* set trying */
703
-		state |= DS_TRYING_DST;
704
-		if((sp.len>1) && (sp.s[1]=='P' || sp.s[1]=='p'))
705
-			state |= DS_PROBING_DST;
706
-	} else {
707
-		LM_ERR("unknow state value\n");
708
-		return init_mi_tree(500, "unknown state value", 19);
709
-	}
710
-	node = node->next;
711
-	if(node == NULL)
712
-		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
713
-	sp = node->value;
714
-	if(sp.s == NULL)
715
-	{
716
-		return init_mi_tree(500, "group not found", 15);
717
-	}
718
-
719
-	if(str2int(&sp, &group))
720
-	{
721
-		LM_ERR("bad group value\n");
722
-		return init_mi_tree( 500, "bad group value", 16);
723
-	}
724
-
725
-	node= node->next;
726
-	if(node == NULL)
727
-		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
728
-
729
-	sp = node->value;
730
-	if(sp.s == NULL)
731
-	{
732
-		return init_mi_tree(500,"address not found", 18 );
733
-	}
734
-
735
-	ret = ds_reinit_state(group, &sp, state);
736
-
737
-	if(ret!=0)
738
-	{
739
-		return init_mi_tree(404, "destination not found", 21);
740
-	}
741
-
742
-	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
743
-}
744
-
745
-
746
-
747
-
748
-static struct mi_root* ds_mi_list(struct mi_root* cmd_tree, void* param)
749
-{
750
-	struct mi_root* rpl_tree;
751
-
752
-	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
753
-	if (rpl_tree==NULL)
754
-		return 0;
755
-
756
-	if( ds_print_mi_list(&rpl_tree->node)< 0 )
757
-	{
758
-		LM_ERR("failed to add node\n");
759
-		free_mi_tree(rpl_tree);
760
-		return 0;
761
-	}
762
-
763
-	return rpl_tree;
764
-}
765
-
766
-#define MI_ERR_RELOAD 			"ERROR Reloading data"
767
-#define MI_ERR_RELOAD_LEN 		(sizeof(MI_ERR_RELOAD)-1)
768
-#define MI_NOT_SUPPORTED		"DB mode not configured"
769
-#define MI_NOT_SUPPORTED_LEN 	(sizeof(MI_NOT_SUPPORTED)-1)
770
-#define MI_ERR_DSLOAD			"No reload support for call load dispatching"
771
-#define MI_ERR_DSLOAD_LEN		(sizeof(MI_ERR_DSLOAD)-1)
772
-
773
-static struct mi_root* ds_mi_reload(struct mi_root* cmd_tree, void* param)
774
-{
775
-	if(!ds_db_url.s) {
776
-		if (ds_load_list(dslistfile)!=0)
777
-			return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
778
-	} else {
779
-		if(ds_load_db()<0)
780
-			return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
781
-	}
782
-	return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
783
-}
784
-
785
-
786
-static int w_ds_is_from_list0(struct sip_msg *msg, char *str1, char *str2)
787
-{
788
-	return ds_is_from_list(msg, -1);
789
-}
790
-
791
-
792
-static int w_ds_is_from_list1(struct sip_msg *msg, char *set, char *str2)
793
-{
794
-	return ds_is_from_list(msg, (int)(long)set);
795
-}
796
-
797
-static int ds_parse_reply_codes() {
798
-	param_t* params_list = NULL;
799
-	param_t *pit=NULL;
800
-	int list_size = 0;
801
-	int i = 0;
802
-	int pos = 0;
803
-	int code = 0;
804
-	str input = {0, 0};
805
-	int* ds_ping_reply_codes_new = NULL;
806
-	int* ds_ping_reply_codes_old = NULL;
807
-
808
-	/* Validate String: */
809
-	if (cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).s == 0 
810
-			|| cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).len<=0)
811
-		return 0;
812
-
813
-	/* parse_params will modify the string pointer of .s, so we need to make a copy. */
814
-	input.s = cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).s;
815
-	input.len = cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str).len;
816
-
817
-	/* Parse the parameters: */
818
-	if (parse_params(&input, CLASS_ANY, 0, &params_list)<0)
819
-		return -1;
820
-
821
-	/* Get the number of entries in the list */
822
-	for (pit = params_list; pit; pit=pit->next)
823
-	{
824
-		if (pit->name.len==4
825
-				&& strncasecmp(pit->name.s, "code", 4)==0) {
826
-			str2sint(&pit->body, &code);
827
-			if ((code >= 100) && (code < 700))
828
-				list_size += 1;
829
-		} else if (pit->name.len==5
830
-				&& strncasecmp(pit->name.s, "class", 5)==0) {
831
-			str2sint(&pit->body, &code);
832
-			if ((code >= 1) && (code < 7))
833
-				list_size += 100;
834
-		}
835
-	}
836
-	LM_DBG("Should be %d Destinations.\n", list_size);
837
-
838
-	if (list_size > 0) {
839
-		/* Allocate Memory for the new list: */
840
-		ds_ping_reply_codes_new = (int*)shm_malloc(list_size * sizeof(int));
841
-		if(ds_ping_reply_codes_new== NULL)
842
-		{
843
-			free_params(params_list);
844
-			LM_ERR("no more memory\n");
845
-			return -1;
846
-		}
847
-
848
-		/* Now create the list of valid reply-codes: */
849
-		for (pit = params_list; pit; pit=pit->next)
850
-		{
851
-			if (pit->name.len==4
852
-					&& strncasecmp(pit->name.s, "code", 4)==0) {
853
-				str2sint(&pit->body, &code);
854
-				if ((code >= 100) && (code < 700))
855
-					ds_ping_reply_codes_new[pos++] = code;
856
-			} else if (pit->name.len==5
857
-					&& strncasecmp(pit->name.s, "class", 5)==0) {
858
-				str2sint(&pit->body, &code);
859
-				if ((code >= 1) && (code < 7)) {
860
-					/* Add every code from this class, e.g. 100 to 199 */
861
-					for (i = (code*100); i <= ((code*100)+99); i++) 
862
-						ds_ping_reply_codes_new[pos++] = i;
863
-				}
864
-			}
865
-		}
866
-	} else {
867
-		ds_ping_reply_codes_new = 0;
868
-	}
869
-	free_params(params_list);
870
-
871
-	/* More reply-codes? Change Pointer and then set number of codes. */
872
-	if (list_size > *ds_ping_reply_codes_cnt) {
873
-		// Copy Pointer
874
-		ds_ping_reply_codes_old = *ds_ping_reply_codes;
875
-		*ds_ping_reply_codes = ds_ping_reply_codes_new;
876
-		// Done: Set new Number of entries:
877
-		*ds_ping_reply_codes_cnt = list_size;
878
-		// Free the old memory area:
879
-		if(ds_ping_reply_codes_old)
880
-			shm_free(ds_ping_reply_codes_old);	
881
-		/* Less or equal? Set the number of codes first. */
882
-	} else {
883
-		// Done:
884
-		*ds_ping_reply_codes_cnt = list_size;
885
-		// Copy Pointer
886
-		ds_ping_reply_codes_old = *ds_ping_reply_codes;
887
-		*ds_ping_reply_codes = ds_ping_reply_codes_new;
888
-		// Free the old memory area:
889
-		if(ds_ping_reply_codes_old)
890
-			shm_free(ds_ping_reply_codes_old);	
891
-	}
892
-	/* Print the list as INFO: */
893
-	for (i =0; i< *ds_ping_reply_codes_cnt; i++)
894
-	{
895
-		LM_DBG("Dispatcher: Now accepting Reply-Code %d (%d/%d) as valid\n",
896
-				(*ds_ping_reply_codes)[i], (i+1), *ds_ping_reply_codes_cnt);
897
-	}
898
-	return 0;
899
-}
900
-
901
-int ds_ping_check_rplcode(int code)
902
-{
903
-	int i;