Browse code

modules/cfgt: trace config and save to file

Victor Seva authored on 24/06/2015 20:19:24
Showing 9 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+#
1
+# cfgt module makefile
2
+#
3
+# WARNING: do not run this directly, it should be run by the master Makefile
4
+
5
+include ../../Makefile.defs
6
+auto_gen=
7
+NAME=cfgt.so
8
+LIBS=
9
+
10
+DEFS+=-DKAMAILIO_MOD_INTERFACE
11
+
12
+SERLIBPATH=../../lib
13
+SER_LIBS+=$(SERLIBPATH)/kcore/kcore
14
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
15
+
16
+include ../../Makefile.modules
0 17
new file mode 100644
... ...
@@ -0,0 +1,45 @@
0
+/*
1
+ * Copyright (C) 2015 Victor Seva (sipwise.com)
2
+ *
3
+ * This file is part of Kamailio, a free SIP server.
4
+ *
5
+ * Kamailio is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation; either version 2 of the License, or
8
+ * (at your option) any later version
9
+ *
10
+ * Kamailio is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
+ *
19
+ *
20
+ */
21
+#include "cfgt_mod.h"
22
+#include "cfgt.h"
23
+#include "cfgt_int.h"
24
+
25
+/*!
26
+ * \brief cfgt module API export bind function
27
+ * \param api cfgt API
28
+ * \return 0 on success, -1 on failure
29
+ */
30
+int bind_cfgt(cfgt_api_t* api)
31
+{
32
+	if (!api) {
33
+		LM_ERR("invalid parameter value\n");
34
+		return -1;
35
+	}
36
+	if (init_flag==0) {
37
+		LM_ERR("configuration error - trying to bind to cfgt module"
38
+				" before being initialized\n");
39
+		return -1;
40
+	}
41
+
42
+	api->cfgt_process_route   = cfgt_process_route;
43
+	return 0;
44
+}
0 45
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+/*
1
+ * Copyright (C) 2015 Victor Seva (sipwise.com)
2
+ *
3
+ * This file is part of Kamailio, a free SIP server.
4
+ *
5
+ * Kamailio is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation; either version 2 of the License, or
8
+ * (at your option) any later version
9
+ *
10
+ * Kamailio is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
+ *
19
+ *
20
+ */
21
+
22
+#ifndef _CFGT_BIND_H
23
+#define _CFGT_BIND_H
24
+
25
+#include "../../sr_module.h"
26
+
27
+/* export not usable from scripts */
28
+#define NO_SCRIPT	-1
29
+
30
+typedef int (*cfgt_process_route_f)(struct sip_msg *msg, struct action *a);
31
+
32
+typedef struct cfgt_api {
33
+	cfgt_process_route_f cfgt_process_route;
34
+} cfgt_api_t;
35
+
36
+/*! cfgt API export bind function */
37
+typedef int (*bind_cfgt_t)(cfgt_api_t* api);
38
+
39
+#endif
0 40
new file mode 100644
... ...
@@ -0,0 +1,797 @@
0
+/**
1
+ *
2
+ * Copyright (C) 2015 Victor Seva (sipwise.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * This file is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ *
20
+ */
21
+#include <stdio.h>
22
+#include <sys/stat.h>
23
+
24
+#include "../../events.h"
25
+#include "../../lib/kcore/cmpapi.h"
26
+#include "../../pvar.h"
27
+#include "../../rpc.h"
28
+#include "../../rpc_lookup.h"
29
+
30
+#include "cfgt_int.h"
31
+#include "cfgt_json.h"
32
+
33
+static str _cfgt_route_prefix[] = {
34
+	str_init("start|"),
35
+	str_init("exit|"),
36
+	str_init("drop|"),
37
+	str_init("return|"),
38
+	{0, 0}
39
+};
40
+cfgt_node_p _cfgt_node = NULL;
41
+cfgt_hash_p _cfgt_uuid = NULL;
42
+str cfgt_hdr_prefix = {"NGCP%", 5};
43
+str cfgt_basedir = {"/tmp", 4};
44
+int cfgt_mask = CFGT_DP_ALL;
45
+
46
+static int shm_str_hash_alloc(struct str_hash_table *ht, int size)
47
+{
48
+	ht->table = shm_malloc(sizeof(struct str_hash_head) * size);
49
+
50
+	if (!ht->table)
51
+		return -1;
52
+
53
+	ht->size = size;
54
+	return 0;
55
+}
56
+
57
+static int _cfgt_init_hashtable(struct str_hash_table *ht)
58
+{
59
+	if (shm_str_hash_alloc(ht, CFGT_HASH_SIZE) != 0)
60
+	{
61
+		LM_ERR("Error allocating shared memory hashtable\n");
62
+		return -1;
63
+	}
64
+
65
+	str_hash_init(ht);
66
+
67
+	return 0;
68
+}
69
+
70
+int _cfgt_pv_parse(str *param, pv_elem_p *elem)
71
+{
72
+	if (param->s && param->len > 0)
73
+	{
74
+		if (pv_parse_format(param, elem)<0)
75
+		{
76
+			LM_ERR("malformed or non AVP %.*s AVP definition\n",
77
+					param->len, param->s);
78
+			return -1;
79
+		}
80
+	}
81
+	return 0;
82
+}
83
+
84
+void _cfgt_remove_uuid(const str *uuid)
85
+{
86
+	struct str_hash_head *head;
87
+	struct str_hash_entry *entry, *back;
88
+	int i;
89
+
90
+	if(_cfgt_uuid==NULL) return;
91
+	if(uuid)
92
+	{
93
+		lock_get(&_cfgt_uuid->lock);
94
+		entry = str_hash_get(&_cfgt_uuid->hash, uuid->s, uuid->len);
95
+		if(entry)
96
+		{
97
+			str_hash_del(entry);
98
+			shm_free(entry->key.s);
99
+			shm_free(entry);
100
+			LM_DBG("uuid[%.*s] removed from hash\n", uuid->len, uuid->s);
101
+		}
102
+		else LM_DBG("uuid[%.*s] not found in hash\n", uuid->len, uuid->s);
103
+		lock_release(&_cfgt_uuid->lock);
104
+	}
105
+	else
106
+	{
107
+		lock_get(&_cfgt_uuid->lock);
108
+		for(i=0; i<CFGT_HASH_SIZE; i++)
109
+		{
110
+			head = _cfgt_uuid->hash.table+i;
111
+			clist_foreach_safe(head, entry, back, next)
112
+			{
113
+				LM_DBG("uuid[%.*s] removed from hash\n",
114
+					entry->key.len, entry->key.s);
115
+				str_hash_del(entry);
116
+				shm_free(entry->key.s);
117
+				shm_free(entry);
118
+			}
119
+			lock_release(&_cfgt_uuid->lock);
120
+		}
121
+		LM_DBG("remove all uuids. done\n");
122
+	}
123
+}
124
+
125
+int _cfgt_get_uuid_id(cfgt_node_p node)
126
+{
127
+	struct str_hash_entry *entry;
128
+
129
+	if(_cfgt_uuid==NULL || node==NULL || node->uuid.len == 0) return -1;
130
+	lock_get(&_cfgt_uuid->lock);
131
+	entry = str_hash_get(&_cfgt_uuid->hash, node->uuid.s, node->uuid.len);
132
+	if(entry)
133
+	{
134
+		entry->u.n = entry->u.n + 1;
135
+		node->msgid = entry->u.n;
136
+	}
137
+	else
138
+	{
139
+		entry = shm_malloc(sizeof(struct str_hash_entry));
140
+		if(entry==NULL)
141
+		{
142
+			lock_release(&_cfgt_uuid->lock);
143
+			LM_ERR("No shared memory left\n");
144
+			return -1;
145
+		}
146
+		if (shm_str_dup(&entry->key, &node->uuid) != 0)
147
+		{
148
+			lock_release(&_cfgt_uuid->lock);
149
+			shm_free(entry);
150
+			LM_ERR("No shared memory left\n");
151
+			return -1;
152
+		}
153
+		entry->u.n = 1;
154
+		node->msgid = 1;
155
+		LM_DBG("Add new entry[%.*s]\n", node->uuid.len, node->uuid.s);
156
+		str_hash_add(&_cfgt_uuid->hash, entry);
157
+	}
158
+	lock_release(&_cfgt_uuid->lock);
159
+	LM_DBG("msgid:[%d]\n", node->msgid);
160
+	return 1;
161
+}
162
+
163
+int _cfgt_get_hdr_helper(struct sip_msg *msg, str *res, int mode)
164
+{
165
+	struct hdr_field *hf;
166
+	char *delimiter, *end;
167
+	str tmp = STR_NULL;
168
+
169
+	if(msg==NULL || (mode==0 && res==NULL))
170
+		return -1;
171
+
172
+	/* we need to be sure we have parsed all headers */
173
+	if(parse_headers(msg, HDR_EOH_F, 0)<0)
174
+	{
175
+		LM_ERR("error parsing headers\n");
176
+		return -1;
177
+	}
178
+
179
+	hf = msg->callid;
180
+	if(!hf) return 1;
181
+
182
+	if(strncmp(hf->body.s, cfgt_hdr_prefix.s, cfgt_hdr_prefix.len)==0)
183
+	{
184
+		tmp.s = hf->body.s+cfgt_hdr_prefix.len;
185
+		delimiter = tmp.s-1;
186
+		LM_DBG("Prefix detected. delimiter[%c]\n", *delimiter);
187
+		if(mode==0)
188
+		{
189
+			end = strchr(tmp.s, *delimiter);
190
+			if(end)
191
+			{
192
+				tmp.len = end-tmp.s;
193
+				if(pkg_str_dup(res, &tmp)<0)
194
+				{
195
+					LM_ERR("error copying header\n");
196
+					return -1;
197
+				}
198
+				LM_DBG("cfgtest uuid:[%.*s]\n", res->len, res->s);
199
+				return 0;
200
+			}
201
+		}
202
+		else
203
+		{
204
+			tmp.len = res->len;
205
+			LM_DBG("tmp[%.*s] res[%.*s]\n", tmp.len, tmp.s, res->len, res->s);
206
+			return STR_EQ(tmp, *res);
207
+		}
208
+	}
209
+	return 1; /* not found */
210
+}
211
+
212
+int _cfgt_get_hdr(struct sip_msg *msg, str *res)
213
+{
214
+	return _cfgt_get_hdr_helper(msg, res, 0);
215
+}
216
+
217
+int _cfgt_cmp_hdr(struct sip_msg *msg, str *res)
218
+{
219
+	return _cfgt_get_hdr_helper(msg, res, 1);
220
+}
221
+
222
+cfgt_node_p cfgt_create_node(struct sip_msg *msg)
223
+{
224
+	cfgt_node_p node;
225
+
226
+	node = (cfgt_node_p) pkg_malloc(sizeof(cfgt_node_t));
227
+	if(node==NULL)
228
+	{
229
+		LM_ERR("cannot allocate cfgtest msgnode\n");
230
+		return node;
231
+	}
232
+	memset(node, 0, sizeof(cfgt_node_t));
233
+	srjson_InitDoc(&node->jdoc, NULL);
234
+	if (msg)
235
+	{
236
+		node->msgid = msg->id;
237
+		LM_DBG("msgid:%d\n", node->msgid);
238
+		if(_cfgt_get_hdr(msg, &node->uuid)!=0 || &node->uuid.len==0)
239
+		{
240
+			LM_ERR("cannot get value of cfgtest uuid header!!\n");
241
+			goto error;
242
+		}
243
+	}
244
+	node->jdoc.root = srjson_CreateObject(&node->jdoc);
245
+	if(node->jdoc.root==NULL)
246
+	{
247
+		LM_ERR("cannot create json root\n");
248
+		goto error;
249
+	}
250
+	node->flow = srjson_CreateArray(&node->jdoc);
251
+	if(node->flow==NULL)
252
+	{
253
+		LM_ERR("cannot create json object\n");
254
+		goto error;
255
+	}
256
+	srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "flow\0", node->flow);
257
+	node->in = srjson_CreateArray(&node->jdoc);
258
+	if(node->in==NULL)
259
+	{
260
+		LM_ERR("cannot create json object\n");
261
+		goto error;
262
+	}
263
+	srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "sip_in\0", node->in);
264
+	node->out = srjson_CreateArray(&node->jdoc);
265
+	if(node->out==NULL)
266
+	{
267
+		LM_ERR("cannot create json object\n");
268
+		goto error;
269
+	}
270
+	srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "sip_out\0", node->out);
271
+	LM_DBG("node created\n");
272
+	return node;
273
+
274
+error:
275
+	srjson_DestroyDoc(&node->jdoc);
276
+	pkg_free(node);
277
+	return NULL;
278
+}
279
+
280
+void _cfgt_remove_node(cfgt_node_p node)
281
+{
282
+	if(!node) return;
283
+	srjson_DestroyDoc(&node->jdoc);
284
+	if(node->uuid.s) pkg_free(node->uuid.s);
285
+	while(node->flow_head)
286
+	{
287
+		node->route = node->flow_head;
288
+		node->flow_head = node->route->next;
289
+		pkg_free(node->route);
290
+		node->route = NULL;
291
+	}
292
+	pkg_free(node);
293
+}
294
+
295
+int _cfgt_get_filename(int msgid, str uuid, str *dest, int *dir)
296
+{
297
+	int i, lid;
298
+	char buff_id[INT2STR_MAX_LEN];
299
+	char *sid;
300
+	if(dest==NULL || uuid.len == 0) return -1;
301
+
302
+	dest->len = cfgt_basedir.len + uuid.len;
303
+	if(cfgt_basedir.s[cfgt_basedir.len-1]!='/')
304
+		dest->len = dest->len + 1;
305
+	sid = sint2strbuf(msgid, buff_id, INT2STR_MAX_LEN, &lid);
306
+	dest->len += lid + 6;
307
+	dest->s = (char *) pkg_malloc((dest->len*sizeof(char)+1));
308
+	if(dest->s==NULL)
309
+	{
310
+		LM_ERR("no more memory.\n");
311
+		return -1;
312
+	}
313
+	strncpy(dest->s, cfgt_basedir.s, cfgt_basedir.len);
314
+	i = cfgt_basedir.len;
315
+	if(cfgt_basedir.s[cfgt_basedir.len-1]!='/')
316
+	{
317
+		strncpy(dest->s+i, "/", 1);
318
+		i = i + 1;
319
+	}
320
+	strncpy(dest->s+i, uuid.s, uuid.len);
321
+	i = i + uuid.len; (*dir) = i;
322
+	strncpy(dest->s+i, "\0", 1);
323
+	i = i + 1;
324
+	strncpy(dest->s+i, sid, lid);
325
+	i = i + lid;
326
+	strncpy(dest->s+i, ".json\0", 6);
327
+	return 0;
328
+}
329
+
330
+int _cfgt_node2json(cfgt_node_p node)
331
+{
332
+       srjson_t *jobj;
333
+
334
+       if(!node) return -1;
335
+       jobj = srjson_CreateStr(&node->jdoc, node->uuid.s, node->uuid.len);
336
+       if(jobj==NULL)
337
+       {
338
+               LM_ERR("cannot create json object\n");
339
+               return -1;
340
+       }
341
+       srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "uuid\0", jobj);
342
+
343
+       jobj = srjson_CreateNumber(&node->jdoc, (double)node->msgid);
344
+       if(jobj==NULL)
345
+       {
346
+               LM_ERR("cannot create json object\n");
347
+               return -1;
348
+       }
349
+       srjson_AddItemToObject(&node->jdoc, node->jdoc.root, "msgid\0", jobj);
350
+       return 0;
351
+}
352
+
353
+void cfgt_save_node(cfgt_node_p node)
354
+{
355
+	FILE *fp;
356
+	str dest = STR_NULL;
357
+	int dir = 0;
358
+	if(_cfgt_get_filename(node->msgid, node->uuid, &dest, &dir)<0)
359
+	{
360
+		LM_ERR("can't build filename\n");
361
+		return;
362
+	}
363
+	LM_DBG("dir [%s]\n", dest.s);
364
+	mkdir(dest.s, S_IRWXO|S_IXGRP|S_IRWXU);
365
+	dest.s[dir] = '/';
366
+	fp = fopen(dest.s, "w");
367
+	LM_DBG("file [%s]\n", dest.s);
368
+	if(fp) {
369
+		pkg_free(dest.s);
370
+		dest.s = srjson_Print(&node->jdoc, node->jdoc.root);
371
+	    if(dest.s==NULL)
372
+        {
373
+           LM_ERR("Cannot get the json string\n");
374
+           fclose(fp);
375
+           return;
376
+        }
377
+        if(fputs(dest.s, fp)<0){
378
+        	LM_ERR("failed writing to file\n");
379
+        }
380
+        fclose(fp);
381
+        node->jdoc.free_fn(dest.s);
382
+	}
383
+	else {
384
+		LM_ERR("Can't open file [%s] to write\n", dest.s);
385
+		pkg_free(dest.s);
386
+	}
387
+}
388
+
389
+void _cfgt_print_node(cfgt_node_p node, int json)
390
+{
391
+	char *buf = NULL;
392
+	cfgt_str_list_p route;
393
+
394
+	if(!node) return;
395
+	if(node->flow_head)
396
+	{
397
+		route = node->flow_head;
398
+		while(route)
399
+		{
400
+			if(route == node->route)
401
+				LM_DBG("[--[%.*s][%d]--]\n",
402
+					route->s.len, route->s.s, route->type);
403
+			else LM_DBG("[%.*s][%d]\n",
404
+					route->s.len, route->s.s, route->type);
405
+			route = route->next;
406
+		}
407
+	}
408
+	else LM_DBG("flow:empty\n");
409
+	if(json) {
410
+		buf = srjson_PrintUnformatted(&node->jdoc, node->jdoc.root);
411
+		if(buf==NULL)
412
+		{
413
+			LM_ERR("Cannot get the json string\n");
414
+			return;
415
+		}
416
+		LM_DBG("node[%p]: id:[%d] uuid:[%.*s] info:[%s]\n",
417
+			node, node->msgid, node->uuid.len, node->uuid.s, buf);
418
+		node->jdoc.free_fn(buf);
419
+	}
420
+}
421
+
422
+int _cfgt_set_dump(struct sip_msg *msg, cfgt_node_p node, str *flow)
423
+{
424
+	srjson_t *f, *vars;
425
+
426
+	if(node==NULL || flow == NULL) return -1;
427
+	vars = srjson_CreateObject(&node->jdoc);
428
+	if(vars==NULL)
429
+	{
430
+		LM_ERR("cannot create json object\n");
431
+		return -1;
432
+	}
433
+	if(cfgt_get_json(msg, 30, &node->jdoc, vars)<0)
434
+	{
435
+		LM_ERR("cannot get var info\n");
436
+		return -1;
437
+	}
438
+	f = srjson_CreateObject(&node->jdoc);
439
+	if(f==NULL)
440
+	{
441
+		LM_ERR("cannot create json object\n");
442
+		srjson_Delete(&node->jdoc, vars);
443
+		return -1;
444
+	}
445
+	srjson_AddStrItemToObject(&node->jdoc, f,
446
+		flow->s, flow->len, vars);
447
+	srjson_AddItemToArray(&node->jdoc, node->flow, f);
448
+	LM_DBG("node[%.*s] flow created\n", flow->len, flow->s);
449
+	return 0;
450
+}
451
+
452
+void _cfgt_set_type(cfgt_str_list_p route, struct action *a)
453
+{
454
+	switch(a->type)
455
+	{
456
+		case DROP_T:
457
+			if(a->val[1].u.number&DROP_R_F) {
458
+				route->type = CFGT_DROP_D;
459
+				LM_DBG("set[%.*s]->CFGT_DROP_D\n", route->s.len, route->s.s);
460
+			}
461
+			if(a->val[1].u.number&RETURN_R_F){
462
+				route->type = CFGT_DROP_R;
463
+				LM_DBG("set[%.*s]->CFGT_DROP_R\n", route->s.len, route->s.s);
464
+			}
465
+			else {
466
+				route->type = CFGT_DROP_E;
467
+				LM_DBG("set[%.*s]->CFGT_DROP_E\n", route->s.len, route->s.s);
468
+			}
469
+			break;
470
+		case ROUTE_T:
471
+			route->type = CFGT_ROUTE;
472
+			LM_DBG("set[%.*s]->CFGT_ROUTE\n", route->s.len, route->s.s);
473
+			break;
474
+		default:
475
+			if(route->type!=CFGT_DROP_E)
476
+			{
477
+				route->type = CFGT_DROP_R;
478
+				LM_DBG("[%.*s] no relevant action: CFGT_DROP_R[%d]\n",
479
+					route->s.len, route->s.s, a->type);
480
+			}
481
+			else
482
+			{
483
+				LM_DBG("[%.*s] already set to CFGT_DROP_E[%d]\n",
484
+					route->s.len, route->s.s, a->type);
485
+			}
486
+			break;
487
+	}
488
+}
489
+
490
+int _cfgt_add_routename(cfgt_node_p node, struct action *a,
491
+		str *routename)
492
+{
493
+	cfgt_str_list_p route;
494
+	int ret = 0;
495
+
496
+	if(!node->route) /* initial */
497
+	{
498
+		node->route = pkg_malloc(sizeof(cfgt_str_list_t));
499
+		if(!node->route)
500
+		{
501
+			LM_ERR("No more pkg mem\n");
502
+			return -1;
503
+		}
504
+		memset(node->route, 0, sizeof(cfgt_str_list_t));
505
+		node->flow_head = node->route;
506
+		node->route->type = CFGT_ROUTE;
507
+		ret = 1;
508
+	}
509
+	else
510
+	{
511
+		LM_DBG("actual routename:[%.*s][%d]\n", node->route->s.len,
512
+			node->route->s.s, node->route->type);
513
+		if(node->route->prev)
514
+			LM_DBG("prev routename:[%.*s][%d]\n", node->route->prev->s.len,
515
+				node->route->prev->s.s,	node->route->prev->type);
516
+		if(node->route->next)
517
+			LM_DBG("next routename:[%.*s][%d]\n", node->route->next->s.len,
518
+				node->route->next->s.s,	node->route->next->type);
519
+		if(STR_EQ(*routename, node->route->s))
520
+		{
521
+			LM_DBG("same route\n");
522
+			_cfgt_set_type(node->route, a);
523
+			return 2;
524
+		}
525
+		else if(node->route->prev &&
526
+				STR_EQ(*routename, node->route->prev->s))
527
+		{
528
+			LM_DBG("back to route[%.*s]\n", node->route->prev->s.len,
529
+				node->route->prev->s.s);
530
+			_cfgt_set_type(node->route->prev, a);
531
+			return 3;
532
+		}
533
+		route = pkg_malloc(sizeof(cfgt_str_list_t));
534
+		if(!route)
535
+		{
536
+			LM_ERR("No more pkg mem\n");
537
+			return -1;
538
+		}
539
+		memset(route, 0, sizeof(cfgt_str_list_t));
540
+		route->prev = node->route;
541
+		node->route->next = route;
542
+		node->route = route;
543
+		_cfgt_set_type(node->route, a);
544
+	}
545
+	node->route->s.s = routename->s;
546
+	node->route->s.len = routename->len;
547
+	LM_DBG("add[%d] route:[%.*s]\n", ret, node->route->s.len, node->route->s.s);
548
+	_cfgt_print_node(node, 0);
549
+	return ret;
550
+}
551
+
552
+void _cfgt_del_routename(cfgt_node_p node)
553
+{
554
+	if(node->route->next!=NULL) {
555
+		LM_ERR("wtf!! route->next[%p] not null!!\n", node->route->next);
556
+		_cfgt_print_node(node, 0);
557
+	}
558
+	LM_DBG("del route[%.*s]\n", node->route->s.len, node->route->s.s);
559
+	node->route = node->route->prev;
560
+	pkg_free(node->route->next);
561
+	node->route->next = NULL;
562
+}
563
+/* dest has to be freed */
564
+int _cfgt_node_get_flowname(cfgt_str_list_p route, int *indx, str *dest)
565
+{
566
+	int i;
567
+	if(route==NULL) return -1;
568
+	LM_DBG("routename:[%.*s][%d]\n", route->s.len, route->s.s,
569
+		route->type);
570
+	if(indx) i = *indx;
571
+	else i = route->type-1;
572
+	if(str_append(&_cfgt_route_prefix[i],
573
+		&route->s, dest)<0)
574
+	{
575
+		LM_ERR("Cannot create route name\n");
576
+		return -1;
577
+	}
578
+	return 0;
579
+}
580
+
581
+int cfgt_process_route(struct sip_msg *msg, struct action *a)
582
+{
583
+	str routename;
584
+	int ret = -1;
585
+	int indx = 0;
586
+	str flowname = STR_NULL;
587
+	if(!_cfgt_node) {
588
+		LM_ERR("node empty\n");
589
+		return -1;
590
+	}
591
+	if (a->rname==NULL) {
592
+		LM_DBG("no routename. type:%d\n", a->type);
593
+		return 0;
594
+	}
595
+	LM_DBG("route from action:[%s]\n", a->rname);
596
+	routename.s = a->rname; routename.len = strlen(a->rname);
597
+	switch(_cfgt_add_routename(_cfgt_node, a, &routename))
598
+	{
599
+		case 2: /* same name */
600
+			return 0;
601
+		case 1: /* initial */
602
+			LM_DBG("Initial route[%.*s]. dump vars\n",
603
+				_cfgt_node->route->s.len, _cfgt_node->route->s.s);
604
+			if(_cfgt_node_get_flowname(_cfgt_node->route, &indx, &flowname)<0)
605
+			{
606
+				LM_ERR("cannot create flowname\n");
607
+				return -1;
608
+			}
609
+			ret = _cfgt_set_dump(msg, _cfgt_node, &flowname);
610
+			break;
611
+		case 0: /* new */
612
+			LM_DBG("Change from[%.*s] route to route[%.*s]. dump vars\n",
613
+				_cfgt_node->route->prev->s.len, _cfgt_node->route->prev->s.s,
614
+				_cfgt_node->route->s.len, _cfgt_node->route->s.s);
615
+			if(_cfgt_node_get_flowname(_cfgt_node->route, &indx, &flowname)<0)
616
+			{
617
+				LM_ERR("cannot create flowname\n");
618
+				return -1;
619
+			}
620
+			ret = _cfgt_set_dump(msg, _cfgt_node, &flowname);
621
+			break;
622
+		case 3: /* back to previous */
623
+			if(_cfgt_node_get_flowname(_cfgt_node->route, 0, &flowname)<0)
624
+			{
625
+				LM_ERR("cannot create flowname\n");
626
+				return -1;
627
+			}
628
+			ret = _cfgt_set_dump(msg, _cfgt_node, &flowname);
629
+			_cfgt_del_routename(_cfgt_node);
630
+			break;
631
+		default:
632
+			return -1;
633
+	}
634
+	if(flowname.s) pkg_free(flowname.s);
635
+	return ret;
636
+}
637
+
638
+/*
639
+TODO:
640
+- parse first line, check if is SIP
641
+- parse for header cfgtest
642
+*/
643
+int cfgt_msgin(void *data)
644
+{
645
+	srjson_t *jobj;
646
+	str *buf = (str *) data;
647
+	if(buf==NULL) return 0;
648
+	if(_cfgt_node) {
649
+		cfgt_save_node(_cfgt_node);
650
+		_cfgt_remove_node(_cfgt_node);
651
+		LM_DBG("node removed\n");
652
+		_cfgt_node = NULL;
653
+	}
654
+	LM_DBG("msg in:{%.*s}\n", buf->len, buf->s);
655
+	_cfgt_node = cfgt_create_node(NULL);
656
+	if(_cfgt_node)
657
+	{
658
+		jobj = srjson_CreateStr(&_cfgt_node->jdoc, buf->s, buf->len);
659
+		if(jobj==NULL)
660
+		{
661
+			LM_ERR("cannot create json object\n");
662
+			return -1;
663
+		}
664
+		srjson_AddItemToArray(&_cfgt_node->jdoc, _cfgt_node->in, jobj);
665
+		return 0;
666
+	}
667
+	LM_ERR("_cfgt_node empty\n");
668
+	return -1;
669
+}
670
+
671
+int cfgt_pre(struct sip_msg *msg, unsigned int flags, void *bar) {
672
+	str unknown = {"unknown", 7};
673
+
674
+	if(_cfgt_node)
675
+	{
676
+		if (_cfgt_node->msgid == 0)
677
+		{
678
+			LM_DBG("new node\n");
679
+			if(_cfgt_get_hdr(msg, &_cfgt_node->uuid)!=0 ||
680
+				_cfgt_node->uuid.len==0)
681
+			{
682
+				LM_ERR("cannot get value of cfgtest uuid header."
683
+					" Using unknown\n");
684
+				pkg_str_dup(&_cfgt_node->uuid, &unknown);
685
+			}
686
+			return _cfgt_get_uuid_id(_cfgt_node);
687
+		}
688
+		else
689
+		{
690
+			LM_DBG("_cfgt_node->uuid:[%.*s]\n", _cfgt_node->uuid.len,
691
+				_cfgt_node->uuid.s);
692
+			if(_cfgt_cmp_hdr(msg, &_cfgt_node->uuid))
693
+			{
694
+				LM_DBG("same uuid\n");
695
+				return 1;
696
+			}
697
+			else {
698
+				LM_DBG("different uuid\n");
699
+			}
700
+		}
701
+	}
702
+	else { LM_ERR("node empty??\n"); }
703
+	_cfgt_node = cfgt_create_node(msg);
704
+	if(_cfgt_node) {
705
+		LM_DBG("node created\n");
706
+		return 1;
707
+	}
708
+	return -1;
709
+}
710
+int cfgt_post(struct sip_msg *msg, unsigned int flags, void *bar) {
711
+	str flowname = STR_NULL;
712
+
713
+	if(_cfgt_node) {
714
+		LM_DBG("dump last flow\n");
715
+		if(_cfgt_node_get_flowname(_cfgt_node->route, 0, &flowname)<0)
716
+			LM_ERR("cannot create flowname\n");
717
+		else _cfgt_set_dump(msg, _cfgt_node, &flowname);
718
+		if(flowname.s) pkg_free(flowname.s);
719
+		cfgt_save_node(_cfgt_node);
720
+	}
721
+	return 1;
722
+}
723
+
724
+int cfgt_msgout(void *data)
725
+{
726
+	srjson_t *jobj;
727
+	str *buf = (str *) data;
728
+	if(buf==NULL) return 0;
729
+	LM_DBG("msg out:{%.*s}\n", buf->len, buf->s);
730
+
731
+	if(_cfgt_node)
732
+	{
733
+		jobj = srjson_CreateStr(&_cfgt_node->jdoc, buf->s, buf->len);
734
+		if(jobj==NULL)
735
+		{
736
+			LM_ERR("cannot create json object\n");
737
+			return -1;
738
+		}
739
+		srjson_AddItemToArray(&_cfgt_node->jdoc, _cfgt_node->out, jobj);
740
+		return 0;
741
+	}
742
+	LM_ERR("node empty\n");
743
+	return -1;
744
+}
745
+
746
+/**
747
+ *
748
+ */
749
+static const char* cfgt_rpc_mask_doc[2] = {
750
+	"Specify module mask",
751
+	0
752
+};
753
+
754
+static void cfgt_rpc_mask(rpc_t* rpc, void* ctx){
755
+	int mask = CFGT_DP_ALL;
756
+
757
+	if (rpc->scan(ctx, "*d", &mask) != 1)
758
+	{
759
+		rpc->fault(ctx, 500, "invalid parameters");
760
+		return;
761
+	}
762
+	cfgt_mask = mask;
763
+	rpc->add(ctx, "s", "200 ok");
764
+}
765
+
766
+rpc_export_t cfgt_rpc[] = {
767
+	{"dbg.mask", cfgt_rpc_mask, cfgt_rpc_mask_doc, 0},
768
+	{0, 0, 0, 0}
769
+};
770
+
771
+int cfgt_init(void)
772
+{
773
+	if (rpc_register_array(cfgt_rpc)!=0)
774
+	{
775
+		LM_ERR("failed to register RPC commands\n");
776
+		return -1;
777
+	}
778
+	_cfgt_uuid = shm_malloc(sizeof(cfgt_hash_t));
779
+	if(_cfgt_uuid==NULL)
780
+	{
781
+		LM_ERR("Cannot allocate shared memory\n");
782
+		return -1;
783
+	}
784
+	if(!lock_init(&_cfgt_uuid->lock))
785
+	{
786
+		LM_ERR("cannot init the lock\n");
787
+		shm_free(_cfgt_uuid);
788
+		_cfgt_uuid = NULL;
789
+		return -1;
790
+	}
791
+	if(_cfgt_init_hashtable(&_cfgt_uuid->hash)<0)
792
+		return -1;
793
+	sr_event_register_cb(SREV_NET_DATA_IN, cfgt_msgin);
794
+	sr_event_register_cb(SREV_NET_DATA_OUT, cfgt_msgout);
795
+	return 0;
796
+}
0 797
new file mode 100644
... ...
@@ -0,0 +1,67 @@
0
+/**
1
+ *
2
+ * Copyright (C) 2015 Victor Seva (sipwise.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * This file is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ *
20
+ */
21
+#ifndef _CFGT_INT_H_
22
+#define _CFGT_INT_H_
23
+
24
+#include "../../lib/srutils/srjson.h"
25
+#include "../../locking.h"
26
+#include "../../route_struct.h"
27
+#include "../../str_hash.h"
28
+
29
+#define CFGT_HASH_SIZE 32
30
+
31
+enum _cfgt_action_type {
32
+	CFGT_ROUTE=1,
33
+	CFGT_DROP_E, CFGT_DROP_D, CFGT_DROP_R
34
+};
35
+
36
+typedef struct _cfgt_hash
37
+{
38
+	gen_lock_t lock;
39
+	struct str_hash_table hash;
40
+	str save_uuid; /* uuid to be save */
41
+} cfgt_hash_t, *cfgt_hash_p;
42
+
43
+typedef struct _cfgt_str_list
44
+{
45
+	str s;
46
+	enum _cfgt_action_type type;
47
+	struct _cfgt_str_list *next, *prev;
48
+} cfgt_str_list_t, *cfgt_str_list_p;
49
+
50
+typedef struct _cfgt_node
51
+{
52
+	srjson_doc_t jdoc;
53
+	str uuid;
54
+	int msgid;
55
+	cfgt_str_list_p flow_head;
56
+	cfgt_str_list_p route;
57
+	srjson_t *in, *out, *flow;
58
+	struct _cfgt_node *next, *prev;
59
+} cfgt_node_t, *cfgt_node_p;
60
+
61
+int cfgt_init(void);
62
+cfgt_node_p cfgt_create_node(struct sip_msg *msg);
63
+int cfgt_process_route(struct sip_msg *msg, struct action *a);
64
+int cfgt_pre(struct sip_msg *msg, unsigned int flags, void *bar);
65
+int cfgt_post(struct sip_msg *msg, unsigned int flags, void *bar);
66
+#endif
0 67
new file mode 100644
... ...
@@ -0,0 +1,389 @@
0
+/**
1
+ *
2
+ * Copyright (C) 2013-2015 Victor Seva (sipwise.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * This file is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ *
20
+ */
21
+#include <stdio.h>
22
+
23
+#include "../../pvar.h"
24
+#include "../../mem/shm_mem.h"
25
+#include "../../xavp.h"
26
+#include "../pv/pv_xavp.h"
27
+
28
+#include "cfgt_json.h"
29
+
30
+int _cfgt_get_array_avp_vals(struct sip_msg *msg,
31
+		pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobj,
32
+		str *item_name)
33
+{
34
+	struct usr_avp *avp;
35
+	unsigned short name_type;
36
+	int_str avp_name;
37
+	int_str avp_value;
38
+	struct search_state state;
39
+	srjson_t *jobjt;
40
+	memset(&state, 0, sizeof(struct search_state));
41
+
42
+	if(pv_get_avp_name(msg, param, &avp_name, &name_type)!=0)
43
+	{
44
+		LM_ERR("invalid name\n");
45
+		return -1;
46
+	}
47
+	*jobj = srjson_CreateArray(jdoc);
48
+	if(*jobj==NULL)
49
+	{
50
+		LM_ERR("cannot create json object\n");
51
+		return -1;
52
+	}
53
+	if ((avp=search_first_avp(name_type, avp_name, &avp_value, &state))==0)
54
+	{
55
+		goto ok;
56
+	}
57
+	do
58
+	{
59
+		if(avp->flags & AVP_VAL_STR)
60
+		{
61
+			jobjt = srjson_CreateStr(jdoc, avp_value.s.s, avp_value.s.len);
62
+			if(jobjt==NULL)
63
+			{
64
+				LM_ERR("cannot create json object\n");
65
+				return -1;
66
+			}
67
+		} else {
68
+			jobjt = srjson_CreateNumber(jdoc, avp_value.n);
69
+			if(jobjt==NULL)
70
+			{
71
+				LM_ERR("cannot create json object\n");
72
+				return -1;
73
+			}
74
+		}
75
+		srjson_AddItemToArray(jdoc, *jobj, jobjt);
76
+	} while ((avp=search_next_avp(&state, &avp_value))!=0);
77
+ok:
78
+	item_name->s = avp_name.s.s;
79
+	item_name->len = avp_name.s.len;
80
+	return 0;
81
+}
82
+#define CFGT_XAVP_DUMP_SIZE 32
83
+static str* _cfgt_xavp_dump[CFGT_XAVP_DUMP_SIZE];
84
+int _cfgt_xavp_dump_lookup(pv_param_t *param)
85
+{
86
+	unsigned int i = 0;
87
+	pv_xavp_name_t *xname;
88
+
89
+	if(param==NULL)
90
+		return -1;
91
+
92
+	xname = (pv_xavp_name_t*)param->pvn.u.dname;
93
+
94
+	while(_cfgt_xavp_dump[i]!=NULL&&i<CFGT_XAVP_DUMP_SIZE)
95
+	{
96
+		if(_cfgt_xavp_dump[i]->len==xname->name.len)
97
+		{
98
+			if(strncmp(_cfgt_xavp_dump[i]->s, xname->name.s, xname->name.len)==0)
99
+				return 1; /* already dump before */
100
+		}
101
+		i++;
102
+	}
103
+	if(i==CFGT_XAVP_DUMP_SIZE)
104
+	{
105
+		LM_WARN("full _cfgt_xavp_dump cache array\n");
106
+		return 0; /* end cache names */
107
+	}
108
+	_cfgt_xavp_dump[i] = &xname->name;
109
+	return 0;
110
+}
111
+
112
+void _cfgt_get_obj_xavp_val(sr_xavp_t *avp, srjson_doc_t *jdoc, srjson_t **jobj)
113
+{
114
+	static char _pv_xavp_buf[128];
115
+	int result = 0;
116
+
117
+	switch(avp->val.type) {
118
+		case SR_XTYPE_NULL:
119
+			*jobj = srjson_CreateNull(jdoc);
120
+		break;
121
+		case SR_XTYPE_INT:
122
+			*jobj = srjson_CreateNumber(jdoc, avp->val.v.i);
123
+		break;
124
+		case SR_XTYPE_STR:
125
+			*jobj = srjson_CreateStr(jdoc, avp->val.v.s.s, avp->val.v.s.len);
126
+		break;
127
+		case SR_XTYPE_TIME:
128
+			result = snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t);
129
+		break;
130
+		case SR_XTYPE_LONG:
131
+			result = snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l);
132
+		break;
133
+		case SR_XTYPE_LLONG:
134
+			result = snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll);
135
+		break;
136
+		case SR_XTYPE_XAVP:
137
+			result = snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp);
138
+		break;
139
+		case SR_XTYPE_DATA:
140
+			result = snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data);
141
+		break;
142
+		default:
143
+			LM_WARN("unknown data type\n");
144
+			*jobj = srjson_CreateNull(jdoc);
145
+	}
146
+	if(result<0)
147
+	{
148
+		LM_ERR("cannot convert to str\n");
149
+		*jobj = srjson_CreateNull(jdoc);
150
+	}
151
+	else if(*jobj==NULL)
152
+	{
153
+		*jobj = srjson_CreateStr(jdoc, _pv_xavp_buf, 128);
154
+	}
155
+}
156
+
157
+int _cfgt_get_obj_avp_vals(str name, sr_xavp_t *xavp, srjson_doc_t *jdoc, srjson_t **jobj)
158
+{
159
+	sr_xavp_t *avp = NULL;
160
+	srjson_t *jobjt = NULL;
161
+
162
+	*jobj = srjson_CreateArray(jdoc);
163
+	if(*jobj==NULL)
164
+	{
165
+		LM_ERR("cannot create json object\n");
166
+		return -1;
167
+	}
168
+	avp = xavp;
169
+	while(avp!=NULL&&!STR_EQ(avp->name,name))
170
+	{
171
+		avp = avp->next;
172
+	}
173
+	while(avp!=NULL)
174
+	{
175
+		_cfgt_get_obj_xavp_val(avp, jdoc, &jobjt);
176
+		srjson_AddItemToArray(jdoc, *jobj, jobjt);
177
+		jobjt = NULL;
178
+		avp = xavp_get_next(avp);
179
+	}
180
+
181
+	return 0;
182
+}
183
+
184
+int _cfgt_get_obj_xavp_vals(struct sip_msg *msg,
185
+		pv_param_t *param, srjson_doc_t *jdoc, srjson_t **jobjr,
186
+		str *item_name)
187
+{
188
+	pv_xavp_name_t *xname = (pv_xavp_name_t*)param->pvn.u.dname;
189
+	sr_xavp_t *xavp = NULL;
190
+	sr_xavp_t *avp = NULL;
191
+	srjson_t *jobj = NULL;
192
+	srjson_t *jobjt = NULL;
193
+	struct str_list *keys;
194
+	struct str_list *k;
195
+
196
+	*jobjr = srjson_CreateArray(jdoc);
197
+	if(*jobjr==NULL)
198
+	{
199
+		LM_ERR("cannot create json object\n");
200
+		return -1;
201
+	}
202
+
203
+	item_name->s = xname->name.s;
204
+	item_name->len = xname->name.len;
205
+	xavp = xavp_get_by_index(&xname->name, 0, NULL);
206
+	if(xavp==NULL)
207
+	{
208
+		return 0; /* empty */
209
+	}
210
+
211
+	do
212
+	{
213
+		if(xavp->val.type==SR_XTYPE_XAVP)
214
+		{
215
+			avp = xavp->val.v.xavp;
216
+			jobj = srjson_CreateObject(jdoc);
217
+			if(jobj==NULL)
218
+			{
219
+				LM_ERR("cannot create json object\n");
220
+				return -1;
221
+			}
222
+			keys = xavp_get_list_key_names(xavp);
223
+			if(keys!=NULL)
224
+			{
225
+				do
226
+				{
227
+					_cfgt_get_obj_avp_vals(keys->s, avp, jdoc, &jobjt);
228
+					srjson_AddStrItemToObject(jdoc, jobj, keys->s.s,
229
+						keys->s.len, jobjt);
230
+					k = keys;
231
+					keys = keys->next;
232
+					pkg_free(k);
233
+					jobjt = NULL;
234
+				}while(keys!=NULL);
235
+			}
236
+		}
237
+		if(jobj!=NULL)
238
+		{
239
+			srjson_AddItemToArray(jdoc, *jobjr, jobj);
240
+			jobj = NULL;
241
+		}
242
+	}while((xavp = xavp_get_next(xavp))!=0);
243
+
244
+	return 0;
245
+}
246
+
247
+int cfgt_get_json(struct sip_msg* msg, unsigned int mask, srjson_doc_t *jdoc,
248
+	srjson_t *head)
249
+{
250
+	int i;
251
+	pv_value_t value;
252
+	pv_cache_t **_pv_cache = pv_cache_get_table();
253
+	pv_cache_t *el = NULL;
254
+	srjson_t *jobj = NULL;
255
+	str item_name = STR_NULL;
256
+	static char iname[128];
257
+
258
+	if(_pv_cache==NULL)
259
+	{
260
+		LM_ERR("cannot access pv_cache\n");
261
+		return -1;
262
+	}
263
+	if(jdoc==NULL){
264
+		LM_ERR("jdoc is null\n");
265
+		return -1;
266
+	}
267
+	if(head==NULL){
268
+		LM_ERR("head is null\n");
269
+		return -1;
270
+	}
271
+
272
+	memset(_cfgt_xavp_dump, 0, sizeof(str*)*CFGT_XAVP_DUMP_SIZE);
273
+	for(i=0;i<PV_CACHE_SIZE;i++)
274
+	{
275
+		el = _pv_cache[i];
276
+		while(el)
277
+		{
278
+			if(!(el->spec.type==PVT_AVP||
279
+				el->spec.type==PVT_SCRIPTVAR||
280
+				el->spec.type==PVT_XAVP||
281
+				el->spec.type==PVT_OTHER)||
282
+				!((el->spec.type==PVT_AVP&&mask&CFGT_DP_AVP)||
283
+				(el->spec.type==PVT_XAVP&&mask&CFGT_DP_XAVP)||
284
+				(el->spec.type==PVT_SCRIPTVAR&&mask&CFGT_DP_SCRIPTVAR)||
285
+				(el->spec.type==PVT_OTHER&&mask&CFGT_DP_OTHER))||
286
+				(el->spec.trans!=NULL))
287
+			{
288
+				el = el->next;
289
+				continue;
290
+			}
291
+			jobj = NULL;
292
+			item_name.len = 0;
293
+			item_name.s = 0;
294
+			iname[0] = '\0';
295
+			if(el->spec.type==PVT_AVP)
296
+			{
297
+				if(el->spec.pvp.pvi.type==PV_IDX_ALL||
298
+					(el->spec.pvp.pvi.type==PV_IDX_INT&&el->spec.pvp.pvi.u.ival!=0))
299
+				{
300
+					el = el->next;
301
+					continue;
302
+				}
303
+				else
304
+				{
305
+					if(_cfgt_get_array_avp_vals(msg, &el->spec.pvp, jdoc, &jobj, &item_name)!=0)
306
+					{
307
+						LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
308
+						el = el->next;
309
+						continue;
310
+					}
311
+					if(srjson_GetArraySize(jdoc, jobj)==0 && !(mask&CFGT_DP_NULL))
312
+					{
313
+						el = el->next;
314
+						continue;
315
+					}
316
+					snprintf(iname, 128, "$avp(%.*s)", item_name.len, item_name.s);
317
+				}
318
+			}
319
+			else if(el->spec.type==PVT_XAVP)
320
+			{
321
+				if(_cfgt_xavp_dump_lookup(&el->spec.pvp)!=0)
322
+				{
323
+					el = el->next;
324
+					continue;
325
+				}
326
+				if(_cfgt_get_obj_xavp_vals(msg, &el->spec.pvp, jdoc, &jobj, &item_name)!=0)
327
+				{
328
+					LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
329
+					el = el->next;
330
+					continue;
331
+				}
332
+				if(srjson_GetArraySize(jdoc, jobj)==0 && !(mask&CFGT_DP_NULL))
333
+				{
334
+					el = el->next;
335
+					continue;
336
+				}
337
+				snprintf(iname, 128, "$xavp(%.*s)", item_name.len, item_name.s);
338
+			}
339
+			else
340
+			{
341
+				if(pv_get_spec_value(msg, &el->spec, &value)!=0)
342
+				{
343
+					LM_WARN("can't get value[%.*s]\n", el->pvname.len, el->pvname.s);
344
+					el = el->next;
345
+					continue;
346
+				}
347
+				if(value.flags&(PV_VAL_NULL|PV_VAL_EMPTY|PV_VAL_NONE))
348
+				{
349
+					if(mask&CFGT_DP_NULL)
350
+					{
351
+						jobj = srjson_CreateNull(jdoc);
352
+					}
353
+					else
354
+					{
355
+						el = el->next;
356
+						continue;
357
+					}
358
+				}else if(value.flags&(PV_VAL_INT)){
359
+					jobj = srjson_CreateNumber(jdoc, value.ri);
360
+				}else if(value.flags&(PV_VAL_STR)){
361
+					jobj = srjson_CreateStr(jdoc, value.rs.s, value.rs.len);
362
+				}else {
363
+					LM_WARN("el->pvname[%.*s] value[%d] unhandled\n", el->pvname.len, el->pvname.s,
364
+						value.flags);
365
+					el = el->next;
366
+					continue;
367
+				}
368
+				if(jobj==NULL)
369
+				{
370
+					LM_ERR("el->pvname[%.*s] empty json object\n", el->pvname.len,
371
+						el->pvname.s);
372
+					goto error;
373
+				}
374
+				snprintf(iname, 128, "%.*s", el->pvname.len, el->pvname.s);
375
+			}
376
+			if(jobj!=NULL)
377
+			{
378
+				srjson_AddItemToObject(jdoc, head, iname, jobj);
379
+			}
380
+			el = el->next;
381
+		}
382
+	}
383
+	return 0;
384
+
385
+error:
386
+	srjson_Delete(jdoc, head);
387
+	return -1;
388
+}
0 389
\ No newline at end of file
1 390
new file mode 100644
... ...
@@ -0,0 +1,38 @@
0
+/**
1
+ *
2
+ * Copyright (C) 2013-2015 Victor Seva (sipwise.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * This file is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
+ *
20
+ */
21
+
22
+#ifndef _CFGT_JSON_H
23
+#define _CFGT_JSON_H
24
+
25
+#include "../../lib/srutils/srjson.h"
26
+#include "../../route_struct.h"
27
+
28
+#define CFGT_DP_NULL       1
29
+#define CFGT_DP_AVP        2
30
+#define CFGT_DP_SCRIPTVAR  4
31
+#define CFGT_DP_XAVP       8
32
+#define CFGT_DP_OTHER     16
33
+#define CFGT_DP_ALL       31
34
+
35
+int cfgt_get_json(struct sip_msg* msg, unsigned int mask, srjson_doc_t *jdoc,
36
+	srjson_t *head);
37
+#endif
0 38
new file mode 100644
... ...
@@ -0,0 +1,112 @@
0
+/*
1
+ * Copyright (C) 2015 Victor Seva (sipwise.com)
2
+ *
3
+ * This file is part of Kamailio, a free SIP server.
4
+ *
5
+ * Kamailio is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation; either version 2 of the License, or
8
+ * (at your option) any later version