Browse code

matrix: Add RPC response on matrix reload success

Olle E. Johansson authored on 03/01/2022 15:00:05
Showing 1 changed files
... ...
@@ -526,11 +526,12 @@ static void matrix_rpc_reload(rpc_t* rpc, void* c)
526 526
 	if(db_reload_matrix() < 0) {
527 527
 		rpc->fault(c, 500, "Reload failed");
528 528
 	}
529
+	rpc->rpl_printf(c, "Ok. Reload successful.");
529 530
 	matrix_db_close();
530 531
 }
531 532
 
532 533
 static const char *matrix_rpc_reload_doc[2] = {
533
-	"reload matrix records from database",
534
+	"Reload matrix records from database",
534 535
 	0
535 536
 };
536 537
 
Browse code

matrix: updated to the new mod interface

Victor Seva authored on 28/09/2018 08:27:16
Showing 1 changed files
... ...
@@ -104,19 +104,17 @@ static param_export_t params[] = {
104 104
 
105 105
 
106 106
 
107
-struct module_exports exports= {
108
-	"matrix",
109
-	DEFAULT_DLFLAGS,
110
-	cmds,
111
-	params,
112
-	0,
113
-	0,
114
-	0,
115
-	0,
116
-	mod_init,
117
-	0,
118
-	mod_destroy,
119
-	child_init
107
+struct module_exports exports = {
108
+	"matrix",        /* module name */
109
+	DEFAULT_DLFLAGS, /* dlopen flags */
110
+	cmds,            /* cmd (cfg function) exports */
111
+	params,          /* param exports */
112
+	0,               /* RPC method exports */
113
+	0,               /* pseudo-variables exports */
114
+	0,               /* response handling function */
115
+	mod_init,        /* module init function */
116
+	child_init,      /* per-child init function */
117
+	mod_destroy      /* module destroy function */
120 118
 };
121 119
 
122 120
 
Browse code

matrix: removed mi command

Daniel-Constantin Mierla authored on 30/12/2016 13:58:48
Showing 1 changed files
... ...
@@ -22,7 +22,6 @@
22 22
 
23 23
 #include "../../core/mem/shm_mem.h"
24 24
 #include "../../core/sr_module.h"
25
-#include "../../lib/kmi/mi.h"
26 25
 #include "../../core/mem/mem.h"
27 26
 #include "../../core/usr_avp.h"
28 27
 #include "../../core/locking.h"
... ...
@@ -84,14 +83,8 @@ static int lookup_matrix(struct sip_msg *msg, struct multiparam_t *_first, struc
84 83
 /* ---- module init functions: */
85 84
 static int mod_init(void);
86 85
 static int child_init(int rank);
87
-static int mi_child_init(void);
88 86
 static void mod_destroy(void);
89 87
 
90
-/* --- fifo functions */
91
-struct mi_root * mi_reload_matrix(struct mi_root* cmd, void* param);  /* usage: kamctl fifo reload_matrix */
92
-
93
-
94
-
95 88
 
96 89
 static cmd_export_t cmds[]={
97 90
 	{ "matrix", (cmd_function)lookup_matrix, 3, matrix_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
... ...
@@ -111,22 +104,13 @@ static param_export_t params[] = {
111 104
 
112 105
 
113 106
 
114
-/* Exported MI functions */
115
-static mi_export_t mi_cmds[] = {
116
-	{ "reload_matrix", mi_reload_matrix, MI_NO_INPUT_FLAG, 0, mi_child_init },
117
-	{ 0, 0, 0, 0, 0}
118
-};
119
-
120
-
121
-
122
-
123 107
 struct module_exports exports= {
124 108
 	"matrix",
125 109
 	DEFAULT_DLFLAGS,
126 110
 	cmds,
127 111
 	params,
128 112
 	0,
129
-	mi_cmds,
113
+	0,
130 114
 	0,
131 115
 	0,
132 116
 	mod_init,
... ...
@@ -535,24 +519,16 @@ static void destroy_shmlock(void)
535 519
 
536 520
 
537 521
 
538
-
539
-struct mi_root * mi_reload_matrix(struct mi_root* cmd, void* param)
540
-{
541
-	struct mi_root * tmp = NULL;
542
-	if(db_reload_matrix() >= 0) {
543
-		tmp = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
544
-	} else {
545
-		tmp = init_mi_tree( 500, "cannot reload matrix", 24);
546
-	}
547
-
548
-	return tmp;
549
-}
550
-
551 522
 static void matrix_rpc_reload(rpc_t* rpc, void* c)
552 523
 {
524
+	if (matrix_db_open() != 0) {
525
+		rpc->fault(c, 500, "Failed to connect to db");
526
+		return;
527
+	}
553 528
 	if(db_reload_matrix() < 0) {
554 529
 		rpc->fault(c, 500, "Reload failed");
555 530
 	}
531
+	matrix_db_close();
556 532
 }
557 533
 
558 534
 static const char *matrix_rpc_reload_doc[2] = {
... ...
@@ -609,10 +585,6 @@ static void destroy_matrix(void)
609 585
 
610 586
 static int mod_init(void)
611 587
 {
612
-	if(register_mi_mod(exports.name, mi_cmds)!=0) {
613
-		LM_ERR("failed to register MI commands\n");
614
-		return -1;
615
-	}
616 588
 	if(matrix_rpc_init()<0) {
617 589
 		LM_ERR("failed to init RPC commands");
618 590
 		return -1;
... ...
@@ -628,7 +600,6 @@ static int mod_init(void)
628 600
 
629 601
 
630 602
 
631
-
632 603
 static int child_init(int rank)
633 604
 {
634 605
 	if(rank==PROC_INIT || rank==PROC_TCP_MAIN)
... ...
@@ -639,16 +610,6 @@ static int child_init(int rank)
639 610
 
640 611
 
641 612
 
642
-
643
-static int mi_child_init(void)
644
-{
645
-	if (matrix_db_open() != 0) return -1;
646
-	return 0;
647
-}
648
-
649
-
650
-
651
-
652 613
 static void mod_destroy(void)
653 614
 {
654 615
 	destroy_matrix();
Browse code

matrix: added matrix.reload rpc command

Daniel-Constantin Mierla authored on 13/12/2016 11:59:15
Showing 1 changed files
... ...
@@ -1,6 +1,4 @@
1 1
 /*
2
- * $Id: matrix.c 4978 2008-09-23 14:25:02Z henningw $
3
- *
4 2
  * Copyright (C) 2007 1&1 Internet AG
5 3
  *
6 4
  * This file is part of Kamailio, a free SIP server.
... ...
@@ -15,8 +13,8 @@
15 13
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 14
  * GNU General Public License for more details.
17 15
  *
18
- * You should have received a copy of the GNU General Public License 
19
- * along with this program; if not, write to the Free Software 
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
20 18
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 19
  */
22 20
 
... ...
@@ -31,6 +29,8 @@
31 29
 #include "../../core/error.h"
32 30
 #include "../../core/ut.h"
33 31
 #include "../../core/mod_fix.h"
32
+#include "../../core/rpc_lookup.h"
33
+
34 34
 
35 35
 #include "db_matrix.h"
36 36
 
... ...
@@ -73,6 +73,7 @@ struct multiparam_t {
73 73
 
74 74
 
75 75
 
76
+int matrix_rpc_init(void);
76 77
 
77 78
 /* ---- fixup functions: */
78 79
 static int matrix_fixup(void** param, int param_no);
... ...
@@ -102,9 +103,9 @@ static cmd_export_t cmds[]={
102 103
 
103 104
 static param_export_t params[] = {
104 105
 	matrix_DB_URL
105
-	matrix_DB_TABLE
106
-	matrix_DB_COLS
107
-	{ 0, 0, 0}
106
+		matrix_DB_TABLE
107
+		matrix_DB_COLS
108
+		{ 0, 0, 0}
108 109
 };
109 110
 
110 111
 
... ...
@@ -138,7 +139,7 @@ struct module_exports exports= {
138 139
 
139 140
 
140 141
 struct first_t {
141
-  struct first_t *next;
142
+	struct first_t *next;
142 143
 	int id;
143 144
 	short int second_list[MAXCOLS+1];
144 145
 };
... ...
@@ -147,7 +148,7 @@ struct first_t {
147 148
 
148 149
 
149 150
 struct matrix_t {
150
-  struct first_t *head;
151
+	struct first_t *head;
151 152
 };
152 153
 
153 154
 
... ...
@@ -178,7 +179,7 @@ static int mp_fixup(void ** param) {
178 179
 		return -1;
179 180
 	}
180 181
 	memset(mp, 0, sizeof(struct multiparam_t));
181
-	
182
+
182 183
 	s.s = (char *)(*param);
183 184
 	s.len = strlen(s.s);
184 185
 
... ...
@@ -238,14 +239,14 @@ static int avp_name_fixup(void ** param) {
238 239
 		LM_ERR("Malformed or non AVP definition <%s>\n", (char *)(*param));
239 240
 		return -1;
240 241
 	}
241
-	
242
+
242 243
 	mp = (struct multiparam_t *)pkg_malloc(sizeof(struct multiparam_t));
243 244
 	if (mp == NULL) {
244 245
 		LM_ERR("out of pkg memory\n");
245 246
 		return -1;
246 247
 	}
247 248
 	memset(mp, 0, sizeof(struct multiparam_t));
248
-	
249
+
249 250
 	mp->type=MP_AVP;
250 251
 	if(pv_get_avp_name(0, &(avp_spec.pvp), &(mp->u.a.name), &(mp->u.a.flags))!=0) {
251 252
 		LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
... ...
@@ -254,7 +255,7 @@ static int avp_name_fixup(void ** param) {
254 255
 	}
255 256
 
256 257
 	*param = (void*)mp;
257
-	
258
+
258 259
 	return 0;
259 260
 }
260 261
 
... ...
@@ -351,7 +352,7 @@ static int matrix_insert(int first, short int second, int res)
351 352
 
352 353
 
353 354
 /* Returns the res id if the matrix contains an entry for the given indices, -1 otherwise.
354
- */
355
+*/
355 356
 static int internal_lookup(int first, short int second)
356 357
 {
357 358
 	struct first_t *item;
... ...
@@ -385,47 +386,47 @@ static int lookup_matrix(struct sip_msg *msg, struct multiparam_t *_srctree, str
385 386
 	int_str avp_val;
386 387
 
387 388
 	switch (_srctree->type) {
388
-	case MP_INT:
389
-		first = _srctree->u.n;
390
-		break;
391
-	case MP_AVP:
392
-		avp = search_first_avp(_srctree->u.a.flags, _srctree->u.a.name, &avp_val, 0);
393
-		if (!avp) {
394
-			LM_ERR("cannot find srctree AVP\n");
395
-			return -1;
396
-		}
397
-		if ((avp->flags&AVP_VAL_STR)) {
398
-			LM_ERR("cannot process string value in srctree AVP\n");
389
+		case MP_INT:
390
+			first = _srctree->u.n;
391
+			break;
392
+		case MP_AVP:
393
+			avp = search_first_avp(_srctree->u.a.flags, _srctree->u.a.name, &avp_val, 0);
394
+			if (!avp) {
395
+				LM_ERR("cannot find srctree AVP\n");
396
+				return -1;
397
+			}
398
+			if ((avp->flags&AVP_VAL_STR)) {
399
+				LM_ERR("cannot process string value in srctree AVP\n");
400
+				return -1;
401
+			}
402
+			else first = avp_val.n;
403
+			break;
404
+		default:
405
+			LM_ERR("invalid srctree type\n");
399 406
 			return -1;
400
-		}
401
-		else first = avp_val.n;
402
-		break;
403
-	default:
404
-		LM_ERR("invalid srctree type\n");
405
-		return -1;
406 407
 	}
407 408
 
408 409
 	switch (_second->type) {
409
-	case MP_INT:
410
-		second = _second->u.n;
411
-		break;
412
-	case MP_AVP:
413
-		avp = search_first_avp(_second->u.a.flags, _second->u.a.name, &avp_val, 0);
414
-		if (!avp) {
415
-			LM_ERR("cannot find second_value AVP\n");
416
-			return -1;
417
-		}
418
-		if ((avp->flags&AVP_VAL_STR)) {
419
-			LM_ERR("cannot process string value in second_value AVP\n");
410
+		case MP_INT:
411
+			second = _second->u.n;
412
+			break;
413
+		case MP_AVP:
414
+			avp = search_first_avp(_second->u.a.flags, _second->u.a.name, &avp_val, 0);
415
+			if (!avp) {
416
+				LM_ERR("cannot find second_value AVP\n");
417
+				return -1;
418
+			}
419
+			if ((avp->flags&AVP_VAL_STR)) {
420
+				LM_ERR("cannot process string value in second_value AVP\n");
421
+				return -1;
422
+			}
423
+			else second = avp_val.n;
424
+			break;
425
+		default:
426
+			LM_ERR("invalid second_value type\n");
420 427
 			return -1;
421
-		}
422
-		else second = avp_val.n;
423
-		break;
424
-	default:
425
-		LM_ERR("invalid second_value type\n");
426
-		return -1;
427 428
 	}
428
-	
429
+
429 430
 
430 431
 	/* critical section start: avoids dirty reads when updating d-tree */
431 432
 	lock_get(lock);
... ...
@@ -462,7 +463,7 @@ static int db_reload_matrix(void)
462 463
 	db1_res_t *res;
463 464
 	int i;
464 465
 	int n = 0;
465
-	
466
+
466 467
 	if (matrix_dbf.use_table(matrix_dbh, &matrix_table) < 0) {
467 468
 		LM_ERR("cannot use table '%.*s'.\n", matrix_table.len, matrix_table.s);
468 469
 		return -1;
... ...
@@ -547,9 +548,35 @@ struct mi_root * mi_reload_matrix(struct mi_root* cmd, void* param)
547 548
 	return tmp;
548 549
 }
549 550
 
551
+static void matrix_rpc_reload(rpc_t* rpc, void* c)
552
+{
553
+	if(db_reload_matrix() < 0) {
554
+		rpc->fault(c, 500, "Reload failed");
555
+	}
556
+}
550 557
 
558
+static const char *matrix_rpc_reload_doc[2] = {
559
+	"reload matrix records from database",
560
+	0
561
+};
551 562
 
552 563
 
564
+rpc_export_t matrix_rpc_cmds[] = {
565
+	{"matrix.reload", matrix_rpc_reload, matrix_rpc_reload_doc, 0},
566
+	{0, 0, 0, 0}
567
+};
568
+
569
+int matrix_rpc_init(void)
570
+{
571
+	if (rpc_register_array(matrix_rpc_cmds)!=0)
572
+	{
573
+		LM_ERR("failed to register RPC commands\n");
574
+		return -1;
575
+	}
576
+	return 0;
577
+
578
+}
579
+
553 580
 static int init_matrix(void)
554 581
 {
555 582
 	matrix = shm_malloc(sizeof(struct matrix_t));
... ...
@@ -582,11 +609,14 @@ static void destroy_matrix(void)
582 609
 
583 610
 static int mod_init(void)
584 611
 {
585
-	if(register_mi_mod(exports.name, mi_cmds)!=0)
586
-	{
612
+	if(register_mi_mod(exports.name, mi_cmds)!=0) {
587 613
 		LM_ERR("failed to register MI commands\n");
588 614
 		return -1;
589 615
 	}
616
+	if(matrix_rpc_init()<0) {
617
+		LM_ERR("failed to init RPC commands");
618
+		return -1;
619
+	}
590 620
 
591 621
 	if (init_shmlock() != 0) return -1;
592 622
 	if (matrix_db_init() != 0) return -1;
Browse code

core, lib, modules: updated include paths for header files

Daniel-Constantin Mierla authored on 07/12/2016 11:07:22
Showing 1 changed files
... ...
@@ -22,15 +22,15 @@
22 22
 
23 23
 #include <string.h>
24 24
 
25
-#include "../../mem/shm_mem.h"
26
-#include "../../sr_module.h"
25
+#include "../../core/mem/shm_mem.h"
26
+#include "../../core/sr_module.h"
27 27
 #include "../../lib/kmi/mi.h"
28
-#include "../../mem/mem.h"
29
-#include "../../usr_avp.h"
30
-#include "../../locking.h"
31
-#include "../../error.h"
32
-#include "../../ut.h"
33
-#include "../../mod_fix.h"
28
+#include "../../core/mem/mem.h"
29
+#include "../../core/usr_avp.h"
30
+#include "../../core/locking.h"
31
+#include "../../core/error.h"
32
+#include "../../core/ut.h"
33
+#include "../../core/mod_fix.h"
34 34
 
35 35
 #include "db_matrix.h"
36 36
 
Browse code

core, lib, modules: restructured source code tree

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

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,627 @@
1
+/*
2
+ * $Id: matrix.c 4978 2008-09-23 14:25:02Z henningw $
3
+ *
4
+ * Copyright (C) 2007 1&1 Internet AG
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License 
19
+ * along with this program; if not, write to the Free Software 
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ */
22
+
23
+#include <string.h>
24
+
25
+#include "../../mem/shm_mem.h"
26
+#include "../../sr_module.h"
27
+#include "../../lib/kmi/mi.h"
28
+#include "../../mem/mem.h"
29
+#include "../../usr_avp.h"
30
+#include "../../locking.h"
31
+#include "../../error.h"
32
+#include "../../ut.h"
33
+#include "../../mod_fix.h"
34
+
35
+#include "db_matrix.h"
36
+
37
+MODULE_VERSION
38
+
39
+
40
+
41
+
42
+#define MAXCOLS 1000
43
+
44
+
45
+
46
+
47
+str matrix_db_url = str_init(DEFAULT_RODB_URL);
48
+
49
+
50
+
51
+
52
+/**
53
+ * Generic parameter that holds a string, an int or an pseudo-variable
54
+ * @todo replace this with gparam_t
55
+ */
56
+struct multiparam_t {
57
+	enum {
58
+		MP_INT,
59
+		MP_STR,
60
+		MP_AVP,
61
+		MP_PVE,
62
+	} type;
63
+	union {
64
+		int n;
65
+		str s;
66
+		struct {
67
+			unsigned short flags;
68
+			int_str name;
69
+		} a;
70
+		pv_elem_t *p;
71
+	} u;
72
+};
73
+
74
+
75
+
76
+
77
+/* ---- fixup functions: */
78
+static int matrix_fixup(void** param, int param_no);
79
+
80
+/* ---- exported commands: */
81
+static int lookup_matrix(struct sip_msg *msg, struct multiparam_t *_first, struct multiparam_t *_second, struct multiparam_t *_dstavp);
82
+
83
+/* ---- module init functions: */
84
+static int mod_init(void);
85
+static int child_init(int rank);
86
+static int mi_child_init(void);
87
+static void mod_destroy(void);
88
+
89
+/* --- fifo functions */
90
+struct mi_root * mi_reload_matrix(struct mi_root* cmd, void* param);  /* usage: kamctl fifo reload_matrix */
91
+
92
+
93
+
94
+
95
+static cmd_export_t cmds[]={
96
+	{ "matrix", (cmd_function)lookup_matrix, 3, matrix_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
97
+	{ 0, 0, 0, 0, 0, 0}
98
+};
99
+
100
+
101
+
102
+
103
+static param_export_t params[] = {
104
+	matrix_DB_URL
105
+	matrix_DB_TABLE
106
+	matrix_DB_COLS
107
+	{ 0, 0, 0}
108
+};
109
+
110
+
111
+
112
+
113
+/* Exported MI functions */
114
+static mi_export_t mi_cmds[] = {
115
+	{ "reload_matrix", mi_reload_matrix, MI_NO_INPUT_FLAG, 0, mi_child_init },
116
+	{ 0, 0, 0, 0, 0}
117
+};
118
+
119
+
120
+
121
+
122
+struct module_exports exports= {
123
+	"matrix",
124
+	DEFAULT_DLFLAGS,
125
+	cmds,
126
+	params,
127
+	0,
128
+	mi_cmds,
129
+	0,
130
+	0,
131
+	mod_init,
132
+	0,
133
+	mod_destroy,
134
+	child_init
135
+};
136
+
137
+
138
+
139
+
140
+struct first_t {
141
+  struct first_t *next;
142
+	int id;
143
+	short int second_list[MAXCOLS+1];
144
+};
145
+
146
+
147
+
148
+
149
+struct matrix_t {
150
+  struct first_t *head;
151
+};
152
+
153
+
154
+
155
+
156
+static gen_lock_t *lock = NULL;
157
+static struct matrix_t *matrix = NULL;
158
+
159
+
160
+
161
+
162
+/**
163
+ * fixes the module functions' parameters if it is a phone number.
164
+ * supports string, pseudo-variables and AVPs.
165
+ *
166
+ * @param param the parameter
167
+ *
168
+ * @return 0 on success, -1 on failure
169
+ */
170
+static int mp_fixup(void ** param) {
171
+	pv_spec_t avp_spec;
172
+	struct multiparam_t *mp;
173
+	str s;
174
+
175
+	mp = (struct multiparam_t *)pkg_malloc(sizeof(struct multiparam_t));
176
+	if (mp == NULL) {
177
+		LM_ERR("out of pkg memory\n");
178
+		return -1;
179
+	}
180
+	memset(mp, 0, sizeof(struct multiparam_t));
181
+	
182
+	s.s = (char *)(*param);
183
+	s.len = strlen(s.s);
184
+
185
+	if (s.s[0]!='$') {
186
+		/* This is string */
187
+		mp->type=MP_STR;
188
+		mp->u.s=s;
189
+	}
190
+	else {
191
+		/* This is a pseudo-variable */
192
+		if (pv_parse_spec(&s, &avp_spec)==0) {
193
+			LM_ERR("pv_parse_spec failed for '%s'\n", (char *)(*param));
194
+			pkg_free(mp);
195
+			return -1;
196
+		}
197
+		if (avp_spec.type==PVT_AVP) {
198
+			/* This is an AVP - could be an id or name */
199
+			mp->type=MP_AVP;
200
+			if(pv_get_avp_name(0, &(avp_spec.pvp), &(mp->u.a.name), &(mp->u.a.flags))!=0) {
201
+				LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
202
+				pkg_free(mp);
203
+				return -1;
204
+			}
205
+		} else {
206
+			mp->type=MP_PVE;
207
+			if(pv_parse_format(&s, &(mp->u.p))<0) {
208
+				LM_ERR("pv_parse_format failed for '%s'\n", (char *)(*param));
209
+				pkg_free(mp);
210
+				return -1;
211
+			}
212
+		}
213
+	}
214
+	*param = (void*)mp;
215
+
216
+	return 0;
217
+}
218
+
219
+
220
+
221
+
222
+/**
223
+ * fixes the module functions' parameters in case of AVP names.
224
+ *
225
+ * @param param the parameter
226
+ *
227
+ * @return 0 on success, -1 on failure
228
+ */
229
+static int avp_name_fixup(void ** param) {
230
+	pv_spec_t avp_spec;
231
+	struct multiparam_t *mp;
232
+	str s;
233
+
234
+	s.s = (char *)(*param);
235
+	s.len = strlen(s.s);
236
+	if (s.len <= 0) return -1;
237
+	if (pv_parse_spec(&s, &avp_spec)==0 || avp_spec.type!=PVT_AVP) {
238
+		LM_ERR("Malformed or non AVP definition <%s>\n", (char *)(*param));
239
+		return -1;
240
+	}
241
+	
242
+	mp = (struct multiparam_t *)pkg_malloc(sizeof(struct multiparam_t));
243
+	if (mp == NULL) {
244
+		LM_ERR("out of pkg memory\n");
245
+		return -1;
246
+	}
247
+	memset(mp, 0, sizeof(struct multiparam_t));
248
+	
249
+	mp->type=MP_AVP;
250
+	if(pv_get_avp_name(0, &(avp_spec.pvp), &(mp->u.a.name), &(mp->u.a.flags))!=0) {
251
+		LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
252
+		pkg_free(mp);
253
+		return -1;
254
+	}
255
+
256
+	*param = (void*)mp;
257
+	
258
+	return 0;
259
+}
260
+
261
+
262
+
263
+
264
+static int matrix_fixup(void** param, int param_no)
265
+{
266
+	if (param_no == 1) {
267
+		/* source id */
268
+		if (mp_fixup(param) < 0) {
269
+			LM_ERR("cannot fixup parameter %d\n", param_no);
270
+			return -1;
271
+		}
272
+	}
273
+	else if (param_no == 2) {
274
+		/* destination id */
275
+		if (mp_fixup(param) < 0) {
276
+			LM_ERR("cannot fixup parameter %d\n", param_no);
277
+			return -1;
278
+		}
279
+	}
280
+	else if (param_no == 3) {
281
+		/* destination avp name */
282
+		if (avp_name_fixup(param) < 0) {
283
+			LM_ERR("cannot fixup parameter %d\n", param_no);
284
+			return -1;
285
+		}
286
+	}
287
+
288
+	return 0;
289
+}
290
+
291
+
292
+
293
+
294
+static void matrix_clear(void)
295
+{
296
+	struct first_t *srcitem;
297
+	if (matrix) {
298
+		while (matrix->head) {
299
+			srcitem = matrix->head;
300
+			matrix->head = srcitem->next;
301
+			shm_free(srcitem);
302
+		}
303
+	}
304
+}
305
+
306
+
307
+
308
+
309
+static int matrix_insert(int first, short int second, int res)
310
+{
311
+	struct first_t *srcitem;
312
+	int i;
313
+
314
+	if ((second<0) || (second>MAXCOLS)) {
315
+		LM_ERR("invalid second value %d\n", second);
316
+		return -1;
317
+	}
318
+	LM_DBG("searching for %d, %d\n", first, second);
319
+	if (matrix) {
320
+		srcitem = matrix->head;
321
+		while (srcitem) {
322
+			if (srcitem->id == first) {
323
+				srcitem->second_list[second] = res;
324
+				LM_DBG("inserted (%d, %d, %d)\n", first, second, res);
325
+				return 0;
326
+			}
327
+			srcitem = srcitem->next;
328
+		}
329
+		/* not found */
330
+		srcitem = shm_malloc(sizeof(struct first_t));
331
+		if (srcitem == NULL) {
332
+			LM_ERR("out of shared memory.\n");
333
+			return -1;
334
+		}
335
+		memset(srcitem, 0, sizeof(struct first_t));
336
+
337
+		/* Mark all new cells as empty */
338
+		for (i=0; i<=MAXCOLS; i++) srcitem->second_list[i] = -1;
339
+
340
+		srcitem->next = matrix->head;
341
+		srcitem->id = first;
342
+		srcitem->second_list[second] = res;
343
+		matrix->head = srcitem;
344
+	}
345
+
346
+	LM_DBG("inserted new row for (%d, %d, %d)\n", first, second, res);
347
+	return 0;
348
+}
349
+
350
+
351
+
352
+
353
+/* Returns the res id if the matrix contains an entry for the given indices, -1 otherwise.
354
+ */
355
+static int internal_lookup(int first, short int second)
356
+{
357
+	struct first_t *item;
358
+
359
+	if ((second<0) || (second>MAXCOLS)) {
360
+		LM_ERR("invalid second value %d\n", second);
361
+		return -1;
362
+	}
363
+
364
+	if (matrix) {
365
+		item = matrix->head;
366
+		while (item) {
367
+			if (item->id == first) {
368
+				return item->second_list[second];
369
+			}
370
+			item = item->next;
371
+		}
372
+	}
373
+
374
+	return -1;
375
+}
376
+
377
+
378
+
379
+
380
+static int lookup_matrix(struct sip_msg *msg, struct multiparam_t *_srctree, struct multiparam_t *_second, struct multiparam_t *_dstavp)
381
+{
382
+	int first;
383
+	int second;
384
+	struct usr_avp *avp;
385
+	int_str avp_val;
386
+
387
+	switch (_srctree->type) {
388
+	case MP_INT:
389
+		first = _srctree->u.n;
390
+		break;
391
+	case MP_AVP:
392
+		avp = search_first_avp(_srctree->u.a.flags, _srctree->u.a.name, &avp_val, 0);
393
+		if (!avp) {
394
+			LM_ERR("cannot find srctree AVP\n");
395
+			return -1;
396
+		}
397
+		if ((avp->flags&AVP_VAL_STR)) {
398
+			LM_ERR("cannot process string value in srctree AVP\n");
399
+			return -1;
400
+		}
401
+		else first = avp_val.n;
402
+		break;
403
+	default:
404
+		LM_ERR("invalid srctree type\n");
405
+		return -1;
406
+	}
407
+
408
+	switch (_second->type) {
409
+	case MP_INT:
410
+		second = _second->u.n;
411
+		break;
412
+	case MP_AVP:
413
+		avp = search_first_avp(_second->u.a.flags, _second->u.a.name, &avp_val, 0);
414
+		if (!avp) {
415
+			LM_ERR("cannot find second_value AVP\n");
416
+			return -1;
417
+		}
418
+		if ((avp->flags&AVP_VAL_STR)) {
419
+			LM_ERR("cannot process string value in second_value AVP\n");
420
+			return -1;
421
+		}
422
+		else second = avp_val.n;
423
+		break;
424
+	default:
425
+		LM_ERR("invalid second_value type\n");
426
+		return -1;
427
+	}
428
+	
429
+
430
+	/* critical section start: avoids dirty reads when updating d-tree */
431
+	lock_get(lock);
432
+
433
+	avp_val.n=internal_lookup(first, second);
434
+
435
+	/* critical section end */
436
+	lock_release(lock);
437
+
438
+	if (avp_val.n<0) {
439
+		LM_INFO("lookup failed\n");
440
+		return -1;
441
+	}
442
+
443
+	/* set avp ! */
444
+	if (add_avp(_dstavp->u.a.flags, _dstavp->u.a.name, avp_val)<0) {
445
+		LM_ERR("add AVP failed\n");
446
+		return -1;
447
+	}
448
+	LM_INFO("result from lookup: %d\n", avp_val.n);
449
+	return 1;
450
+}
451
+
452
+
453
+
454
+
455
+/**
456
+ * Rebuild matrix using database entries
457
+ * \return negative on failure, positive on success, indicating the number of matrix entries
458
+ */
459
+static int db_reload_matrix(void)
460
+{
461
+	db_key_t columns[3] = { &matrix_first_col, &matrix_second_col, &matrix_res_col };
462
+	db1_res_t *res;
463
+	int i;
464
+	int n = 0;
465
+	
466
+	if (matrix_dbf.use_table(matrix_dbh, &matrix_table) < 0) {
467
+		LM_ERR("cannot use table '%.*s'.\n", matrix_table.len, matrix_table.s);
468
+		return -1;
469
+	}
470
+	if (matrix_dbf.query(matrix_dbh, NULL, NULL, NULL, columns, 0, 3, NULL, &res) < 0) {
471
+		LM_ERR("error while executing query.\n");
472
+		return -1;
473
+	}
474
+
475
+	/* critical section start: avoids dirty reads when updating d-tree */