Browse code

Merge 15fd09bb5e4d49bb9d61ee067a17e87fc9bf4abb into e676498f4d0a46ae81e4e07e56ff64c97a075faf

mojtabaesfandiari authored on 20/10/2020 11:52:14 • GitHub committed on 20/10/2020 11:52:14
Showing 7 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+lreproxy
0 2
new file mode 100644
... ...
@@ -0,0 +1,1976 @@
1
+/*
2
+ * Copyright (C) 2019-2020 Mojtaba Esfandiari.S, Nasim-Telecom
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * Kamailio 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
+ * Kamailio 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
+#include <sys/types.h>
23
+#include <sys/socket.h>
24
+#include <sys/time.h>
25
+#include <netinet/in.h>
26
+#include <netinet/in_systm.h>
27
+#ifndef __USE_BSD
28
+#define  __USE_BSD
29
+#endif
30
+#include <netinet/ip.h>
31
+#ifndef __FAVOR_BSD
32
+#define __FAVOR_BSD
33
+#endif
34
+#include <netinet/udp.h>
35
+#include <arpa/inet.h>
36
+#include <sys/uio.h>
37
+#include <sys/un.h>
38
+#include <ctype.h>
39
+#include <errno.h>
40
+#include <netdb.h>
41
+#include <poll.h>
42
+#include <stdio.h>
43
+#include <stdlib.h>
44
+#include <string.h>
45
+#include <unistd.h>
46
+
47
+#include "../../core/flags.h"
48
+#include "../../core/sr_module.h"
49
+#include "../../core/dprint.h"
50
+#include "../../core/data_lump.h"
51
+#include "../../core/data_lump_rpl.h"
52
+#include "../../core/error.h"
53
+#include "../../core/forward.h"
54
+#include "../../core/mem/mem.h"
55
+#include "../../core/parser/parse_from.h"
56
+#include "../../core/parser/parse_to.h"
57
+#include "../../core/parser/parse_uri.h"
58
+#include "../../core/parser/parser_f.h"
59
+#include "../../core/parser/sdp/sdp.h"
60
+#include "../../core/resolve.h"
61
+#include "../../core/timer.h"
62
+#include "../../core/trim.h"
63
+#include "../../core/ut.h"
64
+#include "../../core/pt.h"
65
+#include "../../core/timer_proc.h"
66
+#include "../../core/rpc.h"
67
+#include "../../core/rpc_lookup.h"
68
+#include "../../core/pvar.h"
69
+#include "../../core/lvalue.h"
70
+#include "../../core/msg_translator.h"
71
+#include "../../core/usr_avp.h"
72
+#include "../../core/socket_info.h"
73
+#include "../../core/mod_fix.h"
74
+#include "../../core/dset.h"
75
+#include "../../core/route.h"
76
+#include "../../core/kemi.h"
77
+#include "../../modules/tm/tm_load.h"
78
+#include "lreproxy.h"
79
+#include "lreproxy_hash.h"
80
+#include "lreproxy_funcs.h"
81
+//#include "rtpproxy_stream.h"
82
+
83
+MODULE_VERSION
84
+
85
+
86
+#if !defined(AF_LOCAL)
87
+#define	AF_LOCAL AF_UNIX
88
+#endif
89
+#if !defined(PF_LOCAL)
90
+#define	PF_LOCAL PF_UNIX
91
+#endif
92
+
93
+///* NAT UAC test constants */
94
+//#define	NAT_UAC_TEST_C_1918	0x01
95
+//#define	NAT_UAC_TEST_RCVD	0x02
96
+//#define	NAT_UAC_TEST_V_1918	0x04
97
+//#define	NAT_UAC_TEST_S_1918	0x08
98
+//#define	NAT_UAC_TEST_RPORT	0x10
99
+
100
+#define DEFAULT_LREP_SET_ID		0
101
+static str DEFAULT_LREP_SET_ID_STR = str_init("0");
102
+
103
+//#define RPC_DEFAULT_NATPING_STATE	1
104
+
105
+#define RPC_MIN_RECHECK_TICKS		0
106
+#define RPC_MAX_RECHECK_TICKS		(unsigned int)-1
107
+
108
+
109
+/* Supported version of the RTP proxy command protocol */
110
+#define	SUP_CPROTOVER	"20190708"
111
+/* Required additional version of the RTP proxy command protocol */
112
+#define	REQ_CPROTOVER	"20190709"
113
+/* Additional version necessary for re-packetization support */
114
+#define	REP_CPROTOVER	"20190708"
115
+#define	PTL_CPROTOVER	"20190708"
116
+
117
+#define	CPORT		"22333"
118
+#define HASH_SIZE   128
119
+//static int extract_mediaip(str *, str *, int *, char *);
120
+//static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);
121
+//static int alter_mediaport(struct sip_msg *, str *, str *, str *, int);
122
+//static int alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport);
123
+static char *gencookie();
124
+static int lrep_test(struct lrep_node*);
125
+static int lrep_get_config(struct lrep_node *node);
126
+static int lrep_set_conntrack_rule(struct lreproxy_hash_entry *e);
127
+
128
+//static int unforce_rtp_proxy1_f(struct sip_msg *, char *, char *);
129
+//static int unforce_rtp_proxy(struct sip_msg *, char *);
130
+//static int force_rtp_proxy(struct sip_msg *, char *, char *, int, int);
131
+//static int start_recording_f(struct sip_msg *, char *, char *);
132
+//static int lreproxy_answer1_f(struct sip_msg *, char *, char *);
133
+//static int lreproxy_answer2_f(struct sip_msg *, char *, char *);
134
+//static int lreproxy_offer1_f(struct sip_msg *, char *, char *);
135
+//static int lreproxy_offer2_f(struct sip_msg *, char *, char *);
136
+static int lreproxy_force(struct sip_msg *msg, const char *flags, enum lre_operation op, int more);
137
+static int lreproxy_unforce(struct sip_msg *msg, const char *flags, enum lre_operation op, int more);
138
+
139
+static int lreproxy_manage0(struct sip_msg *msg, char *flags, char *ip);
140
+static int lreproxy_manage1(struct sip_msg *msg, char *flags, char *ip);
141
+static int lreproxy_manage2(struct sip_msg *msg, char *flags, char *ip);
142
+//static int w_lre_manage(sip_msg_t *msg, char *flags);
143
+//static int lre_get_sdp_info(struct sip_msg *msg, lre_sdp_info_t *lre_sdp_info);
144
+//static int replace_body_total(sip_msg_t *msg, int port, char *flags, int type);
145
+//static int replace_body_total(sip_msg_t *msg, struct lrep_node *n, const char *flags, int type);
146
+//static int change_media_sdp(sip_msg_t *msg, struct lrep_node *n, const char *flags, int type);
147
+static int change_media_sdp(sip_msg_t *msg, struct lreproxy_hash_entry *e, const char *flags, enum lre_operation op);
148
+
149
+
150
+
151
+
152
+
153
+static int add_lreproxy_socks(struct lrep_set * lrep_list, char * rtpproxy);
154
+static int fixup_set_id(void ** param, int param_no);
155
+static int set_lre_proxy_set_f(struct sip_msg * msg, char * str1, char * str2);
156
+
157
+static struct lrep_set * select_lrep_set(int id_set);
158
+
159
+static int rtpproxy_set_store(modparam_t type, void * val);
160
+static int lreproxy_add_lreproxy_set( char * lre_proxies);
161
+
162
+static int mod_init(void);
163
+static int child_init(int);
164
+static void mod_destroy(void);
165
+
166
+/* Pseudo-Variables */
167
+//static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
168
+
169
+static int lreproxy_disable_tout = 60;
170
+static int lreproxy_retr = 5;
171
+static int lreproxy_tout = 1;
172
+static pid_t mypid;
173
+static unsigned int myseqn = 0;
174
+//static str nortpproxy_str = str_init("a=nortpproxy:yes");
175
+//static str extra_id_pv_param = {NULL, 0};
176
+
177
+static char ** rtpp_strings=0;
178
+static int lrep_sets=0; /*used in rtpproxy_set_store()*/
179
+static int lrep_set_count = 0;
180
+static unsigned int current_msg_id = (unsigned int)-1;
181
+/* RTP proxy balancing list */
182
+struct lrep_set_head * lrep_set_list =0;
183
+struct lrep_set * selected_lrep_set =0;
184
+struct lrep_set * default_lrep_set=0;
185
+struct lrep_node *selected_lrep_node = 0;
186
+int lrep_algorithm = LRE_LINER;
187
+static int hash_table_size = 0;
188
+static int hash_table_tout = 3600;
189
+
190
+
191
+
192
+//static char *ice_candidate_priority_avp_param = NULL;
193
+//static int ice_candidate_priority_avp_type;
194
+//static int_str ice_candidate_priority_avp;
195
+//static str rtp_inst_pv_param = {NULL, 0};
196
+//static pv_spec_t *rtp_inst_pvar = NULL;
197
+
198
+/* array with the sockets used by rtpproxy (per process)*/
199
+static unsigned int rtpp_no = 0;
200
+static int *rtpp_socks = 0;
201
+
202
+
203
+typedef struct lrep_set_link {
204
+	struct lrep_set *rset;
205
+	pv_spec_t *rpv;
206
+} lrep_set_link_t;
207
+
208
+/* tm */
209
+static struct tm_binds tmb;
210
+
211
+/*0-> disabled, 1 ->enabled*/
212
+//unsigned int *natping_state=0;
213
+
214
+static str timeout_socket_str = {0, 0};
215
+//static pv_elem_t *extra_id_pv = NULL;
216
+int start_port = 10000;
217
+int end_port = 20000;
218
+str internal_ip;
219
+str external_ip;
220
+
221
+static cmd_export_t cmds[] = {
222
+//        {"lreproxy_offer",	(cmd_function)lreproxy_offer1_f,     0,
223
+//                0, 0,
224
+//                ANY_ROUTE},
225
+//        {"lreproxy_offer",	(cmd_function)lreproxy_offer1_f,     1,
226
+//                fixup_spve_null, 0,
227
+//                ANY_ROUTE},
228
+//        {"lreproxy_offer",	(cmd_function)lreproxy_offer2_f,     2,
229
+//                fixup_spve_spve, 0,
230
+//                ANY_ROUTE},
231
+//        {"lreproxy_answer",	(cmd_function)lreproxy_answer1_f,    0,
232
+//                0, 0,
233
+//                ANY_ROUTE},
234
+//        {"lreproxy_answer",	(cmd_function)lreproxy_answer1_f,    1,
235
+//                fixup_spve_null, 0,
236
+//                ANY_ROUTE},
237
+//        {"lreproxy_answer",	(cmd_function)lreproxy_answer2_f,    2,
238
+//                fixup_spve_spve, 0,
239
+//                ANY_ROUTE},
240
+        {"set_lre_proxy_set",  (cmd_function)set_lre_proxy_set_f,    1,
241
+                fixup_set_id, 0,
242
+                ANY_ROUTE},
243
+        {"lreproxy_manage",	(cmd_function)lreproxy_manage0,     0,
244
+                                                       0, 0,
245
+                   ANY_ROUTE},
246
+        {"lreproxy_manage",	(cmd_function)lreproxy_manage1,     1,
247
+                                                       fixup_spve_null, fixup_free_spve_null,
248
+                   ANY_ROUTE},
249
+        {"lreproxy_manage",	(cmd_function)lreproxy_manage2,     2,
250
+                                                       fixup_spve_spve, fixup_free_spve_spve,
251
+                   ANY_ROUTE},
252
+//        {"lre_manage", (cmd_function) w_lre_manage, 0, 0,
253
+//                0, ANY_ROUTE},
254
+//        {"lre_manage", (cmd_function) w_lre_manage, 1, 0, 0,
255
+//                   ANY_ROUTE},
256
+        {0, 0, 0, 0, 0, 0}
257
+};
258
+
259
+static param_export_t params[] = {
260
+        {"lreproxy_sock",         PARAM_STRING|USE_FUNC_PARAM,
261
+                (void*)rtpproxy_set_store          },
262
+        {"lreproxy_disable_tout", INT_PARAM, &lreproxy_disable_tout },
263
+        {"lreproxy_retr",         INT_PARAM, &lreproxy_retr         },
264
+        {"lreproxy_tout",         INT_PARAM, &lreproxy_tout         },
265
+        {"timeout_socket",    	  PARAM_STR, &timeout_socket_str  },
266
+        {"lrep_alg",         INT_PARAM, &lrep_algorithm         },
267
+        {"hash_table_tout",       INT_PARAM, &hash_table_tout        },
268
+        {"hash_table_size",       INT_PARAM, &hash_table_size        },
269
+//    {"ht_name", STR_PARAM, &ht_name.s},
270
+//        {"start_port",             INT_PARAM, &start_port },
271
+//        {"end_port",             INT_PARAM, &end_port },
272
+//        {"internal_ip",         STR_PARAM, &internal_ip},
273
+//        {"external_ip",         STR_PARAM, &external_ip },
274
+
275
+        {0, 0, 0}
276
+};
277
+
278
+struct module_exports exports = {
279
+        "lreproxy",
280
+        DEFAULT_DLFLAGS, /* dlopen flags */
281
+        cmds,
282
+        params,
283
+        0,           /* exported statistics */
284
+        0,           /* exported MI functions */
285
+        0,     /* exported pseudo-variables */
286
+        0,           /* extra processes */
287
+        mod_init,
288
+        0,           /* reply processing */
289
+        mod_destroy, /* destroy function */
290
+        child_init
291
+};
292
+
293
+
294
+
295
+static int rtpproxy_set_store(modparam_t type, void * val){
296
+
297
+    char * p;
298
+    int len;
299
+
300
+    p = (char* )val;
301
+
302
+    if(p==0 || *p=='\0'){
303
+        return 0;
304
+    }
305
+
306
+    if(lrep_sets==0){
307
+        rtpp_strings = (char**)pkg_malloc(sizeof(char*));
308
+        if(!rtpp_strings){
309
+                    LM_ERR("no pkg memory left\n");
310
+            return -1;
311
+        }
312
+    } else {/*realloc to make room for the current set*/
313
+        rtpp_strings = (char**)pkg_reallocxf(rtpp_strings,
314
+                                             (lrep_sets+1)* sizeof(char*));
315
+        if(!rtpp_strings){
316
+                    LM_ERR("no pkg memory left\n");
317
+            return -1;
318
+        }
319
+    }
320
+
321
+    /*allocate for the current set of urls*/
322
+    len = strlen(p);
323
+    rtpp_strings[lrep_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
324
+
325
+    if(!rtpp_strings[lrep_sets]){
326
+                LM_ERR("no pkg memory left\n");
327
+        return -1;
328
+    }
329
+
330
+    memcpy(rtpp_strings[lrep_sets], p, len);
331
+    rtpp_strings[lrep_sets][len] = '\0';
332
+    lrep_sets++;
333
+
334
+    return 0;
335
+}
336
+
337
+struct lrep_set *get_lrep_set(str *const set_name)
338
+{
339
+    unsigned int this_set_id;
340
+    struct lrep_set *lrep_list;
341
+    if (lrep_set_list == NULL)
342
+    {
343
+                LM_ERR("rtpp set list not configured\n");
344
+        return NULL;
345
+    }
346
+    /* Only integer set_names are valid at the moment */
347
+    if ((set_name->s == NULL) || (set_name->len == 0))
348
+    {
349
+                LM_ERR("Invalid set name '%.*s'\n", set_name->len, set_name->s);
350
+        return NULL;
351
+    }
352
+    if (str2int(set_name, &this_set_id) < 0)
353
+    {
354
+                LM_ERR("Invalid set name '%.*s' - must be integer\n", set_name->len, set_name->s);
355
+        return NULL;
356
+    }
357
+
358
+    lrep_list = select_lrep_set(this_set_id);
359
+
360
+    if(lrep_list==NULL){	/*if a new id_set : add a new set of rtpp*/
361
+        lrep_list = shm_malloc(sizeof(struct lrep_set));
362
+        if(!lrep_list){
363
+                    LM_ERR("no shm memory left\n");
364
+            return NULL;
365
+        }
366
+        memset(lrep_list, 0, sizeof(struct lrep_set));
367
+        lrep_list->id_set = this_set_id;
368
+        if (lrep_set_list->lset_first == NULL)
369
+        {
370
+            lrep_set_list->lset_first = lrep_list;
371
+        } else {
372
+            lrep_set_list->lset_last->lset_next = lrep_list;
373
+        }
374
+        lrep_set_list->lset_last = lrep_list;
375
+        lrep_set_count++;
376
+
377
+        if (this_set_id == DEFAULT_LREP_SET_ID)
378
+        {
379
+            default_lrep_set = lrep_list;
380
+        }
381
+    }
382
+    return lrep_list;
383
+}
384
+
385
+int insert_lrep_node(struct lrep_set *const lrep_list, const str *const url, const int weight, const int enable)
386
+{
387
+    struct lrep_node *pnode;
388
+
389
+    if ((pnode = shm_malloc(sizeof(struct lrep_node) + url->len + 1)) == NULL)
390
+    {
391
+                LM_ERR("out of shm memory\n");
392
+        return -1;
393
+    }
394
+
395
+    memset(pnode, 0, sizeof(struct lrep_node) + url->len + 1);
396
+
397
+
398
+    struct lrep_node_conf *node_conf;
399
+    node_conf = shm_malloc(sizeof(struct lrep_node_conf));
400
+    if (!node_conf)
401
+    {
402
+                LM_ERR("out of shm memory\n");
403
+        return -1;
404
+    }
405
+
406
+    memset(node_conf, 0, sizeof(struct lrep_node_conf));
407
+    pnode->lrep_n_c = node_conf;
408
+
409
+    pnode->idx = rtpp_no++;
410
+    pnode->ln_weight = weight;
411
+    pnode->ln_umode = 0;
412
+    pnode->ln_enable = enable;
413
+    /* Permanently disable if marked as disabled */
414
+//    pnode->ln_recheck_ticks = disabled ? RPC_MAX_RECHECK_TICKS : 0;
415
+    pnode->ln_url.s = (char*)(pnode + 1);
416
+    memcpy(pnode->ln_url.s, url->s, url->len);
417
+    pnode->ln_url.len = url->len;
418
+
419
+            LM_DBG("url is '%.*s'\n", pnode->ln_url.len, pnode->ln_url.s);
420
+
421
+    /* Find protocol and store address */
422
+    pnode->ln_address = pnode->ln_url.s;
423
+    if (strncasecmp(pnode->ln_address, "udp:", 4) == 0) {
424
+        pnode->ln_umode = 1;
425
+        pnode->ln_address += 4;
426
+    } else if (strncasecmp(pnode->ln_address, "udp6:", 5) == 0) {
427
+        pnode->ln_umode = 6;
428
+        pnode->ln_address += 5;
429
+    } else if (strncasecmp(pnode->ln_address, "unix:", 5) == 0) {
430
+        pnode->ln_umode = 0;
431
+        pnode->ln_address += 5;
432
+    }
433
+
434
+    if (lrep_list->ln_first == NULL)
435
+    {
436
+        lrep_list->ln_first = pnode;
437
+    } else {
438
+        lrep_list->ln_last->ln_next = pnode;
439
+    }
440
+    lrep_list->ln_last = pnode;
441
+    lrep_list->lrep_node_count++;
442
+
443
+    return 0;
444
+}
445
+
446
+static int add_lreproxy_socks(struct lrep_set * lrep_list,
447
+                              char * rtpproxy){
448
+    /* Make rtp proxies list. */
449
+    char *p, *p1, *p2, *plim;
450
+    int weight;
451
+    str url;
452
+
453
+    p = rtpproxy;
454
+    plim = p + strlen(p);
455
+
456
+    for(;;) {
457
+        weight = 1;
458
+        while (*p && isspace((int)*p))
459
+            ++p;
460
+        if (p >= plim)
461
+            break;
462
+        p1 = p;
463
+        while (*p && !isspace((int)*p))
464
+            ++p;
465
+        if (p <= p1)
466
+            break; /* may happen??? */
467
+        /* Have weight specified? If yes, scan it */
468
+        p2 = memchr(p1, '=', p - p1);
469
+        if (p2 != NULL) {
470
+            weight = strtoul(p2 + 1, NULL, 10);
471
+        } else {
472
+            p2 = p;
473
+        }
474
+
475
+        url.s = p1;
476
+        url.len = (p2-p1);
477
+        insert_lrep_node(lrep_list, &url, weight, 0);
478
+    }
479
+    return 0;
480
+}
481
+
482
+/*	0-succes
483
+ *  -1 - erorr
484
+ * */
485
+static int lreproxy_add_lreproxy_set( char * lre_proxies)
486
+{
487
+    char *p,*p2;
488
+    struct lrep_set * lrep_list;
489
+    str id_set;
490
+
491
+    /* empty definition? */
492
+    p= lre_proxies;
493
+    if(!p || *p=='\0'){
494
+        return 0;
495
+    }
496
+
497
+    for(;*p && isspace(*p);p++);
498
+    if(*p=='\0'){
499
+        return 0;
500
+    }
501
+
502
+    lre_proxies = strstr(p, "==");
503
+    if(lre_proxies){
504
+        if(*(lre_proxies +2)=='\0'){
505
+                    LM_ERR("script error -invalid rtp proxy list!\n");
506
+            return -1;
507
+        }
508
+
509
+        *lre_proxies = '\0';
510
+        p2 = lre_proxies-1;
511
+        for(;isspace(*p2); *p2 = '\0',p2--);
512
+        id_set.s = p;	id_set.len = p2 - p+1;
513
+
514
+        if(id_set.len <= 0){
515
+                    LM_ERR("script error -invalid set_id value!\n");
516
+            return -1;
517
+        }
518
+
519
+        lre_proxies+=2;
520
+    }else{
521
+        lre_proxies = p;
522
+        id_set = DEFAULT_LREP_SET_ID_STR;
523
+    }
524
+
525
+    for(;*lre_proxies && isspace(*lre_proxies);lre_proxies++);
526
+
527
+    if(!(*lre_proxies)){
528
+                LM_ERR("script error -empty rtp_proxy list\n");
529
+        return -1;;
530
+    }
531
+
532
+    lrep_list = get_lrep_set(&id_set);
533
+    if (lrep_list == NULL)
534
+    {
535
+                LM_ERR("Failed to get or create lrep_list for '%.*s'\n", id_set.len, id_set.s);
536
+        return -1;
537
+    }
538
+
539
+    if(add_lreproxy_socks(lrep_list, lre_proxies)!= 0){
540
+        return -1;
541
+    }
542
+
543
+    return 0;
544
+}
545
+
546
+
547
+static int fixup_set_id(void ** param, int param_no)
548
+{
549
+	int int_val, err;
550
+	struct lrep_set* lrep_list;
551
+	lrep_set_link_t *rtpl = NULL;
552
+	str s;
553
+
554
+	rtpl = (lrep_set_link_t*)pkg_malloc(sizeof(lrep_set_link_t));
555
+	if(rtpl==NULL) {
556
+		LM_ERR("no more pkg memory\n");
557
+		return -1;
558
+	}
559
+	memset(rtpl, 0, sizeof(lrep_set_link_t));
560
+	s.s = (char*)*param;
561
+	s.len = strlen(s.s);
562
+
563
+	if(s.s[0] == PV_MARKER) {
564
+		int_val = pv_locate_name(&s);
565
+		if(int_val<0 || int_val!=s.len) {
566
+			LM_ERR("invalid parameter %s\n", s.s);
567
+			pkg_free(rtpl);
568
+			return -1;
569
+		}
570
+		rtpl->rpv = pv_cache_get(&s);
571
+		if(rtpl->rpv == NULL) {
572
+			LM_ERR("invalid pv parameter %s\n", s.s);
573
+			pkg_free(rtpl);
574
+			return -1;
575
+		}
576
+	} else {
577
+		int_val = str2s(*param, strlen(*param), &err);
578
+		if (err == 0) {
579
+			pkg_free(*param);
580
+			if((lrep_list = select_lrep_set(int_val)) ==0){
581
+				LM_ERR("lrep_proxy set %i not configured\n", int_val);
582
+				pkg_free(rtpl);
583
+				return E_CFG;
584
+			}
585
+			rtpl->rset = lrep_list;
586
+		} else {
587
+			LM_ERR("bad number <%s>\n",	(char *)(*param));
588
+			pkg_free(rtpl);
589
+			return E_CFG;
590
+		}
591
+	}
592
+	*param = (void*)rtpl;
593
+	return 0;
594
+}
595
+
596
+//static void  rtpproxy_rpc_enable(rpc_t* rpc, void* ctx)
597
+//{
598
+//	str rtpp_url;
599
+//	int enable;
600
+//	struct lrep_set *lrep_list;
601
+//	struct lrep_node *crt_rtpp;
602
+//	int found;
603
+//
604
+//	found = 0;
605
+//	enable = 0;
606
+//
607
+//	if(lrep_set_list ==NULL)
608
+//		goto end;
609
+//
610
+//	if (rpc->scan(ctx, "Sd", &rtpp_url, &enable) < 2) {
611
+//		rpc->fault(ctx, 500, "Not enough parameters");
612
+//		return;
613
+//	}
614
+//
615
+//	for(lrep_list = lrep_set_list->lset_first; lrep_list != NULL;
616
+//			lrep_list = lrep_list->lset_next) {
617
+//
618
+//		for(crt_rtpp = lrep_list->ln_first; crt_rtpp != NULL;
619
+//				crt_rtpp = crt_rtpp->ln_next) {
620
+//			/*found a matching rtpp*/
621
+//			if(crt_rtpp->ln_url.len == rtpp_url.len) {
622
+//
623
+//				if(strncmp(crt_rtpp->ln_url.s, rtpp_url.s, rtpp_url.len) == 0) {
624
+//					/*set the enabled/disabled status*/
625
+//					found = 1;
626
+//					crt_rtpp->ln_recheck_ticks =
627
+//						enable? RPC_MIN_RECHECK_TICKS : RPC_MAX_RECHECK_TICKS;
628
+//					crt_rtpp->ln_disabled = enable?0:1;
629
+//				}
630
+//			}
631
+//		}
632
+//	}
633
+//
634
+//end:
635
+//	if(!found) {
636
+//		rpc->fault(ctx, 404, "RTPProxy not found");
637
+//		return;
638
+//	}
639
+//}
640
+
641
+
642
+//static void  rtpproxy_rpc_list(rpc_t* rpc, void* ctx)
643
+//{
644
+//	struct lrep_set *lrep_list;
645
+//	struct lrep_node *crt_rtpp;
646
+//	void *vh;
647
+//
648
+//	if(lrep_set_list ==NULL)
649
+//		return;
650
+//
651
+//	for(lrep_list = lrep_set_list->lset_first; lrep_list != NULL;
652
+//			lrep_list = lrep_list->lset_next) {
653
+//
654
+//		for(crt_rtpp = lrep_list->ln_first; crt_rtpp != NULL;
655
+//				crt_rtpp = crt_rtpp->ln_next) {
656
+//
657
+//			if (rpc->add(ctx, "{", &vh) < 0) {
658
+//				rpc->fault(ctx, 500, "Server error");
659
+//				return;
660
+//			}
661
+//			rpc->struct_add(vh, "dSdddd",
662
+//				"setid", lrep_list->id_set,
663
+//				"url", &crt_rtpp->ln_url,
664
+//				"index", crt_rtpp->idx,
665
+//				"disabled", crt_rtpp->ln_disabled,
666
+//				"weight", crt_rtpp->ln_weight,
667
+//				"recheck", crt_rtpp->ln_recheck_ticks);
668
+//		}
669
+//	}
670
+//}
671
+//
672
+//static const char* rtpproxy_rpc_enable_doc[2] = {
673
+//	"Set state (enable/disable) for a rtp proxy.",
674
+//	0
675
+//};
676
+//
677
+//static const char* rtpproxy_rpc_list_doc[2] = {
678
+//	"List rtp proxies.",
679
+//	0
680
+//};
681
+//
682
+//rpc_export_t rtpproxy_rpc[] = {
683
+//	{"rtpproxy.list", rtpproxy_rpc_list, rtpproxy_rpc_list_doc, RET_ARRAY},
684
+//	{"rtpproxy.enable", rtpproxy_rpc_enable, rtpproxy_rpc_enable_doc, 0},
685
+//	{0, 0, 0, 0}
686
+//};
687
+
688
+//static int rtpproxy_rpc_init(void)
689
+//{
690
+//	if (rpc_register_array(rtpproxy_rpc)!=0)
691
+//	{
692
+//		LM_ERR("failed to register RPC commands\n");
693
+//		return -1;
694
+//	}
695
+//	return 0;
696
+//}
697
+
698
+static int
699
+mod_init(void)
700
+{
701
+    int i;
702
+//	pv_spec_t avp_spec;
703
+//	str s;
704
+//	unsigned short avp_flags;
705
+
706
+//	if(rtpproxy_rpc_init()<0)
707
+//	{
708
+//		LM_ERR("failed to register RPC commands\n");
709
+//		return -1;
710
+//	}
711
+
712
+    /* Configure the head of the lrep_set_list */
713
+    lrep_set_list = shm_malloc(sizeof(struct lrep_set_head));
714
+    if (lrep_set_list == NULL)
715
+    {
716
+                LM_ERR("no shm memory for lrep_set_list\n");
717
+        return -1;
718
+    }
719
+    memset(lrep_set_list, 0, sizeof(struct lrep_set_head));
720
+
721
+//	if (nortpproxy_str.s==NULL || nortpproxy_str.len<=0) {
722
+//		nortpproxy_str.len = 0;
723
+//	} else {
724
+//		while (nortpproxy_str.len > 0
725
+//				&& (nortpproxy_str.s[nortpproxy_str.len - 1] == '\r' ||
726
+//					nortpproxy_str.s[nortpproxy_str.len - 1] == '\n'))
727
+//			nortpproxy_str.len--;
728
+//	}
729
+
730
+//	if (rtpp_db_url.s != NULL)
731
+//	{
732
+//		init_rtpproxy_db();
733
+//		if (lrep_sets > 0)
734
+//		{
735
+//			LM_WARN("rtpproxy db url configured - ignoring modparam sets\n");
736
+//		}
737
+//	}
738
+    /* storing the list of rtp proxy sets in shared memory*/
739
+    for(i=0;i<lrep_sets;i++){
740
+                LM_DBG("Adding RTP-Proxy set %d/%d: %s\n", i, lrep_sets, rtpp_strings[i]);
741
+//        if ((rtpp_db_url.s == NULL) &&
742
+        if (lreproxy_add_lreproxy_set(rtpp_strings[i]) != 0) {
743
+            for(;i<lrep_sets;i++)
744
+                if(rtpp_strings[i])
745
+                    pkg_free(rtpp_strings[i]);
746
+            pkg_free(rtpp_strings);
747
+                    LM_ERR("Failed to add RTP-Proxy from Config!\n");
748
+            return -1;
749
+        }
750
+        if(rtpp_strings[i])
751
+            pkg_free(rtpp_strings[i]);
752
+    }
753
+
754
+//	if (ice_candidate_priority_avp_param) {
755
+//		s.s = ice_candidate_priority_avp_param; s.len = strlen(s.s);
756
+//		if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) {
757
+//			LM_ERR("malformed or non AVP definition <%s>\n",
758
+//					ice_candidate_priority_avp_param);
759
+//			return -1;
760
+//		}
761
+//		if (pv_get_avp_name(0, &(avp_spec.pvp), &ice_candidate_priority_avp,
762
+//					&avp_flags) != 0) {
763
+//			LM_ERR("invalid AVP definition <%s>\n",
764
+//					ice_candidate_priority_avp_param);
765
+//			return -1;
766
+//		}
767
+//		ice_candidate_priority_avp_type = avp_flags;
768
+//	}
769
+
770
+//	if (rtp_inst_pv_param.s) {
771
+//		rtp_inst_pvar = pv_cache_get(&rtp_inst_pv_param);
772
+//		if ((rtp_inst_pvar == NULL) ||
773
+//				((rtp_inst_pvar->type != PVT_AVP) &&
774
+//					(rtp_inst_pvar->type != PVT_XAVP) &&
775
+//					(rtp_inst_pvar->type != PVT_SCRIPTVAR))) {
776
+//			LM_ERR("Invalid pvar name <%.*s>\n", rtp_inst_pv_param.len,
777
+//					rtp_inst_pv_param.s);
778
+//			return -1;
779
+//		}
780
+//	}
781
+
782
+//	if (extra_id_pv_param.s && *extra_id_pv_param.s) {
783
+//		if(pv_parse_format(&extra_id_pv_param, &extra_id_pv) < 0) {
784
+//			LM_ERR("malformed PV string: %s\n", extra_id_pv_param.s);
785
+//			return -1;
786
+//		}
787
+//	} else {
788
+//		extra_id_pv = NULL;
789
+//	}
790
+
791
+    if (rtpp_strings)
792
+        pkg_free(rtpp_strings);
793
+
794
+
795
+    /* init the hastable which keeps the all media address for both party and also the elected_node <--> callid& via-branch relation */
796
+    if (hash_table_size < 1){
797
+        hash_table_size = HASH_SIZE;    //the default size 128 entry.
798
+    }
799
+
800
+    if (!lreproxy_hash_table_init(hash_table_size)) {
801
+                LM_ERR("lreproxy_hash_table_init(%d) failed!\n", hash_table_size);
802
+        return -1;
803
+    } else {
804
+                LM_INFO(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>lreproxy_hash_table_init(%d) success!\n", hash_table_size);
805
+    }
806
+
807
+
808
+
809
+    /* load tm module*/
810
+    if (load_tm_api( &tmb ) < 0)
811
+    {
812
+                LM_DBG("could not load the TM-functions - answer-offer model"
813
+                               " auto-detection is disabled\n");
814
+        memset(&tmb, 0, sizeof(struct tm_binds));
815
+    }
816
+
817
+    return 0;
818
+}
819
+
820
+
821
+static int
822
+child_init(int rank)
823
+{
824
+    int n;
825
+    char *cp;
826
+    struct addrinfo hints, *res;
827
+    struct lrep_set  *lrep_list;
828
+    struct lrep_node *pnode;
829
+
830
+    if(lrep_set_list==NULL )
831
+        return 0;
832
+
833
+    /* do not init sockets for PROC_INIT and main process when fork=yes */
834
+    if(rank==PROC_INIT || (rank==PROC_MAIN && dont_fork==0)) {
835
+        return 0;
836
+    }
837
+
838
+    /* Iterate known RTP proxies - create sockets */
839
+    mypid = getpid();
840
+
841
+    rtpp_socks = (int*)pkg_malloc( sizeof(int)*rtpp_no );
842
+    if (rtpp_socks==NULL) {
843
+                LM_ERR("no more pkg memory\n");
844
+        return -1;
845
+    }
846
+    memset(rtpp_socks, -1, sizeof(int)*rtpp_no);
847
+
848
+    for(lrep_list = lrep_set_list->lset_first; lrep_list != 0;
849
+        lrep_list = lrep_list->lset_next){
850
+
851
+        for (pnode=lrep_list->ln_first; pnode!=0; pnode = pnode->ln_next){
852
+            char *hostname;
853
+
854
+            if (pnode->ln_umode == 0) {
855
+                rtpp_socks[pnode->idx] = -1;
856
+                goto rptest;
857
+            }
858
+
859
+            /*
860
+             * This is UDP or UDP6. Detect host and port; lookup host;
861
+             * do connect() in order to specify peer address
862
+             */
863
+            hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->ln_address) + 1));
864
+            if (hostname==NULL) {
865
+                        LM_ERR("no more pkg memory\n");
866
+                return -1;
867
+            }
868
+            strcpy(hostname, pnode->ln_address);
869
+
870
+            cp = strrchr(hostname, ':');
871
+            if (cp != NULL) {
872
+                *cp = '\0';
873
+                cp++;
874
+            }
875
+            if (cp == NULL || *cp == '\0')
876
+                cp = CPORT;
877
+
878
+            memset(&hints, 0, sizeof(hints));
879
+            hints.ai_flags = 0;
880
+            hints.ai_family = (pnode->ln_umode == 6) ? AF_INET6 : AF_INET;
881
+            hints.ai_socktype = SOCK_DGRAM;
882
+            if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
883
+                        LM_ERR("%s\n", gai_strerror(n));
884
+                pkg_free(hostname);
885
+                return -1;
886
+            }
887
+            pkg_free(hostname);
888
+
889
+            rtpp_socks[pnode->idx] = socket((pnode->ln_umode == 6)
890
+                                            ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
891
+            if ( rtpp_socks[pnode->idx] == -1) {
892
+                        LM_ERR("can't create socket\n");
893
+                freeaddrinfo(res);
894
+                return -1;
895
+            }
896
+
897
+            if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
898
+                        LM_ERR("can't connect to a RTP proxy\n");
899
+                close( rtpp_socks[pnode->idx] );
900
+                rtpp_socks[pnode->idx] = -1;
901
+                freeaddrinfo(res);
902
+                return -1;
903
+            }
904
+            freeaddrinfo(res);
905
+rptest:
906
+            pnode->ln_enable = lrep_test(pnode);
907
+            if (pnode->ln_enable) {       //get lre proxy config if it is enable.
908
+//                LM_INFO("lrep_test test is calling here\n"); //enable next line.
909
+                lrep_get_config(pnode);
910
+            }
911
+        }
912
+    }
913
+
914
+    return 0;
915
+}
916
+
917
+
918
+static void mod_destroy(void)
919
+{
920
+    struct lrep_set * crt_list, * last_list;
921
+    struct lrep_node * crt_rtpp, *last_rtpp;
922
+
923
+    /*free the shared memory*/
924
+//	if (natping_state)
925
+//		shm_free(natping_state);
926
+
927
+    if(lrep_set_list == NULL)
928
+        return;
929
+
930
+    for(crt_list = lrep_set_list->lset_first; crt_list != NULL; ){
931
+
932
+        for(crt_rtpp = crt_list->ln_first; crt_rtpp != NULL;  ){
933
+
934
+            last_rtpp = crt_rtpp;
935
+            crt_rtpp = last_rtpp->ln_next;
936
+            shm_free(last_rtpp);
937
+        }
938
+
939
+        last_list = crt_list;
940
+        crt_list = last_list->lset_next;
941
+        shm_free(last_list);
942
+    }
943
+
944
+    shm_free(lrep_set_list);
945
+
946
+    /* destroy the hash table */
947
+    if (!lreproxy_hash_table_destroy()) {
948
+                LM_ERR("lreproxy_hash_table_destroy() failed!\n");
949
+    } else {
950
+                LM_DBG("lreproxy_hash_table_destroy() success!\n");
951
+    }
952
+
953
+}
954
+
955
+
956
+
957
+static char * gencookie(void)
958
+{
959
+    static char cook[34];
960
+
961
+    sprintf(cook, "%d_%u ", (int)mypid, myseqn);
962
+    myseqn++;
963
+    return cook;
964
+}
965
+
966
+static int lrep_test(struct lrep_node *node)
967
+{
968
+    int buflen = 256;
969
+    char buf[buflen];
970
+    struct iovec v[2] = {{NULL, 0}, {"P", 1}};
971
+
972
+    memset(buf, 0, buflen);
973
+    memcpy(buf, send_lrep_command(node, v, 2, 0), buflen);
974
+
975
+//    if (buf == NULL) {
976
+    if (!buf[0]) {
977
+        LM_ERR("can't ping the lre proxy %s, Disable it right now.\n", node->ln_url.s);
978
+        return 0;
979
+    }
980
+
981
+    char *resp = buf + v[0].iov_len + v[1].iov_len + 1;
982
+    if (memcmp(resp, "PONG", 4) == 0)
983
+//                LM_DBG("Recieve PONG response from lre proxy server %s, Enable it right now.\n", node->ln_url.s);
984
+            LM_INFO("Recieve PONG response from lre proxy server %s, Enable it right now.\n", node->ln_url.s);
985
+
986
+    return 1;
987
+
988
+}
989
+
990
+static int lrep_get_config(struct lrep_node *node){
991
+
992
+    int buflen = 256;
993
+    char buf[buflen];
994
+    struct iovec v[2] = {{NULL, 0}, {"G", 1}};
995
+    struct lrep_node_conf *lnconf = NULL;
996
+
997
+    memset(buf, 0, buflen);
998
+    memcpy(buf, send_lrep_command(node, v, 2, 0), buflen);
999
+
1000
+//    if (buf == NULL) {
1001
+    if (!buf[0]) {
1002
+        LM_ERR("can't get config of the lre proxy %s, Disable it right now.\n", node->ln_url.s);
1003
+        return 0;
1004
+    }
1005
+
1006
+    lnconf = (struct lrep_node_conf *)(buf + v[0].iov_len + v[1].iov_len + 1);
1007
+
1008
+    if (lnconf == NULL){
1009
+        LM_ERR("can't get config of the lre proxy %s, Disable it right now.\n", node->ln_url.s);
1010
+        return 0;
1011
+    }
1012
+
1013
+
1014
+    memcpy(node->lrep_n_c, lnconf, sizeof(struct lrep_node_conf));
1015
+
1016
+//    node->lrep_n_c = lnconf;
1017
+    LM_INFO("the lre proxy %s is configured successfully right now.\n", node->ln_url.s);
1018
+    LM_INFO("buffer internal:%s\n", node->lrep_n_c->internal_ip);
1019
+    LM_INFO("buffer external:%s\n", node->lrep_n_c->external_ip);
1020
+    LM_INFO("buffer start_port:%d\n", node->lrep_n_c->start_port);
1021
+    LM_INFO("buffer end_port:%d\n", node->lrep_n_c->end_port);
1022
+    LM_INFO("buffer current_port:%d\n", node->lrep_n_c->current_port);
1023
+
1024
+    return 1;
1025
+
1026
+
1027
+
1028
+}
1029
+
1030
+static int lrep_set_conntrack_rule(struct lreproxy_hash_entry *e) {
1031
+    int buflen = 254;
1032
+    char buf[buflen];
1033
+    int v_len = 0;
1034
+
1035
+    char src_ipv4[20];
1036
+    char src_port[20];
1037
+    char dst_ipv4[20];
1038
+    char dst_port[20];
1039
+    char snat_ipv4[20];
1040
+    char snat_port[20];
1041
+    char dnat_ipv4[20];
1042
+    char dnat_port[20];
1043
+    char timeout[20];
1044
+
1045
+    struct iovec v[] = {
1046
+            {NULL, 0},  /* reserved (cookie) */
1047
+            {"S",  1},   /* command & common options */
1048
+            {NULL, 0},  /* src_ipv4 */
1049
+            {NULL, 0},  /* dst_ipv4 */
1050
+            {NULL, 0},  /* snat_ipv4 */
1051
+            {NULL, 0},  /* dnat_ipv4 */
1052
+            {NULL, 0},  /* src_port */
1053
+            {NULL, 0},  /* dst_port*/
1054
+            {NULL, 0},  /* snat_port */
1055
+            {NULL, 0},  /* dnat_port*/
1056
+            {NULL, 0},  /* timeout to clear conntrack entry*/
1057
+    };
1058
+
1059
+    v_len += v[1].iov_len;
1060
+
1061
+    //set src_ipv4 to buffer.
1062
+    sprintf(src_ipv4, "%.*s ", e->src_ipv4.len, e->src_ipv4.s);
1063
+    v[2].iov_base = src_ipv4;
1064
+    v[2].iov_len = strlen(v[2].iov_base);
1065
+    v_len += v[2].iov_len;
1066
+
1067
+    //set dst_ipv4 to buffer.
1068
+    sprintf(dst_ipv4, "%.*s ", e->dst_ipv4.len, e->dst_ipv4.s);
1069
+    v[3].iov_base = dst_ipv4;
1070
+    v[3].iov_len = strlen(v[3].iov_base);
1071
+    v_len += v[3].iov_len;
1072
+
1073
+    //set snat_ipv4 to buffer.
1074
+    sprintf(snat_ipv4, "%.*s ", e->snat_ipv4.len, e->snat_ipv4.s);
1075
+    v[4].iov_base = snat_ipv4;
1076
+    v[4].iov_len = strlen(v[4].iov_base);
1077
+    v_len += v[4].iov_len;
1078
+
1079
+    //set dnat_ipv4 to buffer.
1080
+    sprintf(dnat_ipv4, "%.*s ", e->dnat_ipv4.len, e->dnat_ipv4.s);
1081
+    v[5].iov_base = dnat_ipv4;
1082
+    v[5].iov_len = strlen(v[5].iov_base);
1083
+    v_len += v[5].iov_len;
1084
+
1085
+    //set src_port to buffer.
1086
+    sprintf(src_port, "%.*s ", e->src_port.len, e->src_port.s);
1087
+    v[6].iov_base = src_port;
1088
+    v[6].iov_len = strlen(v[6].iov_base);
1089
+    v_len += v[6].iov_len;
1090
+
1091
+    //set dst_port to buffer.
1092
+    sprintf(dst_port, "%.*s ", e->dst_port.len, e->dst_port.s);
1093
+    v[7].iov_base = dst_port;
1094
+    v[7].iov_len = strlen(v[7].iov_base);
1095
+    v_len += v[7].iov_len;
1096
+
1097
+    //set snat_port to buffer.
1098
+    sprintf(snat_port, "%.*s ", e->snat_port.len, e->snat_port.s);
1099
+    v[8].iov_base = snat_port;
1100
+    v[8].iov_len = strlen(v[8].iov_base);
1101
+    v_len += v[8].iov_len;
1102
+
1103
+    //set dnat_port to buffer.
1104
+    sprintf(dnat_port, "%.*s ", e->dnat_port.len, e->dnat_port.s);
1105
+    v[9].iov_base = dnat_port;
1106
+    v[9].iov_len = strlen(v[9].iov_base);
1107
+    v_len += v[9].iov_len;
1108
+
1109
+    //set timeout to buffer. Set to 60 sec for default.
1110
+    sprintf(timeout, "%d ", 60);
1111
+    v[10].iov_base = timeout;
1112
+    v[10].iov_len = strlen(v[10].iov_base);
1113
+    v_len += v[10].iov_len;
1114
+
1115
+    memset(buf, 0, buflen);
1116
+    memcpy(buf, send_lrep_command(e->node, v, 11, v_len), buflen);
1117
+//
1118
+
1119
+//    if (buf == NULL) {
1120
+    if (!buf[0]) {
1121
+                LM_ERR("can't ping the lre proxy %s, Disable it right now.\n", e->node->ln_url.s);
1122
+        return 0;
1123
+    }
1124
+
1125
+    v_len += v[0].iov_len;
1126
+
1127
+
1128
+//    char *resp = buf + v[0].iov_len + v[1].iov_len + v[2].iov_len;
1129
+    char *resp = buf + v_len;
1130
+    if (memcmp(resp, "OK", 2) == 0) {
1131
+                LM_INFO("Recieve OK response from lre proxy server %s, Rule set successfully.\n", e->node->ln_url.s);
1132
+                LM_DBG("Recieve OK response from lre proxy server %s, Rule set successfully.\n", e->node->ln_url.s);
1133
+    }
1134
+    return 1;
1135
+
1136
+}
1137
+
1138
+
1139
+char *send_lrep_command(struct lrep_node *node, struct iovec *v, int vcnt, int more)
1140
+{
1141
+    struct sockaddr_un addr;
1142
+    int fd, len, i;
1143
+//    char *cp;
1144
+    static char buf[256];
1145
+    struct pollfd fds[1];
1146
+
1147
+    memset(buf, 0, 256);
1148
+    len = 0;
1149
+//    cp = buf;
1150
+    if (node->ln_umode == 0) {
1151
+        memset(&addr, 0, sizeof(addr));
1152
+        addr.sun_family = AF_LOCAL;
1153
+        strncpy(addr.sun_path, node->ln_address,
1154
+                sizeof(addr.sun_path) - 1);
1155
+#ifdef HAVE_SOCKADDR_SA_LEN
1156
+        addr.sun_len = strlen(addr.sun_path);
1157
+#endif
1158
+
1159
+        fd = socket(AF_LOCAL, SOCK_STREAM, 0);
1160
+        if (fd < 0) {
1161
+                    LM_ERR("can't create socket\n");
1162
+            goto badproxy;
1163
+        }
1164
+        if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1165
+            close(fd);
1166
+                    LM_ERR("can't connect to lre proxy\n");
1167
+            goto badproxy;
1168
+        }
1169
+
1170
+        do {
1171
+            len = writev(fd, v + 1, vcnt - 1);
1172
+        } while (len == -1 && errno == EINTR);
1173
+        if (len <= 0) {
1174
+            close(fd);
1175
+                    LM_ERR("can't send command to a lre proxy %s\n", node->ln_url.s);
1176
+            goto badproxy;
1177
+        }
1178
+        do {
1179
+            len = read(fd, buf, sizeof(buf) - 1);
1180
+        } while (len == -1 && errno == EINTR);
1181
+        close(fd);
1182
+        if (len <= 0) {
1183
+                    LM_ERR("can't read reply from a lre proxy %s\n", node->ln_url.s);
1184
+            goto badproxy;
1185
+        }
1186
+    } else {
1187
+        fds[0].fd = rtpp_socks[node->idx];
1188
+        fds[0].events = POLLIN;
1189
+        fds[0].revents = 0;
1190
+        /* Drain input buffer */
1191
+        while ((poll(fds, 1, 0) == 1) &&
1192
+               ((fds[0].revents & POLLIN) != 0)) {
1193
+            recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
1194
+            fds[0].revents = 0;
1195
+        }
1196
+        v[0].iov_base = gencookie();
1197
+        v[0].iov_len = strlen(v[0].iov_base);
1198
+        for (i = 0; i < lreproxy_retr; i++) {
1199
+            do {
1200
+                len = writev(rtpp_socks[node->idx], v, vcnt);
1201
+            } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
1202
+            if (len <= 0) {
1203
+                        LM_ERR("can't send command to a lre proxy %s\n", node->ln_url.s);
1204
+                goto badproxy;
1205
+            }
1206
+            while ((poll(fds, 1, lreproxy_tout * 1000) == 1) &&
1207
+                   (fds[0].revents & POLLIN) != 0) {
1208
+                do {
1209
+                    len = recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
1210
+                } while (len == -1 && errno == EINTR);
1211
+                if (len <= 0) {
1212
+                            LM_ERR("can't read reply from a lre proxy %s\n", node->ln_url.s);
1213
+                    goto badproxy;
1214
+                }
1215
+                if (len >= (v[0].iov_len - 1) &&
1216
+                    memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {      //check coocke validation.
1217
+                    char *command = buf + v[0].iov_len;
1218
+                    switch (*command) {
1219
+                        case 'P':
1220
+                            if (len == v[0].iov_len + v[1].iov_len + 4 + 1)
1221
+                                goto out;
1222
+//                            break;
1223
+                        case 'G':
1224
+                            if (len == v[0].iov_len + v[1].iov_len + sizeof(struct lrep_node_conf) + 1)
1225
+                                goto out;
1226
+//                            break;
1227
+                        case 'S':
1228
+                            if (len == more + v[0].iov_len + 2)
1229
+                                goto out;
1230
+//                            break;
1231
+                    }
1232
+//                    len -= (v[0].iov_len - 1);
1233
+//                    cp += (v[0].iov_len - 1);
1234
+//                    if (len != 0) {
1235
+//                        len--;
1236
+//                        cp++;
1237
+//                    }
1238
+//                    goto out;
1239
+//                    }
1240
+                }
1241
+                fds[0].revents = 0;
1242
+            }
1243
+        }
1244
+        if (i == lreproxy_tout) {
1245
+                    LM_ERR("timeout waiting reply from a lre proxy server %s\n", node->ln_url.s);
1246
+            goto badproxy;
1247
+
1248
+        }
1249
+    }
1250
+    out:
1251
+    return buf;
1252
+    badproxy:
1253
+            LM_ERR("lre proxy <%s> does not respond, disable it\n", node->ln_url.s);
1254
+    node->ln_enable = 0;
1255
+//    node->ln_recheck_ticks = get_ticks() + lreproxy_disable_tout;
1256
+    return buf;
1257
+}
1258
+
1259
+/*
1260
+ * select the set with the id_set id
1261
+ */
1262
+static struct lrep_set * select_lrep_set(int id_set ){
1263
+
1264
+    struct lrep_set * lrep_list;
1265
+    /*is it a valid set_id?*/
1266
+
1267
+    if(!lrep_set_list)
1268
+    {
1269
+                LM_ERR("rtpproxy set list not initialised\n");
1270
+        return NULL;
1271
+    }
1272
+
1273
+    for(lrep_list=lrep_set_list->lset_first; lrep_list!=NULL &&
1274
+                                             lrep_list->id_set!=id_set; lrep_list=lrep_list->lset_next);
1275
+
1276
+    return lrep_list;
1277
+}
1278
+
1279
+
1280
+struct lrep_node *select_lrep_node(int do_test)
1281
+{
1282
+//    unsigned sum, sumcut, weight_sum;
1283
+    unsigned weight_sum;
1284
+    struct lrep_node* node;
1285
+    int was_forced;
1286
+    int was_forced2;
1287
+    int was_forced3;
1288
+
1289
+    if(!selected_lrep_set){
1290
+        LM_ERR("script error -no valid set selected\n");
1291
+        return NULL;
1292
+    }
1293
+    /* Most popular case: 1 proxy, nothing to calculate */
1294
+    if (selected_lrep_set->lrep_node_count == 1) {
1295
+        node = selected_lrep_set->ln_first;
1296
+//        if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks())
1297
+        if (!node->ln_enable) {
1298
+            node->ln_enable = lrep_test(node);
1299
+            if (node->ln_enable) {       //get lre proxy config if it is enable.
1300
+                lrep_get_config(node);
1301
+                return node;
1302
+            }
1303
+        }
1304
+//        return node->ln_enable ? node : NULL;
1305
+        return NULL;
1306
+    }
1307
+
1308
+//    /* XXX Use quick-and-dirty hashing algo */
1309
+//    for(sum = 0; callid.len > 0; callid.len--)
1310
+//        sum += callid.s[callid.len - 1];
1311
+//    sum &= 0xff;
1312
+
1313
+
1314
+    /* Check node is enable and test it again*/
1315
+    was_forced = 0;
1316
+retry:
1317
+    weight_sum = 0;
1318
+    for (node=selected_lrep_set->ln_first; node!=NULL; node=node->ln_next) {
1319
+
1320
+        if (!node->ln_enable) {
1321
+            /* Try to enable if it's time to try. */
1322
+            node->ln_enable = lrep_test(node);
1323
+            if (node->ln_enable)       //get lre proxy config if it is enable.
1324
+                lrep_get_config(node);
1325
+        }
1326
+
1327
+//        if (!node->rn_disabled)
1328
+//            weight_sum += node->rn_weight;
1329
+        if (node->ln_enable)
1330
+            weight_sum += node->ln_weight;
1331
+    }
1332
+
1333
+    if (weight_sum == 0) {
1334
+        /* No proxies? Force all to be redetected, if not yet */
1335
+        if (was_forced)
1336
+            return NULL;
1337
+        was_forced = 1;
1338
+//        for(node=selected_lrep_set->ln_first; node!=NULL; node=node->ln_next) {
1339
+//            node->ln_enable = lrep_test(node);
1340
+//        }
1341
+        goto retry;
1342
+    }
1343
+
1344
+    if (lrep_algorithm == LRE_LINER) {
1345
+        was_forced2 = 0;
1346
+retry2:
1347
+        for (node=selected_lrep_set->ln_first; node != NULL; node = node->ln_next)
1348
+            if (node->ln_enable)
1349
+                goto found;
1350
+        was_forced2 = 1;
1351
+        if (was_forced2)
1352
+            return NULL;
1353
+
1354
+        goto retry2;
1355
+    }
1356
+    else if(lrep_algorithm == LRE_RR) {
1357
+        was_forced3 = 0;
1358
+retry3:
1359
+        if (!selected_lrep_node) {
1360
+            selected_lrep_node = selected_lrep_set->ln_first;
1361
+            was_forced3 = 1;
1362
+        }
1363
+        for (node = selected_lrep_node; node != NULL; node = node->ln_next) {
1364
+            if (!node->ln_enable)
1365
+                continue;
1366
+            selected_lrep_node = node->ln_next;
1367
+//        if (sumcut < node->ln_weight)
1368
+            goto found;
1369
+//        sumcut -= node->ln_weight;
1370
+        }
1371
+
1372
+        if (was_forced3)
1373
+            return NULL;
1374
+
1375
+        selected_lrep_node = NULL;
1376
+        goto retry3;
1377
+    }
1378
+
1379
+//            LM_INFO("STEP-4>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1380
+
1381
+
1382
+//    sumcut = sum % weight_sum;
1383
+//    /*
1384
+//     * sumcut here lays from 0 to weight_sum-1.
1385
+//     * Scan proxy list and decrease until appropriate proxy is found.
1386
+//     */
1387
+//    for (node=selected_rtpp_set->ln_first; node!=NULL; node=node->ln_next) {
1388
+//        if (!node->ln_enable)
1389
+//            continue;
1390
+//        if (sumcut < node->ln_weight)
1391
+//            goto found;
1392
+//        sumcut -= node->ln_weight;
1393
+//    }
1394
+    /* No node list */
1395
+//    return NULL;
1396
+    found:
1397
+    if (do_test) {
1398
+//    //todo...
1399
+        node->ln_enable = lrep_test(node);