Browse code

Merge beda3fef42dfbbe96d76cf62e6b1a9f56bc957af into 4a4f0475716cbf824b2ab9684457e21f6732aa74

mojtabaesfandiari authored on 24/01/2021 16:31:19 • GitHub committed on 24/01/2021 16:31:19
Showing 8 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+#
2
+# lreproxy module makefile
3
+#
4
+#
5
+# WARNING: do not run this directly, it should be run by the master Makefile
6
+
7
+include ../../Makefile.defs
8
+auto_gen=
9
+NAME=lreproxy.so
10
+LIBS=
11
+
12
+DEFS+=-DKAMAILIO_MOD_INTERFACE
13
+
14
+SERLIBPATH=../../lib
15
+#SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
16
+include ../../Makefile.modules
17
+
0 18
new file mode 100644
... ...
@@ -0,0 +1,341 @@
1
+lreproxy Module
2
+
3
+Maxim Sobolev
4
+
5
+   Sippy Software, Inc.
6
+
7
+Juha Heinanen
8
+
9
+   TuTPro, Inc.
10
+
11
+Edited by
12
+
13
+Maxim Sobolev
14
+
15
+Edited by
16
+
17
+Bogdan-Andrei Iancu
18
+
19
+Edited by
20
+
21
+Juha Heinanen
22
+
23
+Edited by
24
+
25
+Sas Ovidiu
26
+
27
+Edited by
28
+
29
+Carsten Bock
30
+
31
+Edited by
32
+
33
+Mojtaba Esfandiari.S
34
+
35
+
36
+   ng-voice GmbH
37
+
38
+   Copyright © 2003-2008 Sippy Software, Inc.
39
+
40
+   Copyright © 2005 Voice Sistem SRL
41
+
42
+   Copyright © 2009-2012 TuTPro Inc.
43
+
44
+   Copyright © 2010 VoIPEmbedded Inc.
45
+
46
+   Copyright © 2020 Nasim-Telecom Inc.
47
+
48
+     __________________________________________________________________
49
+
50
+   Table of Contents
51
+
52
+   1. Admin Guide
53
+
54
+        1. Overview
55
+        2. Multiple lreproxy usage
56
+        3. Dependencies
57
+
58
+              3.1. Kamailio Modules
59
+              3.2. External Libraries or Applications
60
+
61
+        4. Parameters
62
+
63
+              4.1. lreproxy_sock (string)
64
+              4.2. lreproxy_disable_tout (integer)
65
+              4.3. lreproxy_tout (integer)
66
+              4.4. lreproxy_retr (integer)
67
+              4.5. lrep_alg
68
+              4.6. hash_table_tout
69
+              4.7. hash_table_size
70
+
71
+        5. Functions
72
+
73
+              5.1. set_lre_proxy_set(setid)
74
+              5.2. lreproxy_manage([flags [, ip_address]])
75
+
76
+   List of Examples
77
+
78
+   1.1. Set lreproxy_sock parameter
79
+   1.2. Set lreproxy_disable_tout parameter
80
+   1.3. Set lreproxy_tout parameter
81
+   1.4. Set lreproxy_retr parameter
82
+   1.5. Set lrep_alg parameter
83
+   1.6. Set hash_table_tout
84
+   1.7. Set hash_table_size
85
+   1.8. set_lre_proxy_set usage
86
+   1.9. lreproxy_manage usage
87
+
88
+
89
+Chapter 1. Admin Guide
90
+
91
+   Table of Contents
92
+
93
+   1. Overview
94
+   2. Multiple LREProxy usage
95
+   3. Dependencies
96
+
97
+        3.1. Kamailio Modules
98
+        3.2. External Libraries or Applications
99
+
100
+   4. Parameters
101
+
102
+              4.1. lreproxy_sock (string)
103
+              4.2. lreproxy_disable_tout (integer)
104
+              4.3. lreproxy_tout (integer)
105
+              4.4. lreproxy_retr (integer)
106
+              4.5. lrep_alg
107
+              4.6. hash_table_tout
108
+              4.7. hash_table_size
109
+
110
+   5. Functions
111
+
112
+          5.1. set_lre_proxy_set(setid)
113
+          5.2. lreproxy_manage([flags [, ip_address]])
114
+
115
+1. Overview
116
+
117
+    This is a module that enables media streams to be relayed via an
118
+    lreproxy. This module works with py_lreproxy engine in:
119
+    https://github.com/mojtabaesfandiari/py-lreproxy
120
+    This module does relaying audio streams between peers in
121
+    PREROUTING netfilter-hooking section in kernel-space linux.
122
+    The LREProxy architecture is composed of two
123
+    different layers. These layers are independent of each
124
+    other.
125
+
126
+    1.1. LREP_Controlling Layer (LREP_CL)
127
+
128
+        The first layer is developed as User-Space
129
+        application that allows User-Space to directly
130
+        access and manipulate cache data
131
+        buffer and packet buffer in Kernel-Space. This layer
132
+        gets all information about creating new sessions,
133
+        active sessions and tear-down sessions which is
134
+        gotten from SDP body during signaling plan and relay
135
+        them to the LREP-Transport Stateful Layer (LREP-
136
+        TSL).
137
+
138
+    1.2. LREP_Transport Stateful Layer (LREP_TSL)
139
+
140
+        The second layer is developed in Kernel-Space as
141
+        a main decision point for RTP admission controller
142
+        and Quickpath selector to where a received packet
143
+        should be forwarded with power of packet mangling
144
+        framework in the network stack.
145
+
146
+    The LREP_CL and LREP-TSL could be run as
147
+    independence functions on different machines. We
148
+    could have one LREP_CL with multiple LREP-TSL
149
+    on different machines. The LREP_CL could works
150
+    with all LREP-TSL with different strategies(lrep_alg parameter).
151
+
152
+2. Multiple LREProxy usage
153
+
154
+   The LREP_CL Layer can support multiple LREP_TSL Layer
155
+    for balancing/distribution and control/selection purposes.
156
+
157
+   The module allows definition of several sets of LREP_TSL.
158
+   Load-balancing will be performed over predefine algorithm by setting lrep_alg parameter.
159
+
160
+   IMPORTANT: This module does not support balancing inside a set like as is done RTPProxy module based on
161
+   the weight of each rtpproxy from the set. The balancing would be run on different machine
162
+   intead of different instances of LREP_TSL.
163
+
164
+   3. Dependencies
165
+
166
+   3.1. Kamailio Modules
167
+   3.2. External Libraries or Applications
168
+
169
+3.1. Kamailio Modules
170
+
171
+   The following modules must be loaded before this module:
172
+     * tm module - (optional) if you want to have lreproxy_manage() fully
173
+       functional
174
+
175
+3.2. External Libraries or Applications
176
+
177
+   The following libraries or applications must be installed before
178
+   running Kamailio with this module loaded:
179
+     * None.
180
+
181
+4. Parameters
182
+
183
+  4.1. lreproxy_sock (string)
184
+  4.2. lreproxy_disable_tout (integer)
185
+  4.3. lreproxy_tout (integer)
186
+  4.4. lreproxy_retr (integer)
187
+  4.5. lrep_alg
188
+  4.6. hash_table_tout
189
+  4.7. hash_table_size
190
+
191
+4.1. lreproxy_sock (string)
192
+
193
+   Used to define the list of LREP_TSL instances to connect to. These can
194
+   be UNIX sockets or IPv4/IPv6 UDP sockets. Each modparam entry will
195
+   insert sockets into a single set with default value set ID '0'.
196
+   To define multiple LREP_TSL, just add the instances in each modparam.
197
+
198
+   Example 1.1. Set lreproxy_sock (LREP_TSL instance) parameter
199
+...
200
+# single lreproxy
201
+modparam("lreproxy", "lreproxy_sock", "udp:192.168.122.108:8080")
202
+
203
+# multiple lreproxies for LB in diffenrent machine
204
+modparam("lreproxy", "lreproxy_sock", "udp:192.168.122.108:8080")
205
+modparam("lreproxy", "lreproxy_sock", "udp:192.168.122.109:8080")
206
+
207
+...
208
+
209
+4.2. lreproxy_disable_tout (integer)
210
+
211
+   Once LREP_TSL was found unreachable and marked as disabled, the
212
+   LREP_CL module will not attempt to establish communication to LREP_TSL
213
+   for lreproxy_disable_tout seconds.
214
+
215
+   Default value is “60”.
216
+
217
+   Example 1.2. Set lreproxy_disable_tout parameter
218
+...
219
+modparam("lreproxy", "lreproxy_disable_tout", 20)
220
+...
221
+
222
+4.3. lreproxy_tout (integer)
223
+
224
+   Timeout value in waiting for reply from LREP_TSL.
225
+
226
+   Default value is “1”.
227
+
228
+   Example 1.3. Set lreproxy_tout parameter
229
+...
230
+modparam("lreproxy", "lreproxy_tout", 2)
231
+...
232
+
233
+4.4. lreproxy_retr (integer)
234
+
235
+   How many times the LREP_CL should retry to send and receive after
236
+   timeout was generated.
237
+
238
+   Default value is “5”.
239
+
240
+   Example 1.4. Set lreproxy_retr parameter
241
+...
242
+modparam("lreproxy", "lreproxy_retr", 2)
243
+...
244
+
245
+4.5. lrep_alg
246
+
247
+    This parameter set the algorithm of LREP_TSL selection.
248
+    LRE_LINER=0,
249
+    LRE_RR=1
250
+
251
+    Example 1.5. Set lrep_alg parameter
252
+
253
+...
254
+modparam("lreproxy", "lrep_alg", 1)
255
+...
256
+
257
+4.6. hash_table_tout (integer)
258
+
259
+   Number of seconds after an lreproxy hash table entry is marked for
260
+   deletion. By default, this parameter is set to 3600 (seconds).
261
+
262
+   To maintain information about a selected rtp machine node, for a given
263
+   call, entries are added in a hashtable of (callid, viabranch) pairs. When
264
+   command comes, lookup callid, viabranch pairs. If found, return chosen node. If not
265
+   found, choose a new node, insert it in the hastable and return the
266
+   chosen node.
267
+
268
+   NOTE: In the current implementation, the actual deletion happens on the
269
+   fly, while insert/remove/lookup the hastable, only for the entries in
270
+   the insert/remove/lookup path.
271
+
272
+   NOTE: When configuring this parameter, one should consider maximum call
273
+   time VS share memory for unfinished calls.
274
+
275
+   Example 1.6. Set hash_table_tout parameter
276
+...
277
+modparam("lreproxy", "hash_table_tout", "300")
278
+...
279
+
280
+4.7. hash_table_size (integer)
281
+
282
+   Size of the hash table. Default value is 256.
283
+
284
+   NOTE: If configured size is less than 1, the size will be defaulted to
285
+   1.
286
+
287
+   Example 1.7. Set hash_table_size parameter
288
+...
289
+modparam("rtpengine", "hash_table_size", "123")
290
+...
291
+
292
+5. Functions
293
+
294
+      5.1. set_lre_proxy_set(setid)
295
+      5.2. lreproxy_manage([flags [, ip_address]])
296
+
297
+5.1.  set_lre_proxy_set(setid)
298
+
299
+   Sets the Id of the lreproxy set to be used for the next
300
+   unforce_lre_proxy(), lreproxy_offer(), lreproxy_answer() or
301
+   lreproxy_manage() command. The parameter can be an integer or a config
302
+   variable holding an integer.
303
+
304
+   This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE,
305
+   BRANCH_ROUTE.
306
+
307
+   Example 1.8. set_lre_proxy_set usage
308
+...
309
+set_lre_proxy_set("0");
310
+lreproxy_manage();
311
+...
312
+
313
+5.2.  lreproxy_manage([flags [, ip_address]])
314
+
315
+   Manage the LREProxy session - it combines the functionality of
316
+   lreproxy_offer(), lreproxy_answer() and unforce_lreproxy(), detecting
317
+   internally based on message type and method which one to execute.
318
+
319
+   It can take the same parameters as lreproxy_offer(). The flags
320
+   parameter to lreproxy_manage() can be a configuration variable
321
+   containing the flags as a string.
322
+
323
+    Meaning of the parameters is as follows:
324
+        * flags - flags to turn on some features.
325
+          The “flags” string is a list of space-separated items. Each item is
326
+          either an individual token, or a token in “key=value” format. The
327
+          possible tokens are described below.
328
+        + internal, external - shorthand for “ie”
329
+        + external, internal - shorthand for “ei”
330
+
331
+     This function can be used from ANY_ROUTE.
332
+
333
+   Example 1.9. lreproxy_manage usage
334
+...
335
+lreproxy_manage();
336
+//or
337
+lreproxy_manage("ie");
338
+//or
339
+lreproxy_manage("ei");
340
+
341
+...
0 342
new file mode 100644
... ...
@@ -0,0 +1,1741 @@
1
+/*
2
+ * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
3
+ * Copyright (C) 2020 Mojtaba Esfandiari.S, Nasim-Telecom
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
+ *
21
+ */
22
+
23
+#include <sys/types.h>
24
+#include <sys/socket.h>
25
+#include <sys/time.h>
26
+#include <netinet/in.h>
27
+#include <netinet/in_systm.h>
28
+#ifndef __USE_BSD
29
+#define  __USE_BSD
30
+#endif
31
+#include <netinet/ip.h>
32
+#ifndef __FAVOR_BSD
33
+#define __FAVOR_BSD
34
+#endif
35
+#include <netinet/udp.h>
36
+#include <arpa/inet.h>
37
+#include <sys/uio.h>
38
+#include <sys/un.h>
39
+#include <ctype.h>
40
+#include <errno.h>
41
+#include <netdb.h>
42
+#include <poll.h>
43
+#include <stdio.h>
44
+#include <stdlib.h>
45
+#include <string.h>
46
+#include <unistd.h>
47
+
48
+#include "../../core/flags.h"
49
+#include "../../core/sr_module.h"
50
+#include "../../core/dprint.h"
51
+#include "../../core/data_lump.h"
52
+#include "../../core/data_lump_rpl.h"
53
+#include "../../core/error.h"
54
+#include "../../core/forward.h"
55
+#include "../../core/mem/mem.h"
56
+#include "../../core/parser/parse_from.h"
57
+#include "../../core/parser/parse_to.h"
58
+#include "../../core/parser/parse_uri.h"
59
+#include "../../core/parser/parser_f.h"
60
+#include "../../core/parser/sdp/sdp.h"
61
+#include "../../core/resolve.h"
62
+#include "../../core/timer.h"
63
+#include "../../core/trim.h"
64
+#include "../../core/ut.h"
65
+#include "../../core/pt.h"
66
+#include "../../core/timer_proc.h"
67
+#include "../../core/rpc.h"
68
+#include "../../core/rpc_lookup.h"
69
+#include "../../core/pvar.h"
70
+#include "../../core/lvalue.h"
71
+#include "../../core/msg_translator.h"
72
+#include "../../core/usr_avp.h"
73
+#include "../../core/socket_info.h"
74
+#include "../../core/mod_fix.h"
75
+#include "../../core/dset.h"
76
+#include "../../core/route.h"
77
+#include "../../core/kemi.h"
78
+#include "../../modules/tm/tm_load.h"
79
+#include "lreproxy.h"
80
+#include "lreproxy_hash.h"
81
+#include "lreproxy_funcs.h"
82
+//#include "rtpproxy_stream.h"
83
+
84
+MODULE_VERSION
85
+
86
+
87
+#if !defined(AF_LOCAL)
88
+#define	AF_LOCAL AF_UNIX
89
+#endif
90
+#if !defined(PF_LOCAL)
91
+#define	PF_LOCAL PF_UNIX
92
+#endif
93
+
94
+///* NAT UAC test constants */
95
+//#define	NAT_UAC_TEST_C_1918	0x01
96
+//#define	NAT_UAC_TEST_RCVD	0x02
97
+//#define	NAT_UAC_TEST_V_1918	0x04
98
+//#define	NAT_UAC_TEST_S_1918	0x08
99
+//#define	NAT_UAC_TEST_RPORT	0x10
100
+
101
+#define DEFAULT_LREP_SET_ID		0
102
+static str DEFAULT_LREP_SET_ID_STR = str_init("0");
103
+
104
+//#define RPC_DEFAULT_NATPING_STATE	1
105
+
106
+#define RPC_MIN_RECHECK_TICKS		0
107
+#define RPC_MAX_RECHECK_TICKS		(unsigned int)-1
108
+
109
+
110
+/* Supported version of the RTP proxy command protocol */
111
+#define	SUP_CPROTOVER	"20190708"
112
+/* Required additional version of the RTP proxy command protocol */
113
+#define	REQ_CPROTOVER	"20190709"
114
+/* Additional version necessary for re-packetization support */
115
+#define	REP_CPROTOVER	"20190708"
116
+#define	PTL_CPROTOVER	"20190708"
117
+
118
+#define	CPORT		"22333"
119
+#define HASH_SIZE   128
120
+
121
+static char *gencookie();
122
+static int lrep_test(struct lrep_node*);
123
+static int lrep_get_config(struct lrep_node *node);
124
+static int lrep_set_conntrack_rule(struct lreproxy_hash_entry *e);
125
+
126
+
127
+static int lreproxy_force(struct sip_msg *msg, const char *flags, enum lre_operation op, int more);
128
+static int lreproxy_unforce(struct sip_msg *msg, const char *flags, enum lre_operation op, int more);
129
+
130
+static int lreproxy_manage0(struct sip_msg *msg, char *flags, char *ip);
131
+static int lreproxy_manage1(struct sip_msg *msg, char *flags, char *ip);
132
+static int lreproxy_manage2(struct sip_msg *msg, char *flags, char *ip);
133
+
134
+static int change_media_sdp(sip_msg_t *msg, struct lreproxy_hash_entry *e, const char *flags, enum lre_operation op);
135
+
136
+static int add_lreproxy_socks(struct lrep_set * lrep_list, char * rtpproxy);
137
+static int fixup_set_id(void ** param, int param_no);
138
+static int set_lre_proxy_set_f(struct sip_msg * msg, char * str1, char * str2);
139
+
140
+static struct lrep_set * select_lrep_set(int id_set);
141
+
142
+static int rtpproxy_set_store(modparam_t type, void * val);
143
+static int lreproxy_add_lreproxy_set( char * lre_proxies);
144
+
145
+static int mod_init(void);
146
+static int child_init(int);
147
+static void mod_destroy(void);
148
+
149
+/* Pseudo-Variables */
150
+//static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
151
+
152
+static int lreproxy_disable_tout = 60;
153
+static int lreproxy_retr = 5;
154
+static int lreproxy_tout = 1;
155
+static pid_t mypid;
156
+static unsigned int myseqn = 0;
157
+//static str nortpproxy_str = str_init("a=nortpproxy:yes");
158
+//static str extra_id_pv_param = {NULL, 0};
159
+
160
+static char ** rtpp_strings=0;
161
+static int lrep_sets=0; /*used in rtpproxy_set_store()*/
162
+static int lrep_set_count = 0;
163
+static unsigned int current_msg_id = (unsigned int)-1;
164
+/* RTP proxy balancing list */
165
+struct lrep_set_head * lrep_set_list =0;
166
+struct lrep_set * selected_lrep_set =0;
167
+struct lrep_set * default_lrep_set=0;
168
+struct lrep_node *selected_lrep_node = 0;
169
+int lrep_algorithm = LRE_LINER;
170
+static int hash_table_size = 0;
171
+static int hash_table_tout = 3600;
172
+
173
+
174
+
175
+//static char *ice_candidate_priority_avp_param = NULL;
176
+//static int ice_candidate_priority_avp_type;
177
+//static int_str ice_candidate_priority_avp;
178
+//static str rtp_inst_pv_param = {NULL, 0};
179
+//static pv_spec_t *rtp_inst_pvar = NULL;
180
+
181
+/* array with the sockets used by rtpproxy (per process)*/
182
+static unsigned int rtpp_no = 0;
183
+static int *rtpp_socks = 0;
184
+
185
+
186
+typedef struct lrep_set_link {
187
+	struct lrep_set *rset;
188
+	pv_spec_t *rpv;
189
+} lrep_set_link_t;
190
+
191
+/* tm */
192
+static struct tm_binds tmb;
193
+
194
+/*0-> disabled, 1 ->enabled*/
195
+//unsigned int *natping_state=0;
196
+
197
+//static pv_elem_t *extra_id_pv = NULL;
198
+int start_port = 10000;
199
+int end_port = 20000;
200
+str internal_ip;
201
+str external_ip;
202
+
203
+static cmd_export_t cmds[] = {
204
+
205
+        {"set_lre_proxy_set",  (cmd_function)set_lre_proxy_set_f,    1,
206
+                fixup_set_id, 0,
207
+                ANY_ROUTE},
208
+        {"lreproxy_manage",	(cmd_function)lreproxy_manage0,     0,
209
+                                                       0, 0,
210
+                   ANY_ROUTE},
211
+        {"lreproxy_manage",	(cmd_function)lreproxy_manage1,     1,
212
+                                                       fixup_spve_null, fixup_free_spve_null,
213
+                   ANY_ROUTE},
214
+        {"lreproxy_manage",	(cmd_function)lreproxy_manage2,     2,
215
+                                                       fixup_spve_spve, fixup_free_spve_spve,
216
+                   ANY_ROUTE},
217
+
218
+        {0, 0, 0, 0, 0, 0}
219
+};
220
+
221
+static param_export_t params[] = {
222
+        {"lreproxy_sock",         PARAM_STRING|USE_FUNC_PARAM,
223
+                (void*)rtpproxy_set_store          },
224
+        {"lreproxy_disable_tout", INT_PARAM, &lreproxy_disable_tout },
225
+        {"lreproxy_retr",         INT_PARAM, &lreproxy_retr         },
226
+        {"lreproxy_tout",         INT_PARAM, &lreproxy_tout         },
227
+        {"lrep_alg",         INT_PARAM, &lrep_algorithm         },
228
+        {"hash_table_tout",       INT_PARAM, &hash_table_tout        },
229
+        {"hash_table_size",       INT_PARAM, &hash_table_size        },
230
+
231
+        {0, 0, 0}
232
+};
233
+
234
+struct module_exports exports = {
235
+        "lreproxy",
236
+        DEFAULT_DLFLAGS, /* dlopen flags */
237
+        cmds,
238
+        params,
239
+        0,           /* exported statistics */
240
+        0,           /* exported MI functions */
241
+        0,     /* exported pseudo-variables */
242
+        0,           /* extra processes */
243
+        mod_init,
244
+        0,           /* reply processing */
245
+        mod_destroy, /* destroy function */
246
+        child_init
247
+};
248
+
249
+
250
+
251
+static int rtpproxy_set_store(modparam_t type, void * val){
252
+
253
+    char * p;
254
+    int len;
255
+
256
+    p = (char* )val;
257
+
258
+    if(p==0 || *p=='\0'){
259
+        return 0;
260
+    }
261
+
262
+    if(lrep_sets==0){
263
+        rtpp_strings = (char**)pkg_malloc(sizeof(char*));
264
+        if(!rtpp_strings){
265
+                    LM_ERR("no pkg memory left\n");
266
+            return -1;
267
+        }
268
+    } else {/*realloc to make room for the current set*/
269
+        rtpp_strings = (char**)pkg_reallocxf(rtpp_strings,
270
+                                             (lrep_sets+1)* sizeof(char*));
271
+        if(!rtpp_strings){
272
+                    LM_ERR("no pkg memory left\n");
273
+            return -1;
274
+        }
275
+    }
276
+
277
+    /*allocate for the current set of urls*/
278
+    len = strlen(p);
279
+    rtpp_strings[lrep_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
280
+
281
+    if(!rtpp_strings[lrep_sets]){
282
+                LM_ERR("no pkg memory left\n");
283
+        return -1;
284
+    }
285
+
286
+    memcpy(rtpp_strings[lrep_sets], p, len);
287
+    rtpp_strings[lrep_sets][len] = '\0';
288
+    lrep_sets++;
289
+
290
+    return 0;
291
+}
292
+
293
+struct lrep_set *get_lrep_set(str *const set_name)
294
+{
295
+    unsigned int this_set_id;
296
+    struct lrep_set *lrep_list;
297
+    if (lrep_set_list == NULL)
298
+    {
299
+                LM_ERR("rtpp set list not configured\n");
300
+        return NULL;
301
+    }
302
+    /* Only integer set_names are valid at the moment */
303
+    if ((set_name->s == NULL) || (set_name->len == 0))
304
+    {
305
+                LM_ERR("Invalid set name '%.*s'\n", set_name->len, set_name->s);
306
+        return NULL;
307
+    }
308
+    if (str2int(set_name, &this_set_id) < 0)
309
+    {
310
+                LM_ERR("Invalid set name '%.*s' - must be integer\n", set_name->len, set_name->s);
311
+        return NULL;
312
+    }
313
+
314
+    lrep_list = select_lrep_set(this_set_id);
315
+
316
+    if(lrep_list==NULL){	/*if a new id_set : add a new set of rtpp*/
317
+        lrep_list = shm_malloc(sizeof(struct lrep_set));
318
+        if(!lrep_list){
319
+                    LM_ERR("no shm memory left\n");
320
+            return NULL;
321
+        }
322
+        memset(lrep_list, 0, sizeof(struct lrep_set));
323
+        lrep_list->id_set = this_set_id;
324
+        if (lrep_set_list->lset_first == NULL)
325
+        {
326
+            lrep_set_list->lset_first = lrep_list;
327
+        } else {
328
+            lrep_set_list->lset_last->lset_next = lrep_list;
329
+        }
330
+        lrep_set_list->lset_last = lrep_list;
331
+        lrep_set_count++;
332
+
333
+        if (this_set_id == DEFAULT_LREP_SET_ID)
334
+        {
335
+            default_lrep_set = lrep_list;
336
+        }
337
+    }
338
+    return lrep_list;
339
+}
340
+
341
+int insert_lrep_node(struct lrep_set *const lrep_list, const str *const url, const int weight, const int enable)
342
+{
343
+    struct lrep_node *pnode;
344
+
345
+    if ((pnode = shm_malloc(sizeof(struct lrep_node) + url->len + 1)) == NULL)
346
+    {
347
+                LM_ERR("out of shm memory\n");
348
+        return -1;
349
+    }
350
+
351
+    memset(pnode, 0, sizeof(struct lrep_node) + url->len + 1);
352
+
353
+
354
+    struct lrep_node_conf *node_conf;
355
+    node_conf = shm_malloc(sizeof(struct lrep_node_conf));
356
+    if (!node_conf)
357
+    {
358
+                LM_ERR("out of shm memory\n");
359
+        return -1;
360
+    }
361
+
362
+    memset(node_conf, 0, sizeof(struct lrep_node_conf));
363
+    pnode->lrep_n_c = node_conf;
364
+
365
+    pnode->idx = rtpp_no++;
366
+    pnode->ln_weight = weight;
367
+    pnode->ln_umode = 0;
368
+    pnode->ln_enable = enable;
369
+    /* Permanently disable if marked as disabled */
370
+//    pnode->ln_recheck_ticks = disabled ? RPC_MAX_RECHECK_TICKS : 0;
371
+    pnode->ln_url.s = (char*)(pnode + 1);
372
+    memcpy(pnode->ln_url.s, url->s, url->len);
373
+    pnode->ln_url.len = url->len;
374
+
375
+            LM_DBG("url is '%.*s'\n", pnode->ln_url.len, pnode->ln_url.s);
376
+
377
+    /* Find protocol and store address */
378
+    pnode->ln_address = pnode->ln_url.s;
379
+    if (strncasecmp(pnode->ln_address, "udp:", 4) == 0) {
380
+        pnode->ln_umode = 1;
381
+        pnode->ln_address += 4;
382
+    } else if (strncasecmp(pnode->ln_address, "udp6:", 5) == 0) {
383
+        pnode->ln_umode = 6;
384
+        pnode->ln_address += 5;
385
+    } else if (strncasecmp(pnode->ln_address, "unix:", 5) == 0) {
386
+        pnode->ln_umode = 0;
387
+        pnode->ln_address += 5;
388
+    }
389
+
390
+    if (lrep_list->ln_first == NULL)
391
+    {
392
+        lrep_list->ln_first = pnode;
393
+    } else {
394
+        lrep_list->ln_last->ln_next = pnode;
395
+    }
396
+    lrep_list->ln_last = pnode;
397
+    lrep_list->lrep_node_count++;
398
+
399
+    return 0;
400
+}
401
+
402
+static int add_lreproxy_socks(struct lrep_set * lrep_list,
403
+                              char * rtpproxy){
404
+    /* Make rtp proxies list. */
405
+    char *p, *p1, *p2, *plim;
406
+    int weight;
407
+    str url;
408
+
409
+    p = rtpproxy;
410
+    plim = p + strlen(p);
411
+
412
+    for(;;) {
413
+        weight = 1;
414
+        while (*p && isspace((int)*p))
415
+            ++p;
416
+        if (p >= plim)
417
+            break;
418
+        p1 = p;
419
+        while (*p && !isspace((int)*p))
420
+            ++p;
421
+        if (p <= p1)
422
+            break; /* may happen??? */
423
+        /* Have weight specified? If yes, scan it */
424
+        p2 = memchr(p1, '=', p - p1);
425
+        if (p2 != NULL) {
426
+            weight = strtoul(p2 + 1, NULL, 10);
427
+        } else {
428
+            p2 = p;
429
+        }
430
+
431
+        url.s = p1;
432
+        url.len = (p2-p1);
433
+        insert_lrep_node(lrep_list, &url, weight, 0);
434
+    }
435
+    return 0;
436
+}
437
+
438
+/*	0-succes
439
+ *  -1 - erorr
440
+ * */
441
+static int lreproxy_add_lreproxy_set( char * lre_proxies)
442
+{
443
+    char *p,*p2;
444
+    struct lrep_set * lrep_list;
445
+    str id_set;
446
+
447
+    /* empty definition? */
448
+    p= lre_proxies;
449
+    if(!p || *p=='\0'){
450
+        return 0;
451
+    }
452
+
453
+    for(;*p && isspace(*p);p++);
454
+    if(*p=='\0'){
455
+        return 0;
456
+    }
457
+
458
+    lre_proxies = strstr(p, "==");
459
+    if(lre_proxies){
460
+        if(*(lre_proxies +2)=='\0'){
461
+                    LM_ERR("script error -invalid rtp proxy list!\n");
462
+            return -1;
463
+        }
464
+
465
+        *lre_proxies = '\0';
466
+        p2 = lre_proxies-1;
467
+        for(;isspace(*p2); *p2 = '\0',p2--);
468
+        id_set.s = p;	id_set.len = p2 - p+1;
469
+
470
+        if(id_set.len <= 0){
471
+                    LM_ERR("script error -invalid set_id value!\n");
472
+            return -1;
473
+        }
474
+
475
+        lre_proxies+=2;
476
+    }else{
477
+        lre_proxies = p;
478
+        id_set = DEFAULT_LREP_SET_ID_STR;
479
+    }
480
+
481
+    for(;*lre_proxies && isspace(*lre_proxies);lre_proxies++);
482
+
483
+    if(!(*lre_proxies)){
484
+                LM_ERR("script error -empty rtp_proxy list\n");
485
+        return -1;;
486
+    }
487
+
488
+    lrep_list = get_lrep_set(&id_set);
489
+    if (lrep_list == NULL)
490
+    {
491
+                LM_ERR("Failed to get or create lrep_list for '%.*s'\n", id_set.len, id_set.s);
492
+        return -1;
493
+    }
494
+
495
+    if(add_lreproxy_socks(lrep_list, lre_proxies)!= 0){
496
+        return -1;
497
+    }
498
+
499
+    return 0;
500
+}
501
+
502
+
503
+static int fixup_set_id(void ** param, int param_no)
504
+{
505
+	int int_val, err;
506
+	struct lrep_set* lrep_list;
507
+	lrep_set_link_t *rtpl = NULL;
508
+	str s;
509
+
510
+	rtpl = (lrep_set_link_t*)pkg_malloc(sizeof(lrep_set_link_t));
511
+	if(rtpl==NULL) {
512
+		LM_ERR("no more pkg memory\n");
513
+		return -1;
514
+	}
515
+	memset(rtpl, 0, sizeof(lrep_set_link_t));
516
+	s.s = (char*)*param;
517
+	s.len = strlen(s.s);
518
+
519
+	if(s.s[0] == PV_MARKER) {
520
+		int_val = pv_locate_name(&s);
521
+		if(int_val<0 || int_val!=s.len) {
522
+			LM_ERR("invalid parameter %s\n", s.s);
523
+			pkg_free(rtpl);
524
+			return -1;
525
+		}
526
+		rtpl->rpv = pv_cache_get(&s);
527
+		if(rtpl->rpv == NULL) {
528
+			LM_ERR("invalid pv parameter %s\n", s.s);
529
+			pkg_free(rtpl);
530
+			return -1;
531
+		}
532
+	} else {
533
+		int_val = str2s(*param, strlen(*param), &err);
534
+		if (err == 0) {
535
+			pkg_free(*param);
536
+			if((lrep_list = select_lrep_set(int_val)) ==0){
537
+				LM_ERR("lrep_proxy set %i not configured\n", int_val);
538
+				pkg_free(rtpl);
539
+				return E_CFG;
540
+			}
541
+			rtpl->rset = lrep_list;
542
+		} else {
543
+			LM_ERR("bad number <%s>\n",	(char *)(*param));
544
+			pkg_free(rtpl);
545
+			return E_CFG;
546
+		}
547
+	}
548
+	*param = (void*)rtpl;
549
+	return 0;
550
+}
551
+
552
+
553
+static int
554
+mod_init(void)
555
+{
556
+    int i;
557
+//	pv_spec_t avp_spec;
558
+//	str s;
559
+//	unsigned short avp_flags;
560
+
561
+//	if(rtpproxy_rpc_init()<0)
562
+//	{
563
+//		LM_ERR("failed to register RPC commands\n");
564
+//		return -1;
565
+//	}
566
+
567
+    /* Configure the head of the lrep_set_list */
568
+    lrep_set_list = shm_malloc(sizeof(struct lrep_set_head));
569
+    if (lrep_set_list == NULL)
570
+    {
571
+                LM_ERR("no shm memory for lrep_set_list\n");
572
+        return -1;
573
+    }
574
+    memset(lrep_set_list, 0, sizeof(struct lrep_set_head));
575
+
576
+
577
+    /* storing the list of rtp proxy sets in shared memory*/
578
+    for(i=0;i<lrep_sets;i++){
579
+                LM_DBG("Adding RTP-Proxy set %d/%d: %s\n", i, lrep_sets, rtpp_strings[i]);
580
+//        if ((rtpp_db_url.s == NULL) &&
581
+        if (lreproxy_add_lreproxy_set(rtpp_strings[i]) != 0) {
582
+            for(;i<lrep_sets;i++)
583
+                if(rtpp_strings[i])
584
+                    pkg_free(rtpp_strings[i]);
585
+            pkg_free(rtpp_strings);
586
+                    LM_ERR("Failed to add RTP-Proxy from Config!\n");
587
+            return -1;
588
+        }
589
+        if(rtpp_strings[i])
590
+            pkg_free(rtpp_strings[i]);
591
+    }
592
+
593
+
594
+    if (rtpp_strings)
595
+        pkg_free(rtpp_strings);
596
+
597
+
598
+    /* init the hastable which keeps the all media address for both party and also the elected_node <--> callid& via-branch relation */
599
+    if (hash_table_size < 1){
600
+        hash_table_size = HASH_SIZE;    //the default size 128 entry.
601
+    }
602
+
603
+    if (!lreproxy_hash_table_init(hash_table_size)) {
604
+                LM_ERR("lreproxy_hash_table_init(%d) failed!\n", hash_table_size);
605
+        return -1;
606
+    } else {
607
+//                LM_DBG("rtpengine_hash_table_init(%d) success!\n", hash_table_size);
608
+                LM_INFO(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>lreproxy_hash_table_init(%d) success!\n", hash_table_size);
609
+    }
610
+
611
+
612
+
613
+    /* load tm module*/
614
+    if (load_tm_api( &tmb ) < 0)
615
+    {
616
+                LM_DBG("could not load the TM-functions - answer-offer model"
617
+                               " auto-detection is disabled\n");
618
+        memset(&tmb, 0, sizeof(struct tm_binds));
619
+    }
620
+
621
+    return 0;
622
+}
623
+
624
+
625
+static int
626
+child_init(int rank)
627
+{
628
+    int n;
629
+    char *cp;
630
+    struct addrinfo hints, *res;
631
+    struct lrep_set  *lrep_list;
632
+    struct lrep_node *pnode;
633
+
634
+    if(lrep_set_list==NULL )
635
+        return 0;
636
+
637
+    /* do not init sockets for PROC_INIT and main process when fork=yes */
638
+    if(rank==PROC_INIT || (rank==PROC_MAIN && dont_fork==0)) {
639
+        return 0;
640
+    }
641
+
642
+    /* Iterate known RTP proxies - create sockets */
643
+    mypid = getpid();
644
+
645
+    rtpp_socks = (int*)pkg_malloc( sizeof(int)*rtpp_no );
646
+    if (rtpp_socks==NULL) {
647
+                LM_ERR("no more pkg memory\n");
648
+        return -1;
649
+    }
650
+    memset(rtpp_socks, -1, sizeof(int)*rtpp_no);
651
+
652
+    for(lrep_list = lrep_set_list->lset_first; lrep_list != 0;
653
+        lrep_list = lrep_list->lset_next){
654
+
655
+        for (pnode=lrep_list->ln_first; pnode!=0; pnode = pnode->ln_next){
656
+            char *hostname;
657
+
658
+            if (pnode->ln_umode == 0) {
659
+                rtpp_socks[pnode->idx] = -1;
660
+                goto rptest;
661
+            }
662
+
663
+            /*
664
+             * This is UDP or UDP6. Detect host and port; lookup host;
665
+             * do connect() in order to specify peer address
666
+             */
667
+            hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->ln_address) + 1));
668
+            if (hostname==NULL) {
669
+                        LM_ERR("no more pkg memory\n");
670
+                return -1;
671
+            }
672
+            strcpy(hostname, pnode->ln_address);
673
+
674
+            cp = strrchr(hostname, ':');
675
+            if (cp != NULL) {
676
+                *cp = '\0';
677
+                cp++;
678
+            }
679
+            if (cp == NULL || *cp == '\0')
680
+                cp = CPORT;
681
+
682
+            memset(&hints, 0, sizeof(hints));
683
+            hints.ai_flags = 0;
684
+            hints.ai_family = (pnode->ln_umode == 6) ? AF_INET6 : AF_INET;
685
+            hints.ai_socktype = SOCK_DGRAM;
686
+            if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
687
+                        LM_ERR("%s\n", gai_strerror(n));
688
+                pkg_free(hostname);
689
+                return -1;
690
+            }
691
+            pkg_free(hostname);
692
+
693
+            rtpp_socks[pnode->idx] = socket((pnode->ln_umode == 6)
694
+                                            ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
695
+            if ( rtpp_socks[pnode->idx] == -1) {
696
+                        LM_ERR("can't create socket\n");
697
+                freeaddrinfo(res);
698
+                return -1;
699
+            }
700
+
701
+            if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
702
+                        LM_ERR("can't connect to a RTP proxy\n");
703
+                close( rtpp_socks[pnode->idx] );
704
+                rtpp_socks[pnode->idx] = -1;
705
+                freeaddrinfo(res);
706
+                return -1;
707
+            }
708
+            freeaddrinfo(res);
709
+rptest:
710
+            pnode->ln_enable = lrep_test(pnode);
711
+            if (pnode->ln_enable) {       //get lre proxy config if it is enable.
712
+//                LM_INFO("lrep_test test is calling here\n"); //enable next line.
713
+                lrep_get_config(pnode);
714
+            }
715
+        }
716
+    }
717
+
718
+    return 0;
719
+}
720
+
721
+
722
+static void mod_destroy(void)
723
+{
724
+    struct lrep_set * crt_list, * last_list;
725
+    struct lrep_node * crt_rtpp, *last_rtpp;
726
+
727
+    /*free the shared memory*/
728
+//	if (natping_state)
729
+//		shm_free(natping_state);
730
+
731
+    if(lrep_set_list == NULL)
732
+        return;
733
+
734
+    for(crt_list = lrep_set_list->lset_first; crt_list != NULL; ){
735
+
736
+        for(crt_rtpp = crt_list->ln_first; crt_rtpp != NULL;  ){
737
+
738
+            last_rtpp = crt_rtpp;
739
+            crt_rtpp = last_rtpp->ln_next;
740
+            shm_free(last_rtpp);
741
+        }
742
+
743
+        last_list = crt_list;
744
+        crt_list = last_list->lset_next;
745
+        shm_free(last_list);
746
+    }
747
+
748
+    shm_free(lrep_set_list);
749
+
750
+    /* destroy the hash table */
751
+    if (!lreproxy_hash_table_destroy()) {
752
+                LM_ERR("rtpengine_hash_table_destroy() failed!\n");
753
+    } else {
754
+                LM_DBG("rtpengine_hash_table_destroy() success!\n");
755
+    }
756
+
757
+}
758
+
759
+
760
+static char * gencookie(void)
761
+{
762
+    static char cook[34];
763
+
764
+    sprintf(cook, "%d_%u ", (int)mypid, myseqn);
765
+    myseqn++;
766
+    return cook;
767
+}
768
+
769
+static int lrep_test(struct lrep_node *node)
770
+{
771
+    int buflen = 256;
772
+    char buf[buflen];
773
+    struct iovec v[2] = {{NULL, 0}, {"P", 1}};
774
+
775
+    memset(buf, 0, buflen);
776
+    memcpy(buf, send_lrep_command(node, v, 2, 0), buflen);
777
+
778
+//    if (buf == NULL) {
779
+    if (!buf[0]) {
780
+        LM_ERR("can't ping the lre proxy %s, Disable it right now.\n", node->ln_url.s);
781
+        return 0;
782
+    }
783
+
784
+    char *resp = buf + v[0].iov_len + v[1].iov_len + 1;
785
+    if (memcmp(resp, "PONG", 4) == 0)
786
+//                LM_DBG("Recieve PONG response from lre proxy server %s, Enable it right now.\n", node->ln_url.s);
787
+            LM_INFO("Recieve PONG response from lre proxy server %s, Enable it right now.\n", node->ln_url.s);
788
+
789
+    return 1;
790
+
791
+}
792
+
793
+static int lrep_get_config(struct lrep_node *node){
794
+
795
+    int buflen = 256;
796
+    char buf[buflen];
797
+    struct iovec v[2] = {{NULL, 0}, {"G", 1}};
798
+    struct lrep_node_conf *lnconf = NULL;
799
+
800
+    memset(buf, 0, buflen);
801
+    memcpy(buf, send_lrep_command(node, v, 2, 0), buflen);
802
+
803
+//    if (buf == NULL) {
804
+    if (!buf[0]) {
805
+        LM_ERR("can't get config of the lre proxy %s, Disable it right now.\n", node->ln_url.s);
806
+        return 0;
807
+    }
808
+
809
+    lnconf = (struct lrep_node_conf *)(buf + v[0].iov_len + v[1].iov_len + 1);
810
+
811
+    if (lnconf == NULL){
812
+        LM_ERR("can't get config of the lre proxy %s, Disable it right now.\n", node->ln_url.s);
813
+        return 0;
814
+    }
815
+
816
+
817
+    memcpy(node->lrep_n_c, lnconf, sizeof(struct lrep_node_conf));
818
+
819
+//    node->lrep_n_c = lnconf;
820
+    LM_INFO("the lre proxy %s is configured successfully right now.\n", node->ln_url.s);
821
+    LM_INFO("buffer internal:%s\n", node->lrep_n_c->internal_ip);
822
+    LM_INFO("buffer external:%s\n", node->lrep_n_c->external_ip);
823
+    LM_INFO("buffer start_port:%d\n", node->lrep_n_c->start_port);
824
+    LM_INFO("buffer end_port:%d\n", node->lrep_n_c->end_port);
825
+    LM_INFO("buffer current_port:%d\n", node->lrep_n_c->current_port);
826
+
827
+    return 1;
828
+
829
+
830
+}
831
+
832
+static int lrep_set_conntrack_rule(struct lreproxy_hash_entry *e) {
833
+    int buflen = 254;
834
+    char buf[buflen];
835
+    int v_len = 0;
836
+
837
+    char src_ipv4[20];
838
+    char src_port[20];
839
+    char dst_ipv4[20];
840
+    char dst_port[20];
841
+    char snat_ipv4[20];
842
+    char snat_port[20];
843
+    char dnat_ipv4[20];
844
+    char dnat_port[20];
845
+    char timeout[20];
846
+    char callid[50];
847
+
848
+    struct iovec v[] = {
849
+            {NULL, 0},  /* reserved (cookie) */
850
+            {"S",  1},   /* command & common options */
851
+            {NULL, 0},  /* src_ipv4 */
852
+            {NULL, 0},  /* dst_ipnv4 */
853
+            {NULL, 0},  /* snat_ipv4 */
854
+            {NULL, 0},  /* dnat_ipv4 */
855
+            {NULL, 0},  /* src_port */
856
+            {NULL, 0},  /* dst_port*/
857
+            {NULL, 0},  /* snat_port */
858
+            {NULL, 0},  /* dnat_port*/
859
+            {NULL, 0},  /* timeout to clear conntrack entry*/
860
+            {NULL, 0},  /* callid of session */
861
+    };
862
+
863
+    v_len += v[1].iov_len;
864
+
865
+    //set src_ipv4 to buffer.
866
+    sprintf(src_ipv4, " %.*s ", e->src_ipv4.len, e->src_ipv4.s);
867
+    v[2].iov_base = src_ipv4;
868
+    v[2].iov_len = strlen(v[2].iov_base);
869
+    v_len += v[2].iov_len;
870
+
871
+    //set dst_ipv4 to buffer.
872
+    sprintf(dst_ipv4, "%.*s ", e->dst_ipv4.len, e->dst_ipv4.s);
873
+    v[3].iov_base = dst_ipv4;
874
+    v[3].iov_len = strlen(v[3].iov_base);
875
+    v_len += v[3].iov_len;
876
+
877
+    //set snat_ipv4 to buffer.
878
+    sprintf(snat_ipv4, "%.*s ", e->snat_ipv4.len, e->snat_ipv4.s);
879
+    v[4].iov_base = snat_ipv4;
880
+    v[4].iov_len = strlen(v[4].iov_base);
881
+    v_len += v[4].iov_len;
882
+
883
+    //set dnat_ipv4 to buffer.
884
+    sprintf(dnat_ipv4, "%.*s ", e->dnat_ipv4.len, e->dnat_ipv4.s);
885
+    v[5].iov_base = dnat_ipv4;
886
+    v[5].iov_len = strlen(v[5].iov_base);
887
+    v_len += v[5].iov_len;
888
+
889
+    //set src_port to buffer.
890
+    sprintf(src_port, "%.*s ", e->src_port.len, e->src_port.s);
891
+    v[6].iov_base = src_port;
892
+    v[6].iov_len = strlen(v[6].iov_base);
893
+    v_len += v[6].iov_len;
894
+
895
+    //set dst_port to buffer.
896
+    sprintf(dst_port, "%.*s ", e->dst_port.len, e->dst_port.s);
897
+    v[7].iov_base = dst_port;
898
+    v[7].iov_len = strlen(v[7].iov_base);
899
+    v_len += v[7].iov_len;
900
+
901
+    //set snat_port to buffer.
902
+    sprintf(snat_port, "%.*s ", e->snat_port.len, e->snat_port.s);
903
+    v[8].iov_base = snat_port;
904
+    v[8].iov_len = strlen(v[8].iov_base);
905
+    v_len += v[8].iov_len;
906
+
907
+    //set dnat_port to buffer.
908
+    sprintf(dnat_port, "%.*s ", e->dnat_port.len, e->dnat_port.s);
909
+    v[9].iov_base = dnat_port;
910
+    v[9].iov_len = strlen(v[9].iov_base);
911
+    v_len += v[9].iov_len;
912
+
913
+    //set timeout to buffer. Set to 60 sec for default.
914
+    sprintf(timeout, "%d ", 60);
915
+    v[10].iov_base = timeout;
916
+    v[10].iov_len = strlen(v[10].iov_base);
917
+    v_len += v[10].iov_len;
918
+
919
+    //set callid to buffer.
920
+    sprintf(callid, "%.*s ", e->callid.len, e->callid.s);
921
+    v[11].iov_base = callid;
922
+    v[11].iov_len = strlen(v[11].iov_base);
923
+    v_len += v[11].iov_len;
924
+//    LM_ERR("e->callid.len is:%d right now.\n\n", e->callid.len);
925
+
926
+    memset(buf, 0, buflen);
927
+    memcpy(buf, send_lrep_command(e->node, v, 12, v_len), buflen);
928
+//
929
+
930
+//    if (buf == NULL) {
931
+    if (!buf[0]) {
932
+                LM_ERR("can't ping the lre proxy %s, Disable it right now.\n", e->node->ln_url.s);
933
+        return 0;
934
+    }
935
+
936
+    v_len += v[0].iov_len;
937
+
938
+
939
+//    char *resp = buf + v[0].iov_len + v[1].iov_len + v[2].iov_len;
940
+    char *resp = buf + v_len;
941
+    if (memcmp(resp, "OK", 2) == 0) {
942
+                LM_INFO("Recieve OK response from lre proxy server %s, Rule set successfully.\n", e->node->ln_url.s);
943
+                LM_DBG("Recieve OK response from lre proxy server %s, Rule set successfully.\n", e->node->ln_url.s);
944
+    }
945
+    return 1;
946
+
947
+}
948
+
949
+
950
+char *send_lrep_command(struct lrep_node *node, struct iovec *v, int vcnt, int more)
951
+{
952
+    struct sockaddr_un addr;
953
+    int fd, len, i;
954
+//    char *cp;
955
+    static char buf[256];
956
+    struct pollfd fds[1];
957
+
958
+    memset(buf, 0, 256);
959
+    len = 0;
960
+//    cp = buf;
961
+    if (node->ln_umode == 0) {
962
+        memset(&addr, 0, sizeof(addr));
963
+        addr.sun_family = AF_LOCAL;
964
+        strncpy(addr.sun_path, node->ln_address,
965
+                sizeof(addr.sun_path) - 1);
966
+#ifdef HAVE_SOCKADDR_SA_LEN
967
+        addr.sun_len = strlen(addr.sun_path);
968
+#endif
969
+
970
+        fd = socket(AF_LOCAL, SOCK_STREAM, 0);
971
+        if (fd < 0) {
972
+                    LM_ERR("can't create socket\n");
973
+            goto badproxy;
974
+        }
975
+        if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
976
+            close(fd);
977
+                    LM_ERR("can't connect to lre proxy\n");
978
+            goto badproxy;
979
+        }
980
+
981
+        do {
982
+            len = writev(fd, v + 1, vcnt - 1);
983
+        } while (len == -1 && errno == EINTR);
984
+        if (len <= 0) {
985
+            close(fd);
986
+                    LM_ERR("can't send command to a lre proxy %s\n", node->ln_url.s);
987
+            goto badproxy;
988
+        }
989
+        do {
990
+            len = read(fd, buf, sizeof(buf) - 1);
991
+        } while (len == -1 && errno == EINTR);
992
+        close(fd);
993
+        if (len <= 0) {
994
+                    LM_ERR("can't read reply from a lre proxy %s\n", node->ln_url.s);
995
+            goto badproxy;
996
+        }
997
+    } else {
998
+        fds[0].fd = rtpp_socks[node->idx];
999
+        fds[0].events = POLLIN;
1000
+        fds[0].revents = 0;
1001
+        /* Drain input buffer */
1002
+        while ((poll(fds, 1, 0) == 1) &&
1003
+               ((fds[0].revents & POLLIN) != 0)) {
1004
+            recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
1005
+            fds[0].revents = 0;
1006
+        }
1007
+        v[0].iov_base = gencookie();
1008
+        v[0].iov_len = strlen(v[0].iov_base);
1009
+        for (i = 0; i < lreproxy_retr; i++) {
1010
+            do {
1011
+                len = writev(rtpp_socks[node->idx], v, vcnt);
1012
+            } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
1013
+            if (len <= 0) {
1014
+                        LM_ERR("can't send command to a lre proxy %s\n", node->ln_url.s);
1015
+                goto badproxy;
1016
+            }
1017
+            while ((poll(fds, 1, lreproxy_tout * 1000) == 1) &&
1018
+                   (fds[0].revents & POLLIN) != 0) {
1019
+                do {
1020
+                    len = recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
1021
+                } while (len == -1 && errno == EINTR);
1022
+                if (len <= 0) {
1023
+                            LM_ERR("can't read reply from a lre proxy %s\n", node->ln_url.s);
1024
+                    goto badproxy;
1025
+                }
1026
+                if (len >= (v[0].iov_len - 1) &&
1027
+                    memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {      //check coocke validation.
1028
+                    char *command = buf + v[0].iov_len;
1029
+                    switch (*command) {
1030
+                        case 'P':
1031
+                            if (len == v[0].iov_len + v[1].iov_len + 4 + 1)
1032
+                                goto out;
1033
+//                            break;
1034
+                        case 'G':
1035
+                            if (len == v[0].iov_len + v[1].iov_len + sizeof(struct lrep_node_conf) + 1)
1036
+                                goto out;
1037
+//                            break;
1038
+                        case 'S':
1039
+                            if (len == more + v[0].iov_len + 2)
1040
+                                goto out;
1041
+//                            break;
1042
+                    }
1043
+
1044
+                }
1045
+                fds[0].revents = 0;
1046
+            }
1047
+        }