rtpengine: fix issues reported by Coverity
[sip-router] / src / modules / rtpengine / rtpengine.c
1 /*
2  * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
3  * Copyright (C) 2014-2015 Sipwise GmbH, http://www.sipwise.com
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 #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 #include <ifaddrs.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49
50 #include "../../core/flags.h"
51 #include "../../core/sr_module.h"
52 #include "../../core/dprint.h"
53 #include "../../core/data_lump.h"
54 #include "../../core/data_lump_rpl.h"
55 #include "../../core/error.h"
56 #include "../../core/forward.h"
57 #include "../../core/mem/mem.h"
58 #include "../../core/parser/parse_from.h"
59 #include "../../core/parser/parse_to.h"
60 #include "../../core/parser/parse_uri.h"
61 #include "../../core/parser/parser_f.h"
62 #include "../../core/parser/sdp/sdp.h"
63 #include "../../core/resolve.h"
64 #include "../../core/timer.h"
65 #include "../../core/trim.h"
66 #include "../../core/ut.h"
67 #include "../../core/pt.h"
68 #include "../../core/timer_proc.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/rpc.h"
78 #include "../../core/rpc_lookup.h"
79 #include "../../core/kemi.h"
80 #include "../../modules/tm/tm_load.h"
81 #include "rtpengine.h"
82 #include "rtpengine_funcs.h"
83 #include "rtpengine_hash.h"
84 #include "bencode.h"
85 #include "config.h"
86
87 MODULE_VERSION
88
89 #if !defined(AF_LOCAL)
90 #define AF_LOCAL AF_UNIX
91 #endif
92 #if !defined(PF_LOCAL)
93 #define PF_LOCAL PF_UNIX
94 #endif
95
96 /* NAT UAC test constants */
97 #define NAT_UAC_TEST_C_1918                     0x01
98 #define NAT_UAC_TEST_RCVD                       0x02
99 #define NAT_UAC_TEST_V_1918                     0x04
100 #define NAT_UAC_TEST_S_1918                     0x08
101 #define NAT_UAC_TEST_RPORT                      0x10
102
103 #define COOKIE_SIZE                                     128
104 #define HOSTNAME_SIZE                           100
105
106 #define DEFAULT_RTPP_SET_ID                     0
107
108 enum {
109         RPC_FOUND_ALL = 2,
110         RPC_FOUND_ONE = 1,
111         RPC_FOUND_NONE = 0,
112 };
113
114 #define CPORT                                   "22222"
115
116 struct ng_flags_parse {
117         int via, to, packetize, transport;
118         bencode_item_t *dict, *flags, *direction, *replace, *rtcp_mux;
119         str call_id, from_tag, to_tag;
120 };
121
122 static const char *command_strings[] = {
123         [OP_OFFER]              = "offer",
124         [OP_ANSWER]             = "answer",
125         [OP_DELETE]             = "delete",
126         [OP_START_RECORDING]    = "start recording",
127         [OP_QUERY]              = "query",
128         [OP_PING]               = "ping",
129 };
130
131 struct minmax_mos_stats {
132         str mos_param;
133         str at_param;
134         str packetloss_param;
135         str jitter_param;
136         str roundtrip_param;
137         str samples_param;
138
139         pv_elem_t *mos_pv;
140         pv_elem_t *at_pv;
141         pv_elem_t *packetloss_pv;
142         pv_elem_t *jitter_pv;
143         pv_elem_t *roundtrip_pv;
144         pv_elem_t *samples_pv;
145 };
146 struct minmax_mos_label_stats {
147         int got_any_pvs;
148
149         str label_param;
150         pv_elem_t *label_pv;
151
152         struct minmax_mos_stats min,
153                                 max,
154                                 average;
155 };
156 struct minmax_stats_vals {
157         long long mos;
158         long long at;
159         long long packetloss;
160         long long jitter;
161         long long roundtrip;
162         long long samples;
163         long long avg_samples; /* our own running count to average the averages */
164 };
165
166 static char *gencookie();
167 static int rtpp_test(struct rtpp_node*, int, int);
168 static int start_recording_f(struct sip_msg *, char *, char *);
169 static int rtpengine_answer1_f(struct sip_msg *, char *, char *);
170 static int rtpengine_offer1_f(struct sip_msg *, char *, char *);
171 static int rtpengine_delete1_f(struct sip_msg *, char *, char *);
172 static int rtpengine_manage1_f(struct sip_msg *, char *, char *);
173 static int rtpengine_query1_f(struct sip_msg *, char *, char *);
174
175 static int parse_flags(struct ng_flags_parse *, struct sip_msg *, enum rtpe_operation *, const char *);
176
177 static int rtpengine_offer_answer(struct sip_msg *msg, const char *flags, int op, int more);
178 static int fixup_set_id(void ** param, int param_no);
179 static int set_rtpengine_set_f(struct sip_msg * msg, char * str1, char * str2);
180 static struct rtpp_set * select_rtpp_set(unsigned int id_set);
181 static struct rtpp_node *select_rtpp_node_new(str, str, int, struct rtpp_node **, int);
182 static struct rtpp_node *select_rtpp_node_old(str, str, int, enum rtpe_operation);
183 static struct rtpp_node *select_rtpp_node(str, str, int, struct rtpp_node **, int, enum rtpe_operation);
184 static int is_queried_node(struct rtpp_node *, struct rtpp_node **, int);
185 static int build_rtpp_socks();
186 static char *send_rtpp_command(struct rtpp_node *, bencode_item_t *, int *);
187 static int get_extra_id(struct sip_msg* msg, str *id_str);
188
189 static int rtpengine_set_store(modparam_t type, void * val);
190 static int rtpengine_add_rtpengine_set(char * rtp_proxies, unsigned int weight, int disabled, unsigned int ticks);
191
192 static int mod_init(void);
193 static int child_init(int);
194 static void mod_destroy(void);
195
196 static int get_ip_type(char *str_addr);
197 static int get_ip_scope(char *str_addr); // useful for link-local ipv6
198 static int bind_force_send_ip(int sock_idx);
199
200 static int add_rtpp_node_info(void *ptrs, struct rtpp_node *crt_rtpp, struct rtpp_set *rtpp_list);
201 static int rtpp_test_ping(struct rtpp_node *node);
202
203 /* Pseudo-Variables */
204 static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
205 static int set_rtp_inst_pvar(struct sip_msg *msg, const str * const uri);
206 static int pv_parse_var(str *inp, pv_elem_t **outp, int *got_any);
207 static int mos_label_stats_parse(struct minmax_mos_label_stats *mmls);
208 static void parse_call_stats(bencode_item_t *, struct sip_msg *);
209
210 static int rtpengine_allow_op = 0;
211 static struct rtpp_node **queried_nodes_ptr = NULL;
212 static pid_t mypid;
213 static unsigned int myseqn = 0;
214 static str extra_id_pv_param = {NULL, 0};
215 static char *setid_avp_param = NULL;
216 static int hash_table_tout = 3600;
217 static int hash_table_size = 256;
218 static unsigned int setid_default = DEFAULT_RTPP_SET_ID;
219
220 static char ** rtpp_strings=0;
221 static int rtpp_sets=0; /*used in rtpengine_set_store()*/
222 static int rtpp_set_count = 0;
223 static unsigned int current_msg_id = (unsigned int)-1;
224 /* RTP proxy balancing list */
225 static struct rtpp_set_head * rtpp_set_list =0;
226 static struct rtpp_set * active_rtpp_set =0;
227 static struct rtpp_set * selected_rtpp_set_1 =0;
228 static struct rtpp_set * selected_rtpp_set_2 =0;
229 static struct rtpp_set * default_rtpp_set=0;
230
231 static str body_intermediate;
232
233 static str rtp_inst_pv_param = {NULL, 0};
234 static pv_spec_t *rtp_inst_pvar = NULL;
235
236 /* array with the sockets used by rtpporxy (per process)*/
237 static unsigned int *rtpp_no = 0;
238 static gen_lock_t *rtpp_no_lock = 0;
239 static int *rtpp_socks = 0;
240 static unsigned int rtpp_socks_size = 0;
241
242 static int setid_avp_type;
243 static int_str setid_avp;
244
245 static str write_sdp_pvar_str = {NULL, 0};
246 static pv_spec_t *write_sdp_pvar = NULL;
247
248 static str read_sdp_pvar_str = {NULL, 0};
249 static pv_spec_t *read_sdp_pvar = NULL;
250
251 #define RTPENGINE_SESS_LIMIT_MSG "Parallel session limit reached"
252 #define RTPENGINE_SESS_LIMIT_MSG_LEN (sizeof(RTPENGINE_SESS_LIMIT_MSG)-1)
253
254 char* force_send_ip_str="";
255 int force_send_ip_af = AF_UNSPEC;
256
257 typedef struct rtpp_set_link {
258         struct rtpp_set *rset;
259         pv_spec_t *rpv;
260 } rtpp_set_link_t;
261
262 /* tm */
263 static struct tm_binds tmb;
264
265 static pv_elem_t *extra_id_pv = NULL;
266
267
268 static struct minmax_mos_label_stats global_mos_stats,
269                                      side_A_mos_stats,
270                                      side_B_mos_stats;
271 int got_any_mos_pvs;
272
273
274
275 static cmd_export_t cmds[] = {
276         {"set_rtpengine_set",   (cmd_function)set_rtpengine_set_f,      1,
277                 fixup_set_id, 0,
278                 ANY_ROUTE},
279         {"set_rtpengine_set",   (cmd_function)set_rtpengine_set_f,      2,
280                 fixup_set_id, 0,
281                 ANY_ROUTE},
282         {"start_recording",     (cmd_function)start_recording_f,        0,
283                 0, 0,
284                 ANY_ROUTE },
285         {"rtpengine_offer",     (cmd_function)rtpengine_offer1_f,       0,
286                 0, 0,
287                 ANY_ROUTE},
288         {"rtpengine_offer",     (cmd_function)rtpengine_offer1_f,       1,
289                 fixup_spve_null, 0,
290                 ANY_ROUTE},
291         {"rtpengine_answer",    (cmd_function)rtpengine_answer1_f,      0,
292                 0, 0,
293                 ANY_ROUTE},
294         {"rtpengine_answer",    (cmd_function)rtpengine_answer1_f,      1,
295                 fixup_spve_null, 0,
296                 ANY_ROUTE},
297         {"rtpengine_manage",    (cmd_function)rtpengine_manage1_f,      0,
298                 0, 0,
299                 ANY_ROUTE},
300         {"rtpengine_manage",    (cmd_function)rtpengine_manage1_f,      1,
301                 fixup_spve_null, 0,
302                 ANY_ROUTE},
303         {"rtpengine_delete",    (cmd_function)rtpengine_delete1_f,      0,
304                 0, 0,
305                 ANY_ROUTE},
306         {"rtpengine_delete",    (cmd_function)rtpengine_delete1_f,      1,
307                 fixup_spve_null, 0,
308                 ANY_ROUTE},
309         {"rtpengine_query",     (cmd_function)rtpengine_query1_f,       0,
310                 0, 0,
311                 ANY_ROUTE},
312         {"rtpengine_query",     (cmd_function)rtpengine_query1_f,       1,
313                 fixup_spve_null, 0,
314                 ANY_ROUTE},
315         {0, 0, 0, 0, 0, 0}
316 };
317
318 static pv_export_t mod_pvs[] = {
319         {{"rtpstat", (sizeof("rtpstat")-1)}, /* RTP-Statistics */
320         PVT_OTHER, pv_get_rtpstat_f, 0, 0, 0, 0, 0},
321         {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
322 };
323
324 static param_export_t params[] = {
325         {"rtpengine_sock",        PARAM_STRING|USE_FUNC_PARAM,
326                                  (void*)rtpengine_set_store          },
327         {"rtpengine_disable_tout",INT_PARAM, &default_rtpengine_cfg.rtpengine_disable_tout },
328         {"rtpengine_retr",        INT_PARAM, &default_rtpengine_cfg.rtpengine_retr         },
329         {"queried_nodes_limit",   INT_PARAM, &default_rtpengine_cfg.queried_nodes_limit    },
330         {"rtpengine_tout_ms",     INT_PARAM, &default_rtpengine_cfg.rtpengine_tout_ms      },
331         {"rtpengine_allow_op",    INT_PARAM, &rtpengine_allow_op     },
332         {"db_url",                PARAM_STR, &rtpp_db_url            },
333         {"table_name",            PARAM_STR, &rtpp_table_name        },
334         {"setid_col",             PARAM_STR, &rtpp_setid_col         },
335         {"url_col",               PARAM_STR, &rtpp_url_col           },
336         {"weight_col",            PARAM_STR, &rtpp_weight_col        },
337         {"disabled_col",          PARAM_STR, &rtpp_disabled_col      },
338         {"extra_id_pv",           PARAM_STR, &extra_id_pv_param      },
339         {"setid_avp",             PARAM_STRING, &setid_avp_param     },
340         {"force_send_interface",  PARAM_STRING, &force_send_ip_str   },
341         {"rtp_inst_pvar",         PARAM_STR, &rtp_inst_pv_param      },
342         {"write_sdp_pv",          PARAM_STR, &write_sdp_pvar_str     },
343         {"read_sdp_pv",           PARAM_STR, &read_sdp_pvar_str      },
344         {"hash_table_tout",       INT_PARAM, &hash_table_tout        },
345         {"hash_table_size",       INT_PARAM, &hash_table_size        },
346         {"setid_default",         INT_PARAM, &setid_default          },
347
348         /* MOS stats output */
349         /* global averages */
350         {"mos_min_pv",                PARAM_STR, &global_mos_stats.min.mos_param             },
351         {"mos_min_at_pv",             PARAM_STR, &global_mos_stats.min.at_param              },
352         {"mos_min_packetloss_pv",     PARAM_STR, &global_mos_stats.min.packetloss_param      },
353         {"mos_min_jitter_pv",         PARAM_STR, &global_mos_stats.min.jitter_param          },
354         {"mos_min_roundtrip_pv",      PARAM_STR, &global_mos_stats.min.roundtrip_param       },
355         {"mos_max_pv",                PARAM_STR, &global_mos_stats.max.mos_param             },
356         {"mos_max_at_pv",             PARAM_STR, &global_mos_stats.max.at_param              },
357         {"mos_max_packetloss_pv",     PARAM_STR, &global_mos_stats.max.packetloss_param      },
358         {"mos_max_jitter_pv",         PARAM_STR, &global_mos_stats.max.jitter_param          },
359         {"mos_max_roundtrip_pv",      PARAM_STR, &global_mos_stats.max.roundtrip_param       },
360         {"mos_average_pv",            PARAM_STR, &global_mos_stats.average.mos_param         },
361         {"mos_average_packetloss_pv", PARAM_STR, &global_mos_stats.average.packetloss_param  },
362         {"mos_average_jitter_pv",     PARAM_STR, &global_mos_stats.average.jitter_param      },
363         {"mos_average_roundtrip_pv",  PARAM_STR, &global_mos_stats.average.roundtrip_param   },
364         {"mos_average_samples_pv",    PARAM_STR, &global_mos_stats.average.samples_param     },
365
366         /* designated side A */
367         {"mos_A_label_pv",              PARAM_STR, &side_A_mos_stats.label_param               },
368         {"mos_min_A_pv",                PARAM_STR, &side_A_mos_stats.min.mos_param             },
369         {"mos_min_at_A_pv",             PARAM_STR, &side_A_mos_stats.min.at_param              },
370         {"mos_min_packetloss_A_pv",     PARAM_STR, &side_A_mos_stats.min.packetloss_param      },
371         {"mos_min_jitter_A_pv",         PARAM_STR, &side_A_mos_stats.min.jitter_param          },
372         {"mos_min_roundtrip_A_pv",      PARAM_STR, &side_A_mos_stats.min.roundtrip_param       },
373         {"mos_max_A_pv",                PARAM_STR, &side_A_mos_stats.max.mos_param             },
374         {"mos_max_at_A_pv",             PARAM_STR, &side_A_mos_stats.max.at_param              },
375         {"mos_max_packetloss_A_pv",     PARAM_STR, &side_A_mos_stats.max.packetloss_param      },
376         {"mos_max_jitter_A_pv",         PARAM_STR, &side_A_mos_stats.max.jitter_param          },
377         {"mos_max_roundtrip_A_pv",      PARAM_STR, &side_A_mos_stats.max.roundtrip_param       },
378         {"mos_average_A_pv",            PARAM_STR, &side_A_mos_stats.average.mos_param         },
379         {"mos_average_packetloss_A_pv", PARAM_STR, &side_A_mos_stats.average.packetloss_param  },
380         {"mos_average_jitter_A_pv",     PARAM_STR, &side_A_mos_stats.average.jitter_param      },
381         {"mos_average_roundtrip_A_pv",  PARAM_STR, &side_A_mos_stats.average.roundtrip_param   },
382         {"mos_average_samples_A_pv",    PARAM_STR, &side_A_mos_stats.average.samples_param     },
383
384         /* designated side B */
385         {"mos_B_label_pv",              PARAM_STR, &side_B_mos_stats.label_param               },
386         {"mos_min_B_pv",                PARAM_STR, &side_B_mos_stats.min.mos_param             },
387         {"mos_min_at_B_pv",             PARAM_STR, &side_B_mos_stats.min.at_param              },
388         {"mos_min_packetloss_B_pv",     PARAM_STR, &side_B_mos_stats.min.packetloss_param      },
389         {"mos_min_jitter_B_pv",         PARAM_STR, &side_B_mos_stats.min.jitter_param          },
390         {"mos_min_roundtrip_B_pv",      PARAM_STR, &side_B_mos_stats.min.roundtrip_param       },
391         {"mos_max_B_pv",                PARAM_STR, &side_B_mos_stats.max.mos_param             },
392         {"mos_max_at_B_pv",             PARAM_STR, &side_B_mos_stats.max.at_param              },
393         {"mos_max_packetloss_B_pv",     PARAM_STR, &side_B_mos_stats.max.packetloss_param      },
394         {"mos_max_jitter_B_pv",         PARAM_STR, &side_B_mos_stats.max.jitter_param          },
395         {"mos_max_roundtrip_B_pv",      PARAM_STR, &side_B_mos_stats.max.roundtrip_param       },
396         {"mos_average_B_pv",            PARAM_STR, &side_B_mos_stats.average.mos_param         },
397         {"mos_average_packetloss_B_pv", PARAM_STR, &side_B_mos_stats.average.packetloss_param  },
398         {"mos_average_jitter_B_pv",     PARAM_STR, &side_B_mos_stats.average.jitter_param      },
399         {"mos_average_roundtrip_B_pv",  PARAM_STR, &side_B_mos_stats.average.roundtrip_param   },
400         {"mos_average_samples_B_pv",    PARAM_STR, &side_B_mos_stats.average.samples_param     },
401
402         {0, 0, 0}
403 };
404
405 struct module_exports exports = {
406         "rtpengine",
407         DEFAULT_DLFLAGS, /* dlopen flags */
408         cmds,
409         params,
410         0,           /* exported statistics */
411         0,           /* exported MI functions */
412         mod_pvs,     /* exported pseudo-variables */
413         0,           /* extra processes */
414         mod_init,
415         0,           /* reply processing */
416         mod_destroy, /* destroy function */
417         child_init
418 };
419
420 /* check if the node is already queried */
421 static int is_queried_node(struct rtpp_node *node, struct rtpp_node **queried_nodes_ptr, int queried_nodes)
422 {
423         int i;
424
425         if (!queried_nodes_ptr) {
426                 return 0;
427         }
428
429         for (i = 0; i < queried_nodes; i++) {
430                 if (node == queried_nodes_ptr[i]) {
431                         return 1;
432                 }
433         }
434
435         return 0;
436 }
437
438 /* hide the node from display and disable it permanent */
439 int rtpengine_delete_node(struct rtpp_node *rtpp_node)
440 {
441         rtpp_node->rn_displayed = 0;
442         rtpp_node->rn_disabled = RTPENGINE_MAX_RECHECK_TICKS;
443
444         return 1;
445 }
446
447
448 int rtpengine_delete_node_set(struct rtpp_set *rtpp_list)
449 {
450         struct rtpp_node *rtpp_node;
451
452         lock_get(rtpp_list->rset_lock);
453         for(rtpp_node = rtpp_list->rn_first; rtpp_node != NULL;
454                         rtpp_node = rtpp_node->rn_next) {
455                 rtpengine_delete_node(rtpp_node);
456         }
457         lock_release(rtpp_list->rset_lock);
458
459         return 1;
460 }
461
462
463 int rtpengine_delete_node_all()
464 {
465         struct rtpp_set *rtpp_list;
466
467         if (!rtpp_set_list) {
468                 return 1;
469         }
470
471         lock_get(rtpp_set_list->rset_head_lock);
472         for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
473                         rtpp_list = rtpp_list->rset_next) {
474                 rtpengine_delete_node_set(rtpp_list);
475         }
476         lock_release(rtpp_set_list->rset_head_lock);
477
478         return 1;
479 }
480
481
482 static int get_ip_type(char *str_addr)
483 {
484         struct addrinfo hint, *info = NULL;
485         int ret;
486
487         memset(&hint, '\0', sizeof hint);
488         hint.ai_family = PF_UNSPEC;
489         hint.ai_flags = AI_NUMERICHOST;
490
491         ret = getaddrinfo(str_addr, NULL, &hint, &info);
492         if (ret) {
493                 /* Invalid ip addinfos */
494                 return -1;
495         }
496
497         if(info->ai_family == AF_INET) {
498                 LM_DBG("%s is an ipv4 addinfos\n", str_addr);
499         } else if (info->ai_family == AF_INET6) {
500                 LM_DBG("%s is an ipv6 addinfos\n", str_addr);
501         } else {
502                 LM_DBG("%s is an unknown addinfos format AF=%d\n",str_addr, info->ai_family);
503                 freeaddrinfo(info);
504                 return -1;
505         }
506
507         ret = info->ai_family;
508
509         freeaddrinfo(info);
510
511         return ret;
512 }
513
514
515 static int get_ip_scope(char *str_addr)
516 {
517         struct ifaddrs *ifaddr, *ifa;
518         struct sockaddr_in6 *in6;
519         char str_if_ip[NI_MAXHOST];
520         int ret = -1;
521
522         if (getifaddrs(&ifaddr) == -1) {
523                 LM_ERR("getifaddrs() failed: %s\n", gai_strerror(ret));
524                 return -1;
525         }
526
527         for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
528                 in6 = (struct sockaddr_in6 *)ifa->ifa_addr;
529
530                 if (ifa->ifa_addr == NULL)
531                         continue;
532
533                 if (ifa->ifa_addr->sa_family != AF_INET6)
534                         continue;
535
536                 ret = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
537                 str_if_ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
538                 if (ret != 0) {
539                         LM_ERR("getnameinfo() failed: %s\n", gai_strerror(ret));
540                         return -1;
541                 }
542
543                 if (strstr(str_if_ip, str_addr)) {
544                         LM_INFO("dev: %-8s address: <%s> scope %d\n",
545                         ifa->ifa_name, str_if_ip, in6->sin6_scope_id);
546                         ret = in6->sin6_scope_id;
547                         break;
548                 }
549         }
550
551         freeifaddrs(ifaddr);
552
553         return ret;
554 }
555
556
557 static int bind_force_send_ip(int sock_idx)
558 {
559         struct sockaddr_in tmp, ip4addr;
560         struct sockaddr_in6 tmp6, ip6addr;
561         char str_addr[INET_ADDRSTRLEN];
562         char str_addr6[INET6_ADDRSTRLEN];
563         socklen_t sock_len = sizeof(struct sockaddr);
564         int ret, scope;
565
566         switch (force_send_ip_af) {
567                 case AF_INET:
568                         memset(&ip4addr, 0, sizeof(ip4addr));
569                         ip4addr.sin_family = AF_INET;
570                         ip4addr.sin_port = htons(0);
571                         if (inet_pton(AF_INET, force_send_ip_str, &ip4addr.sin_addr) != 1) {
572                                 LM_ERR("failed to parse IPv4 address %s\n", force_send_ip_str);
573                                 return -1;
574                         }
575
576                         if (bind(rtpp_socks[sock_idx], (struct sockaddr*)&ip4addr, sizeof(ip4addr)) < 0) {
577                                 LM_ERR("can't bind socket to required ipv4 interface\n");
578                                 return -1;
579                         }
580
581                         memset(&tmp, 0, sizeof(tmp));
582                         if (getsockname(rtpp_socks[sock_idx], (struct sockaddr *) &tmp, &sock_len))
583                                 LM_ERR("could not determine local socket name\n");
584                         else {
585                                 inet_ntop(AF_INET, &tmp.sin_addr, str_addr, INET_ADDRSTRLEN);
586                                 LM_DBG("Binding on %s:%d\n", str_addr, ntohs(tmp.sin_port));
587                         }
588
589                         break;
590
591                 case AF_INET6:
592                         if ((scope = get_ip_scope(force_send_ip_str)) < 0) {
593                                 LM_ERR("can't get the ipv6 interface scope\n");
594                                 return -1;
595                         }
596                         memset(&ip6addr, 0, sizeof(ip6addr));
597                         ip6addr.sin6_family = AF_INET6;
598                         ip6addr.sin6_port = htons(0);
599                         ip6addr.sin6_scope_id = scope;
600                         if (inet_pton(AF_INET6, force_send_ip_str, &ip6addr.sin6_addr) != 1) {
601                                 LM_ERR("failed to parse IPv6 address %s\n", force_send_ip_str);
602                                 return -1;
603                         }
604
605                         if ((ret = bind(rtpp_socks[sock_idx], (struct sockaddr*)&ip6addr, sizeof(ip6addr))) < 0) {
606                                 LM_ERR("can't bind socket to required ipv6 interface\n");
607                                 LM_ERR("ret=%d errno=%d\n", ret, errno);
608                                 return -1;
609                         }
610
611                         memset(&tmp6, 0, sizeof(tmp6));
612                         if (getsockname(rtpp_socks[sock_idx], (struct sockaddr *) &tmp6, &sock_len))
613                                 LM_ERR("could not determine local socket name\n");
614                         else {
615                                 inet_ntop(AF_INET6, &tmp6.sin6_addr, str_addr6, INET6_ADDRSTRLEN);
616                                 LM_DBG("Binding on ipv6 %s:%d\n", str_addr6, ntohs(tmp6.sin6_port));
617                         }
618
619                         break;
620
621                 default:
622                         LM_DBG("force_send_ip_str not specified in .cfg file!\n");
623                         break;
624         }
625
626         return 0;
627 }
628
629 static inline int str_cmp(const str *a , const str *b) {
630         return ! (a->len == b->len && ! strncmp(a->s, b->s, a->len));
631 }
632
633 static inline int str_eq(const str *p, const char *q) {
634         int l = strlen(q);
635         if (p->len != l)
636                 return 0;
637         if (memcmp(p->s, q, l))
638                 return 0;
639         return 1;
640 }
641
642 static inline str str_prefix(const str *p, const char *q) {
643         str ret = STR_NULL;
644         int l = strlen(q);
645         if (p->len < l)
646                 return ret;
647         if (memcmp(p->s, q, l))
648                 return ret;
649         ret = *p;
650         ret.s += l;
651         ret.len -= l;
652         return ret;
653 }
654
655
656 static int rtpengine_set_store(modparam_t type, void * val){
657
658         char * p;
659         int len;
660
661         p = (char* )val;
662
663         if(p==0 || *p=='\0'){
664                 return 0;
665         }
666
667         if(rtpp_sets==0){
668                 rtpp_strings = (char**)pkg_malloc(sizeof(char*));
669                 if(!rtpp_strings){
670                         LM_ERR("no pkg memory left\n");
671                         return -1;
672                 }
673         } else {/*realloc to make room for the current set*/
674                 rtpp_strings = (char**)pkg_realloc(rtpp_strings, (rtpp_sets+1)* sizeof(char*));
675                 if(!rtpp_strings){
676                         LM_ERR("no pkg memory left\n");
677                         return -1;
678                 }
679         }
680
681         /*allocate for the current set of urls*/
682         len = strlen(p);
683         rtpp_strings[rtpp_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
684
685         if(!rtpp_strings[rtpp_sets]){
686                 LM_ERR("no pkg memory left\n");
687                 return -1;
688         }
689
690         memcpy(rtpp_strings[rtpp_sets], p, len);
691         rtpp_strings[rtpp_sets][len] = '\0';
692         rtpp_sets++;
693
694         return 0;
695 }
696
697 struct rtpp_node *get_rtpp_node(struct rtpp_set *rtpp_list, str *url)
698 {
699         struct rtpp_node *rtpp_node;
700
701         if (rtpp_list == NULL) {
702                 return NULL;
703         }
704
705         lock_get(rtpp_list->rset_lock);
706         rtpp_node = rtpp_list->rn_first;
707         while (rtpp_node) {
708                 if (str_cmp(&rtpp_node->rn_url, url) == 0) {
709                         lock_release(rtpp_list->rset_lock);
710                         return rtpp_node;
711                 }
712                 rtpp_node = rtpp_node->rn_next;
713         }
714         lock_release(rtpp_list->rset_lock);
715
716         return NULL;
717 }
718
719 struct rtpp_set *get_rtpp_set(unsigned int set_id)
720 {
721         struct rtpp_set * rtpp_list;
722         unsigned int my_current_id = 0;
723         int new_list;
724
725 #if DEFAULT_RTPP_SET_ID > 0
726         if (set_id < DEFAULT_RTPP_SET_ID )
727         {
728                 LM_ERR(" invalid rtpproxy set value [%u]\n", set_id);
729                 return NULL;
730         }
731 #endif
732
733         my_current_id = set_id;
734         /*search for the current_id*/
735         lock_get(rtpp_set_list->rset_head_lock);
736         rtpp_list = rtpp_set_list ? rtpp_set_list->rset_first : 0;
737         while (rtpp_list != 0 && rtpp_list->id_set!=my_current_id)
738                 rtpp_list = rtpp_list->rset_next;
739
740         if (rtpp_list==NULL)
741         {       /*if a new id_set : add a new set of rtpp*/
742                 rtpp_list = shm_malloc(sizeof(struct rtpp_set));
743                 if(!rtpp_list)
744                 {
745                         lock_release(rtpp_set_list->rset_head_lock);
746                         LM_ERR("no shm memory left to create new rtpproxy set %u\n", my_current_id);
747                         return NULL;
748                 }
749                 memset(rtpp_list, 0, sizeof(struct rtpp_set));
750                 rtpp_list->id_set = my_current_id;
751                 rtpp_list->rset_lock = lock_alloc();
752                 if (!rtpp_list->rset_lock) {
753                         lock_release(rtpp_set_list->rset_head_lock);
754                         LM_ERR("no shm memory left to create rtpproxy set lock\n");
755                         shm_free(rtpp_list);
756                         rtpp_list = NULL;
757                         return NULL;
758                 }
759                 if (lock_init(rtpp_list->rset_lock) == 0) {
760                         lock_release(rtpp_set_list->rset_head_lock);
761                         LM_ERR("could not init rtpproxy set lock\n");
762                         lock_dealloc((void*)rtpp_list->rset_lock);
763                         rtpp_list->rset_lock = NULL;
764                         shm_free(rtpp_list);
765                         rtpp_list = NULL;
766                         return NULL;
767                 }
768                 new_list = 1;
769         }
770         else {
771                 new_list = 0;
772         }
773
774         if (new_list)
775         {
776                 /*update the list of set info*/
777                 if (!rtpp_set_list->rset_first)
778                 {
779                         rtpp_set_list->rset_first = rtpp_list;
780                 }
781                 else
782                 {
783                         rtpp_set_list->rset_last->rset_next = rtpp_list;
784                 }
785
786                 rtpp_set_list->rset_last = rtpp_list;
787                 rtpp_set_count++;
788
789                 if(my_current_id == DEFAULT_RTPP_SET_ID){
790                         default_rtpp_set = rtpp_list;
791                 }
792         }
793         lock_release(rtpp_set_list->rset_head_lock);
794
795         return rtpp_list;
796 }
797
798
799 int add_rtpengine_socks(struct rtpp_set * rtpp_list, char * rtpproxy,
800                         unsigned int weight, int disabled, unsigned int ticks, int isDB)
801 {
802         /* Make rtp proxies list. */
803         char *p, *p1, *p2, *plim;
804         struct rtpp_node *pnode;
805         struct rtpp_node *rtpp_node;
806         unsigned int local_weight, port;
807         str s1;
808
809         p = rtpproxy;
810         plim = p + strlen(p);
811
812         for(;;) {
813                 local_weight = weight;
814                 while (*p && isspace((int)*p))
815                         ++p;
816                 if (p >= plim)
817                         break;
818                 p1 = p;
819                 while (*p && !isspace((int)*p))
820                         ++p;
821                 if (p <= p1)
822                         break; /* may happen??? */
823                 p2 = p;
824
825                 /* if called for database, consider simple, single char *URL */
826                 /* if called for config, consider weight URL */
827                 if (!isDB) {
828                         /* Have weight specified? If yes, scan it */
829                         p2 = memchr(p1, '=', p - p1);
830                         if (p2 != NULL) {
831                                 local_weight = strtoul(p2 + 1, NULL, 10);
832                         } else {
833                                 p2 = p;
834                         }
835                 }
836
837                 pnode = shm_malloc(sizeof(struct rtpp_node));
838                 if (pnode == NULL) {
839                         LM_ERR("no shm memory left\n");
840                         return -1;
841                 }
842                 memset(pnode, 0, sizeof(*pnode));
843
844                 lock_get(rtpp_no_lock);
845                 pnode->idx = *rtpp_no;
846
847                 if (ticks == RTPENGINE_MAX_RECHECK_TICKS) {
848                         pnode->rn_recheck_ticks = ticks;
849                 } else {
850                         pnode->rn_recheck_ticks = ticks + get_ticks();
851                 }
852                 pnode->rn_weight = local_weight;
853                 pnode->rn_umode = 0;
854                 pnode->rn_disabled = disabled;
855                 pnode->rn_displayed = 1;
856                 pnode->rn_url.s = shm_malloc(p2 - p1 + 1);
857                 if (pnode->rn_url.s == NULL) {
858                         lock_release(rtpp_no_lock);
859                         shm_free(pnode);
860                         LM_ERR("no shm memory left\n");
861                         return -1;
862                 }
863                 memmove(pnode->rn_url.s, p1, p2 - p1);
864                 pnode->rn_url.s[p2 - p1] = 0;
865                 pnode->rn_url.len = p2-p1;
866
867                 /* Leave only address in rn_address */
868                 pnode->rn_address = pnode->rn_url.s;
869                 if (strncasecmp(pnode->rn_address, "udp:", 4) == 0) {
870                         pnode->rn_umode = 1;
871                         pnode->rn_address += 4;
872                 } else if (strncasecmp(pnode->rn_address, "udp6:", 5) == 0) {
873                         pnode->rn_umode = 6;
874                         pnode->rn_address += 5;
875                 } else if (strncasecmp(pnode->rn_address, "unix:", 5) == 0) {
876                         pnode->rn_umode = 0;
877                         pnode->rn_address += 5;
878                 } else {
879                         lock_release(rtpp_no_lock);
880                         LM_WARN("Node address must start with 'udp:' or 'udp6:' or 'unix:'. Ignore '%s'.\n", pnode->rn_address);
881                         shm_free(pnode->rn_url.s);
882                         shm_free(pnode);
883
884                         if (!isDB) {
885                                 continue;
886                         } else {
887                                 return 0;
888                         }
889                 }
890
891                 /* Check the rn_address is 'hostname:port' */
892                 /* Check the rn_address port is valid */
893                 p1 = strchr(pnode->rn_address, ':');
894                 if (p1 != NULL) {
895                         p1++;
896                 }
897
898                 if (p1 != NULL && p1 != '\0') {
899                         s1.s = p1;
900                         s1.len = strlen(p1);
901                         if (str2int(&s1, &port) < 0 || port > 0xFFFF) {
902                                 lock_release(rtpp_no_lock);
903                                 LM_WARN("Node address must end with a valid port number. Ignore '%s'.\n", pnode->rn_address);
904                                 shm_free(pnode->rn_url.s);
905                                 shm_free(pnode);
906
907                                 if (!isDB) {
908                                         continue;
909                                 } else {
910                                         return 0;
911                                 }
912                         }
913                 }
914
915                 /* If node found in set, update it */
916                 rtpp_node = get_rtpp_node(rtpp_list, &pnode->rn_url);
917
918                 lock_get(rtpp_list->rset_lock);
919                 if (rtpp_node) {
920                         rtpp_node->rn_disabled = pnode->rn_disabled;
921                         rtpp_node->rn_displayed = pnode->rn_displayed;
922                         rtpp_node->rn_recheck_ticks = pnode->rn_recheck_ticks;
923                         rtpp_node->rn_weight = pnode->rn_weight;
924                         lock_release(rtpp_list->rset_lock);
925                         lock_release(rtpp_no_lock);
926
927                         shm_free(pnode->rn_url.s);
928                         shm_free(pnode);
929
930                         if (!isDB) {
931                                 continue;
932                         } else {
933                                 return 0;
934                         }
935                 }
936
937                 if (rtpp_list->rn_first == NULL) {
938                         rtpp_list->rn_first = pnode;
939                 } else {
940                         rtpp_list->rn_last->rn_next = pnode;
941                 }
942
943                 rtpp_list->rn_last = pnode;
944                 rtpp_list->rtpp_node_count++;
945                 lock_release(rtpp_list->rset_lock);
946
947                 *rtpp_no = *rtpp_no + 1;
948                 lock_release(rtpp_no_lock);
949
950                 if (!isDB) {
951                         continue;
952                 } else {
953                         return 0;
954                 }
955         }
956         return 0;
957 }
958
959
960 /* 0 - succes
961  * -1 - erorr
962  * */
963 static int rtpengine_add_rtpengine_set(char * rtp_proxies, unsigned int weight, int disabled, unsigned int ticks)
964 {
965         char *p,*p2;
966         struct rtpp_set * rtpp_list;
967         unsigned int my_current_id;
968         str id_set;
969
970         /* empty definition? */
971         p= rtp_proxies;
972         if(!p || *p=='\0'){
973                 return 0;
974         }
975
976         for(;*p && isspace(*p);p++);
977         if(*p=='\0'){
978                 return 0;
979         }
980
981         rtp_proxies = strstr(p, "==");
982         if(rtp_proxies){
983                 if(*(rtp_proxies +2)=='\0'){
984                         LM_ERR("script error -invalid rtp proxy list!\n");
985                         return -1;
986                 }
987
988                 *rtp_proxies = '\0';
989                 p2 = rtp_proxies-1;
990                 for(;isspace(*p2); *p2 = '\0',p2--);
991                 id_set.s = p;   id_set.len = p2 - p+1;
992
993                 if(id_set.len <= 0 ||str2int(&id_set, &my_current_id)<0 ){
994                 LM_ERR("script error -invalid set_id value!\n");
995                         return -1;
996                 }
997
998                 rtp_proxies+=2;
999         }else{
1000                 rtp_proxies = p;
1001                 my_current_id = DEFAULT_RTPP_SET_ID;
1002         }
1003
1004         for(;*rtp_proxies && isspace(*rtp_proxies);rtp_proxies++);
1005
1006         if(!(*rtp_proxies)){
1007                 LM_ERR("script error -empty rtp_proxy list\n");
1008                 return -1;;
1009         }
1010
1011         /*search for the current_id*/
1012         rtpp_list = get_rtpp_set(my_current_id);
1013
1014         if (rtpp_list != NULL)
1015         {
1016
1017                 if (add_rtpengine_socks(rtpp_list, rtp_proxies, weight, disabled, ticks, 0) != 0)
1018                         goto error;
1019                 else
1020                         return 0;
1021         }
1022
1023 error:
1024         return -1;
1025 }
1026
1027
1028 static int fixup_set_id(void ** param, int param_no)
1029 {
1030         int int_val;
1031         unsigned int set_id;
1032         struct rtpp_set* rtpp_list;
1033         rtpp_set_link_t *rtpl = NULL;
1034         str s;
1035
1036         rtpl = (rtpp_set_link_t*)pkg_malloc(sizeof(rtpp_set_link_t));
1037         if(rtpl==NULL) {
1038                 LM_ERR("no more pkg memory\n");
1039                 return -1;
1040         }
1041         memset(rtpl, 0, sizeof(rtpp_set_link_t));
1042         s.s = (char*)*param;
1043         s.len = strlen(s.s);
1044
1045         if(s.s[0] == PV_MARKER) {
1046                 int_val = pv_locate_name(&s);
1047                 if(int_val<0 || int_val!=s.len) {
1048                         LM_ERR("invalid parameter %s\n", s.s);
1049                         return -1;
1050                 }
1051                 rtpl->rpv = pv_cache_get(&s);
1052                 if(rtpl->rpv == NULL) {
1053                         LM_ERR("invalid pv parameter %s\n", s.s);
1054                         pkg_free(rtpl);
1055                         return -1;
1056                 }
1057         } else {
1058                 int_val = str2int(&s, &set_id);
1059                 if (int_val == 0) {
1060                         pkg_free(*param);
1061                         if((rtpp_list = select_rtpp_set(set_id)) ==0){
1062                                 LM_ERR("rtpp_proxy set %u not configured\n", set_id);
1063                                 pkg_free(rtpl);
1064                                 return E_CFG;
1065                         }
1066                         rtpl->rset = rtpp_list;
1067                 } else {
1068                         LM_ERR("bad number <%s>\n",     (char *)(*param));
1069                         pkg_free(rtpl);
1070                         return E_CFG;
1071                 }
1072         }
1073         *param = (void*)rtpl;
1074         return 0;
1075 }
1076
1077 static int rtpp_test_ping(struct rtpp_node *node)
1078 {
1079         bencode_buffer_t bencbuf;
1080         bencode_item_t *dict;
1081         char *cp;
1082         int ret;
1083
1084         if (bencode_buffer_init(&bencbuf)) {
1085                 return -1;
1086         }
1087         dict = bencode_dictionary(&bencbuf);
1088         bencode_dictionary_add_string(dict, "command", command_strings[OP_PING]);
1089
1090         if (bencbuf.error) {
1091                 goto error;
1092         }
1093
1094         cp = send_rtpp_command(node, dict, &ret);
1095         if (!cp) {
1096                 goto error;
1097         }
1098
1099         dict = bencode_decode_expect(&bencbuf, cp, ret, BENCODE_DICTIONARY);
1100         if (!dict || bencode_dictionary_get_strcmp(dict, "result", "pong")) {
1101                 goto error;
1102         }
1103
1104         bencode_buffer_free(&bencbuf);
1105         return 0;
1106
1107 error:
1108         bencode_buffer_free(&bencbuf);
1109         return -1;
1110 }
1111
1112
1113 static void rtpengine_rpc_reload(rpc_t* rpc, void* ctx)
1114 {
1115         if (rtpp_db_url.s == NULL) {
1116                 // no database
1117                 rpc->fault(ctx, 500, "No Database URL");
1118                 return;
1119         }
1120
1121         if (init_rtpproxy_db() < 0) {
1122                 // fail reloading from database
1123                 rpc->fault(ctx, 500, "Failed reloading db");
1124                 return;
1125         }
1126
1127         if (build_rtpp_socks()) {
1128                 rpc->fault(ctx, 500, "Out of memory");
1129                 return;
1130         }
1131 }
1132
1133 static int rtpengine_rpc_iterate(rpc_t* rpc, void* ctx, const str *rtpp_url,
1134                 int (*cb)(struct rtpp_node *, struct rtpp_set *, void *), void *data)
1135 {
1136         struct rtpp_set *rtpp_list;
1137         struct rtpp_node *crt_rtpp;
1138         int found = RPC_FOUND_NONE, err = 0;
1139         int ret;
1140
1141         if (build_rtpp_socks()) {
1142                 rpc->fault(ctx, 500, "Out of memory");
1143                 return -1;
1144         }
1145
1146         if (!rtpp_set_list) {
1147                 rpc->fault(ctx, 404, "Instance not found (no sets loaded)");
1148                 return -1;
1149         }
1150
1151         /* found a matching all - show all rtpp */
1152         if (strncmp("all", rtpp_url->s, 3) == 0) {
1153                 found = RPC_FOUND_ALL;
1154         }
1155
1156         lock_get(rtpp_set_list->rset_head_lock);
1157         for (rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
1158                         rtpp_list = rtpp_list->rset_next) {
1159
1160                 lock_get(rtpp_list->rset_lock);
1161                 for (crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
1162                                 crt_rtpp = crt_rtpp->rn_next) {
1163
1164                         if (!crt_rtpp->rn_displayed) {
1165                                 continue;
1166                         }
1167
1168                         /* found a matching rtpp - ping it */
1169                         if (found == RPC_FOUND_ALL ||
1170                            (crt_rtpp->rn_url.len == rtpp_url->len &&
1171                            strncmp(crt_rtpp->rn_url.s, rtpp_url->s, rtpp_url->len) == 0)) {
1172
1173                                 ret = cb(crt_rtpp, rtpp_list, data);
1174                                 if (ret) {
1175                                         err = 1;
1176                                         break;
1177                                 }
1178
1179                                 if (found == RPC_FOUND_NONE) {
1180                                         found = RPC_FOUND_ONE;
1181                                 }
1182                         }
1183                 }
1184                 lock_release(rtpp_list->rset_lock);
1185
1186                 if (err)
1187                         break;
1188         }
1189         lock_release(rtpp_set_list->rset_head_lock);
1190
1191         if (err)
1192                 return -1;
1193
1194         if (found == RPC_FOUND_NONE) {
1195                 rpc->fault(ctx, 404, "Instance not found");
1196                 return -1;
1197         }
1198
1199         return found;
1200 }
1201
1202 static int add_rtpp_node_info (void *ptrsp, struct rtpp_node *crt_rtpp, struct rtpp_set *rtpp_list)
1203 {
1204         void *vh;
1205         void **ptrs = ptrsp;
1206         rpc_t *rpc;
1207         void *ctx;
1208         int rtpp_ticks;
1209
1210         rpc = ptrs[0];
1211         ctx = ptrs[1];
1212
1213         if (rpc->add(ctx, "{", &vh) < 0) {
1214                 rpc->fault(ctx, 500, "Server error");
1215                 return -1;
1216         }
1217
1218         rpc->struct_add(vh, "Sddd",
1219                         "url", &crt_rtpp->rn_url,
1220                         "set", rtpp_list->id_set,
1221                         "index", crt_rtpp->idx,
1222                         "weight", crt_rtpp->rn_weight);
1223
1224         if ((1 == crt_rtpp->rn_disabled ) && (crt_rtpp->rn_recheck_ticks == RTPENGINE_MAX_RECHECK_TICKS)) {
1225                 rpc->struct_add(vh, "s", "disabled", "1(permanent)");
1226         } else {
1227                 rpc->struct_add(vh, "d", "disabled", crt_rtpp->rn_disabled);
1228         }
1229
1230         if (crt_rtpp->rn_recheck_ticks == RTPENGINE_MAX_RECHECK_TICKS) {
1231                 rpc->struct_add(vh, "s", "recheck_ticks", "N/A");
1232         } else {
1233                 rtpp_ticks = crt_rtpp->rn_recheck_ticks - get_ticks();
1234                 rtpp_ticks = rtpp_ticks < 0 ? 0 : rtpp_ticks;
1235                 rpc->struct_add(vh, "d", "recheck_ticks", rtpp_ticks);
1236         }
1237
1238         return 0;
1239 }
1240
1241 static int rtpengine_iter_cb_enable(struct rtpp_node *crt_rtpp, struct rtpp_set *rtpp_list, void *flagp)
1242 {
1243         int *flag = flagp;
1244
1245         /* do ping when try to enable the rtpp */
1246         if (*flag) {
1247
1248                 /* if ping success, enable the rtpp and reset ticks */
1249                 if (rtpp_test_ping(crt_rtpp) == 0) {
1250                         crt_rtpp->rn_disabled = 0;
1251                         crt_rtpp->rn_recheck_ticks = RTPENGINE_MIN_RECHECK_TICKS;
1252
1253                 /* if ping fail, disable the rtpps but _not_ permanently*/
1254                 } else {
1255                         crt_rtpp->rn_recheck_ticks = get_ticks() + cfg_get(rtpengine,rtpengine_cfg,rtpengine_disable_tout);
1256                         crt_rtpp->rn_disabled = 1;
1257                         *flag = 2; /* return value to caller */
1258                 }
1259
1260         /* do not ping when disable the rtpp; disable it permanenty */
1261         } else {
1262                 crt_rtpp->rn_disabled = 1;
1263                 crt_rtpp->rn_recheck_ticks = RTPENGINE_MAX_RECHECK_TICKS;
1264         }
1265
1266         return 0;
1267 }
1268
1269 static void rtpengine_rpc_enable(rpc_t* rpc, void* ctx)
1270 {
1271         void *vh;
1272         str rtpp_url;
1273         int flag, found;
1274
1275         if (rpc->scan(ctx, "Sd", &rtpp_url, &flag) < 2) {
1276                 rpc->fault(ctx, 500, "Not enough parameters");
1277                 return;
1278         }
1279
1280         flag = flag ? 1 : 0; /* also used as a return value */
1281
1282         found = rtpengine_rpc_iterate(rpc, ctx, &rtpp_url, rtpengine_iter_cb_enable, &flag);
1283         if (found == -1)
1284                 return;
1285
1286         if (rpc->add(ctx, "{", &vh) < 0) {
1287                 rpc->fault(ctx, 500, "Server error");
1288                 return;
1289         }
1290
1291         rpc->struct_add(vh, "S", "url", &rtpp_url);
1292
1293         if (flag == 0)
1294                 rpc->struct_add(vh, "s", "status", "disable");
1295         else if (flag == 1)
1296                 rpc->struct_add(vh, "s", "status", "enable");
1297         else
1298                 rpc->struct_add(vh, "s", "status", "fail");
1299 }
1300
1301 static int rtpengine_iter_cb_show(struct rtpp_node *crt_rtpp, struct rtpp_set *rtpp_list, void *ptrsp)
1302 {
1303         if (add_rtpp_node_info(ptrsp, crt_rtpp, rtpp_list) < 0)
1304                 return -1;
1305         return 0;
1306 }
1307
1308 static void rtpengine_rpc_show(rpc_t* rpc, void* ctx)
1309 {
1310         str rtpp_url;
1311         void *ptrs[2] = {rpc, ctx};
1312
1313         if (rpc->scan(ctx, "S", &rtpp_url) < 1) {
1314                 rpc->fault(ctx, 500, "Not enough parameters");
1315                 return;
1316         }
1317
1318         rtpengine_rpc_iterate(rpc, ctx, &rtpp_url, rtpengine_iter_cb_show, ptrs);
1319 }
1320
1321 static int rtpengine_iter_cb_ping(struct rtpp_node *crt_rtpp, struct rtpp_set *rtpp_list, void *data)
1322 {
1323         int *found_rtpp_disabled = data;
1324
1325         /* if ping fail */
1326         if (rtpp_test_ping(crt_rtpp) < 0) {
1327                 crt_rtpp->rn_recheck_ticks = get_ticks() + cfg_get(rtpengine,rtpengine_cfg,rtpengine_disable_tout);
1328                 *found_rtpp_disabled = 1;
1329                 crt_rtpp->rn_disabled = 1;
1330         }
1331
1332         return 0;
1333 }
1334
1335 static void rtpengine_rpc_ping(rpc_t* rpc, void* ctx)
1336 {
1337         void *vh;
1338         int found;
1339         int found_rtpp_disabled = 0;
1340         str rtpp_url;
1341
1342         if (rpc->scan(ctx, "S", &rtpp_url) < 1) {
1343                 rpc->fault(ctx, 500, "Not enough parameters");
1344                 return;
1345         }
1346
1347         found = rtpengine_rpc_iterate(rpc, ctx, &rtpp_url, rtpengine_iter_cb_ping, &found_rtpp_disabled);
1348         if (found == -1)
1349                 return;
1350
1351         if (rpc->add(ctx, "{", &vh) < 0) {
1352                 rpc->fault(ctx, 500, "Server error");
1353                 return;
1354         }
1355
1356         rpc->struct_add(vh, "Ss",
1357                         "url", &rtpp_url,
1358                         "status", (found_rtpp_disabled ? "fail" : "success"));
1359 }
1360
1361 static void rtpengine_rpc_get_hash_total(rpc_t* rpc, void* ctx)
1362 {
1363         rpc->add(ctx, "u", rtpengine_hash_table_total());
1364 }
1365
1366
1367 static const char* rtpengine_rpc_reload_doc[2] = {
1368         "Reload rtpengine proxies from database", 0
1369 };
1370 static const char* rtpengine_rpc_ping_doc[2] = {
1371         "Ping an rtpengine instance", 0
1372 };
1373 static const char* rtpengine_rpc_show_doc[2] = {
1374         "Get details about an rtpengine instance", 0
1375 };
1376 static const char* rtpengine_rpc_enable_doc[2] = {
1377         "Enable or disable an rtpengine instance", 0
1378 };
1379 static const char* rtpengine_rpc_get_hash_total_doc[2] = {
1380         "Get total number of entries in hash table", 0
1381 };
1382
1383 rpc_export_t rtpengine_rpc[] = {
1384         {"rtpengine.reload", rtpengine_rpc_reload, rtpengine_rpc_reload_doc, 0},
1385         {"rtpengine.ping", rtpengine_rpc_ping, rtpengine_rpc_ping_doc, 0},
1386         {"rtpengine.show", rtpengine_rpc_show, rtpengine_rpc_show_doc, RET_ARRAY},
1387         {"rtpengine.enable", rtpengine_rpc_enable, rtpengine_rpc_enable_doc, 0},
1388         {"rtpengine.get_hash_total", rtpengine_rpc_get_hash_total, rtpengine_rpc_get_hash_total_doc, 0},
1389         {0, 0, 0, 0}
1390 };
1391
1392 static int rtpengine_rpc_init(void)
1393 {
1394         if (rpc_register_array(rtpengine_rpc)!=0)
1395         {
1396                 LM_ERR("failed to register RPC commands\n");
1397                 return -1;
1398         }
1399         return 0;
1400 }
1401
1402 static int
1403 mod_init(void)
1404 {
1405         int i;
1406         pv_spec_t *avp_spec;
1407         unsigned short avp_flags;
1408         str s;
1409
1410         if(rtpengine_rpc_init()<0)
1411         {
1412                 LM_ERR("failed to register RPC commands\n");
1413                 return -1;
1414         }
1415
1416         rtpp_no = (unsigned int*)shm_malloc(sizeof(unsigned int));
1417         if (!rtpp_no) {
1418                 LM_ERR("no more shm memory for rtpp_no\n");
1419                 return -1;
1420         }
1421         *rtpp_no = 0;
1422
1423         rtpp_no_lock = lock_alloc();
1424         if (!rtpp_no_lock) {
1425                 LM_ERR("no more shm memory for rtpp_no_lock\n");
1426                 return -1;
1427         }
1428
1429         if (lock_init(rtpp_no_lock) == 0) {
1430                 LM_ERR("could not init rtpp_no_lock\n");
1431                 return -1;
1432         }
1433
1434         /* initialize the list of set; mod_destroy does shm_free() if fail */
1435         if (!rtpp_set_list) {
1436                 rtpp_set_list = shm_malloc(sizeof(struct rtpp_set_head));
1437                 if(!rtpp_set_list){
1438                         LM_ERR("no shm memory left to create list of proxysets\n");
1439                         return -1;
1440                 }
1441                 memset(rtpp_set_list, 0, sizeof(struct rtpp_set_head));
1442
1443                 rtpp_set_list->rset_head_lock = lock_alloc();
1444                 if (!rtpp_set_list->rset_head_lock) {
1445                         LM_ERR("no shm memory left to create list of proxysets lock\n");
1446                         return -1;
1447                 }
1448
1449                 if (lock_init(rtpp_set_list->rset_head_lock) == 0) {
1450                         LM_ERR("could not init rtpproxy list of proxysets lock\n");
1451                         return -1;
1452                 }
1453         }
1454
1455         if (rtpp_db_url.s == NULL)
1456         {
1457                 /* storing the list of rtp proxy sets in shared memory*/
1458                 for(i=0;i<rtpp_sets;i++){
1459                         if(rtpengine_add_rtpengine_set(rtpp_strings[i], 1, 0, 0) !=0){
1460                                 for(;i<rtpp_sets;i++)
1461                                         if(rtpp_strings[i])
1462                                                 pkg_free(rtpp_strings[i]);
1463                                 pkg_free(rtpp_strings);
1464                                 return -1;
1465                         }
1466                         if(rtpp_strings[i])
1467                                 pkg_free(rtpp_strings[i]);
1468                 }
1469         }
1470         else
1471         {
1472                 LM_INFO("Loading rtp proxy definitions from DB\n");
1473                 if ( init_rtpproxy_db() < 0)
1474                 {
1475                         LM_ERR("error while loading rtp proxies from database\n");
1476                         return -1;
1477                 }
1478         }
1479
1480         /* any rtpproxy configured? */
1481         if (rtpp_set_list)
1482                 default_rtpp_set = select_rtpp_set(DEFAULT_RTPP_SET_ID);
1483
1484         if (rtp_inst_pv_param.s) {
1485                 rtp_inst_pv_param.len = strlen(rtp_inst_pv_param.s);
1486                 rtp_inst_pvar = pv_cache_get(&rtp_inst_pv_param);
1487                 if ((rtp_inst_pvar == NULL) ||
1488                    ((rtp_inst_pvar->type != PVT_AVP) &&
1489                    (rtp_inst_pvar->type != PVT_XAVP) &&
1490                    (rtp_inst_pvar->type != PVT_SCRIPTVAR))) {
1491                         LM_ERR("Invalid pvar name <%.*s>\n", rtp_inst_pv_param.len, rtp_inst_pv_param.s);
1492                         return -1;
1493                 }
1494         }
1495
1496         if (pv_parse_var(&extra_id_pv_param, &extra_id_pv, NULL))
1497                 return -1;
1498
1499         if (mos_label_stats_parse(&global_mos_stats))
1500                 return -1;
1501         if (mos_label_stats_parse(&side_A_mos_stats))
1502                 return -1;
1503         if (mos_label_stats_parse(&side_B_mos_stats))
1504                 return -1;
1505
1506         if (setid_avp_param) {
1507                 s.s = setid_avp_param; s.len = strlen(s.s);
1508                 avp_spec = pv_cache_get(&s);
1509                 if (avp_spec==NULL || (avp_spec->type != PVT_AVP)) {
1510                         LM_ERR("malformed or non AVP definition <%s>\n", setid_avp_param);
1511                         return -1;
1512                 }
1513                 if (pv_get_avp_name(0, &(avp_spec->pvp), &setid_avp, &avp_flags) != 0) {
1514                         LM_ERR("invalid AVP definition <%s>\n", setid_avp_param);
1515                         return -1;
1516                 }
1517                 setid_avp_type = avp_flags;
1518         }
1519
1520         if (write_sdp_pvar_str.len > 0) {
1521                 write_sdp_pvar = pv_cache_get(&write_sdp_pvar_str);
1522                 if (write_sdp_pvar == NULL
1523                         || (write_sdp_pvar->type != PVT_AVP &&  write_sdp_pvar->type != PVT_SCRIPTVAR) ) {
1524                         LM_ERR("write_sdp_pv: not a valid AVP or VAR definition <%.*s>\n",
1525                                 write_sdp_pvar_str.len, write_sdp_pvar_str.s);
1526                         return -1;
1527                 }
1528         }
1529
1530         if (read_sdp_pvar_str.len > 0) {
1531                 read_sdp_pvar = pv_cache_get(&read_sdp_pvar_str);
1532                 if (read_sdp_pvar == NULL
1533                         || (read_sdp_pvar->type != PVT_AVP &&  read_sdp_pvar->type != PVT_SCRIPTVAR) ) {
1534                         LM_ERR("read_sdp_pv: not a valid AVP or VAR definition <%.*s>\n",
1535                                 read_sdp_pvar_str.len, read_sdp_pvar_str.s);
1536                         return -1;
1537                 }
1538         }
1539
1540         if (rtpp_strings)
1541                 pkg_free(rtpp_strings);
1542
1543         if (load_tm_api( &tmb ) < 0)
1544         {
1545                 LM_DBG("could not load the TM-functions - answer-offer model"
1546                         " auto-detection is disabled\n");
1547                 memset(&tmb, 0, sizeof(struct tm_binds));
1548         }
1549
1550         /* Determine IP addr type (IPv4 or IPv6 allowed) */
1551         force_send_ip_af = get_ip_type(force_send_ip_str);
1552         if (force_send_ip_af != AF_INET && force_send_ip_af != AF_INET6 &&
1553            strlen(force_send_ip_str) > 0) {
1554                 LM_ERR("%s is an unknown address\n", force_send_ip_str);
1555                 return -1;
1556         }
1557
1558         /* init the hastable which keeps the call-id <-> selected_node relation */
1559         if (!rtpengine_hash_table_init(hash_table_size)) {
1560                 LM_ERR("rtpengine_hash_table_init(%d) failed!\n", hash_table_size);
1561                 return -1;
1562         } else {
1563                 LM_DBG("rtpengine_hash_table_init(%d) success!\n", hash_table_size);
1564         }
1565
1566         /* select the default set */
1567         default_rtpp_set = select_rtpp_set(setid_default);
1568         if (!default_rtpp_set) {
1569                 LM_NOTICE("Default rtpp set %u NOT found\n", setid_default);
1570         } else {
1571                 LM_DBG("Default rtpp set %u found\n", setid_default);
1572         }
1573
1574     if(cfg_declare("rtpengine", rtpengine_cfg_def, &default_rtpengine_cfg, cfg_sizeof(rtpengine), &rtpengine_cfg)){
1575         LM_ERR("Failed to declare the configuration\n");
1576         return -1;
1577     }
1578
1579
1580         return 0;
1581 }
1582
1583 static int build_rtpp_socks() {
1584         int n, i;
1585         char *cp;
1586         struct addrinfo hints, *res;
1587         struct rtpp_set  *rtpp_list;
1588         struct rtpp_node *pnode;
1589         unsigned int current_rtpp_no;
1590 #ifdef IP_MTU_DISCOVER
1591         int ip_mtu_discover = IP_PMTUDISC_DONT;
1592 #endif
1593
1594         lock_get(rtpp_no_lock);
1595         current_rtpp_no = *rtpp_no;
1596         lock_release(rtpp_no_lock);
1597
1598         if (current_rtpp_no == rtpp_socks_size)
1599                 return 0;
1600
1601         // close current sockets
1602         for (i = 0; i < rtpp_socks_size; i++) {
1603                 if (rtpp_socks[i] >= 0) {
1604                         close(rtpp_socks[i]);
1605                         rtpp_socks[i] = -1;
1606                 }
1607         }
1608
1609         rtpp_socks_size = current_rtpp_no;
1610         rtpp_socks = (int*)pkg_realloc(rtpp_socks, sizeof(int)*(rtpp_socks_size));
1611         if (!rtpp_socks) {
1612                 LM_ERR("no more pkg memory for rtpp_socks\n");
1613                 return -1;
1614         }
1615         memset(rtpp_socks, -1, sizeof(int)*(rtpp_socks_size));
1616
1617         lock_get(rtpp_set_list->rset_head_lock);
1618         for (rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
1619                 rtpp_list = rtpp_list->rset_next) {
1620
1621                 lock_get(rtpp_list->rset_lock);
1622                 for (pnode=rtpp_list->rn_first; pnode!=0; pnode = pnode->rn_next) {
1623                         char *hostname;
1624
1625                         if (pnode->rn_umode == 0) {
1626                                 rtpp_socks[pnode->idx] = -1;
1627                                 goto rptest;
1628                         }
1629
1630                         /*
1631                          * This is UDP or UDP6. Detect host and port; lookup host;
1632                          * do connect() in order to specify peer address
1633                          */
1634                         hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->rn_address) + 1));
1635                         if (hostname==NULL) {
1636                                 LM_ERR("no more pkg memory\n");
1637                                 rtpp_socks[pnode->idx] = -1;
1638                                 continue;
1639                         }
1640                         strcpy(hostname, pnode->rn_address);
1641
1642                         cp = strrchr(hostname, ':');
1643                         if (cp != NULL) {
1644                                 *cp = '\0';
1645                                 cp++;
1646                         }
1647                         if (cp == NULL || *cp == '\0')
1648                                 cp = CPORT;
1649
1650                         memset(&hints, 0, sizeof(hints));
1651                         hints.ai_flags = 0;
1652                         hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET;
1653                         hints.ai_socktype = SOCK_DGRAM;
1654                         if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
1655                                 LM_ERR("%s\n", gai_strerror(n));
1656                                 pkg_free(hostname);
1657                                 rtpp_socks[pnode->idx] = -1;
1658                                 continue;
1659                         }
1660                         pkg_free(hostname);
1661
1662                         rtpp_socks[pnode->idx] = socket((pnode->rn_umode == 6)
1663                                 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
1664                         if (rtpp_socks[pnode->idx] == -1) {
1665                                 LM_ERR("can't create socket\n");
1666                                 freeaddrinfo(res);
1667                                 continue;
1668                         }
1669
1670 #ifdef IP_MTU_DISCOVER
1671                         if (setsockopt(rtpp_socks[pnode->idx], IPPROTO_IP,
1672                                         IP_MTU_DISCOVER, &ip_mtu_discover,
1673                                         sizeof(ip_mtu_discover)))
1674                                 LM_WARN("Failed enable set MTU discovery socket option\n");
1675 #endif
1676
1677                         if (bind_force_send_ip(pnode->idx) == -1) {
1678                                 LM_ERR("can't bind socket\n");
1679                                 close(rtpp_socks[pnode->idx]);
1680                                 rtpp_socks[pnode->idx] = -1;
1681                                 freeaddrinfo(res);
1682                                 continue;
1683                         }
1684
1685                         if (connect(rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
1686                                 LM_ERR("can't connect to a RTP proxy\n");
1687                                 close(rtpp_socks[pnode->idx]);
1688                                 rtpp_socks[pnode->idx] = -1;
1689                                 freeaddrinfo(res);
1690                                 continue;
1691                         }
1692
1693                         freeaddrinfo(res);
1694 rptest:
1695                         pnode->rn_disabled = rtpp_test(pnode, 0, 1);
1696                 }
1697                 lock_release(rtpp_list->rset_lock);
1698         }
1699         lock_release(rtpp_set_list->rset_head_lock);
1700
1701         return 0;
1702 }
1703
1704 static int pv_parse_var(str *inp, pv_elem_t **outp, int *got_any) {
1705         if (inp->s && *inp->s) {
1706                 inp->len = strlen(inp->s);
1707                 if(pv_parse_format(inp, outp) < 0) {
1708                         LM_ERR("malformed PV string: %s\n", inp->s);
1709                         return -1;
1710                 }
1711                 if (got_any)
1712                         *got_any = 1;
1713         } else {
1714                 *outp = NULL;
1715         }
1716         return 0;
1717 }
1718
1719 static int minmax_pv_parse(struct minmax_mos_stats *s, int *got_any) {
1720         if (pv_parse_var(&s->mos_param, &s->mos_pv, got_any))
1721                 return -1;
1722         if (pv_parse_var(&s->at_param, &s->at_pv, got_any))
1723                 return -1;
1724         if (pv_parse_var(&s->packetloss_param, &s->packetloss_pv, got_any))
1725                 return -1;
1726         if (pv_parse_var(&s->jitter_param, &s->jitter_pv, got_any))
1727                 return -1;
1728         if (pv_parse_var(&s->roundtrip_param, &s->roundtrip_pv, got_any))
1729                 return -1;
1730         if (pv_parse_var(&s->samples_param, &s->samples_pv, got_any))
1731                 return -1;
1732         return 0;
1733 }
1734
1735 static int mos_label_stats_parse(struct minmax_mos_label_stats *mmls) {
1736         if (pv_parse_var(&mmls->label_param, &mmls->label_pv, &mmls->got_any_pvs))
1737                 return -1;
1738
1739         if (minmax_pv_parse(&mmls->min, &mmls->got_any_pvs))
1740                 return -1;
1741         if (minmax_pv_parse(&mmls->max, &mmls->got_any_pvs))
1742                 return -1;
1743         if (minmax_pv_parse(&mmls->average, &mmls->got_any_pvs))
1744                 return -1;
1745
1746         if (mmls->got_any_pvs)
1747                 got_any_mos_pvs = 1;
1748
1749         return 0;
1750 }
1751
1752
1753 static int
1754 child_init(int rank)
1755 {
1756         if(!rtpp_set_list)
1757                 return 0;
1758
1759         /* do not init sockets for PROC_INIT and main process when fork=yes */
1760         if(rank==PROC_INIT || (rank==PROC_MAIN && dont_fork==0)) {
1761                 return 0;
1762         }
1763
1764         mypid = getpid();
1765
1766         // vector of pointers to queried nodes
1767         queried_nodes_ptr = (struct rtpp_node**)pkg_malloc(MAX_RTPP_TRIED_NODES * sizeof(struct rtpp_node*));
1768         if (!queried_nodes_ptr) {
1769                 LM_ERR("no more pkg memory for queried_nodes_ptr\n");
1770                 return -1;
1771         }
1772         memset(queried_nodes_ptr, 0, MAX_RTPP_TRIED_NODES * sizeof(struct rtpp_node*));
1773
1774         /* Iterate known RTP proxies - create sockets */
1775         if (build_rtpp_socks())
1776                 return -1;
1777
1778         return 0;
1779 }
1780
1781
1782 static void mod_destroy(void)
1783 {
1784         struct rtpp_set * crt_list, * last_list;
1785         struct rtpp_node * crt_rtpp, *last_rtpp;
1786
1787         /*free the shared memory*/
1788         if (rtpp_no) {
1789                 shm_free(rtpp_no);
1790                 rtpp_no = NULL;
1791         }
1792
1793         if (rtpp_no_lock) {
1794                 lock_destroy(rtpp_no_lock);
1795                 lock_dealloc(rtpp_no_lock);
1796                 rtpp_no_lock = NULL;
1797         }
1798
1799         if (!rtpp_set_list) {
1800                 return;
1801         }
1802
1803         if (!rtpp_set_list->rset_head_lock) {
1804                 shm_free(rtpp_set_list);
1805                 rtpp_set_list = NULL;
1806                 return;
1807         }
1808
1809         lock_get(rtpp_set_list->rset_head_lock);
1810         for(crt_list = rtpp_set_list->rset_first; crt_list != NULL; ){
1811                 last_list = crt_list;
1812
1813                 if (!crt_list->rset_lock) {
1814                         crt_list = last_list->rset_next;
1815                         shm_free(last_list);
1816                         last_list = NULL;
1817                         continue;
1818                 }
1819
1820                 lock_get(last_list->rset_lock);
1821                 for(crt_rtpp = crt_list->rn_first; crt_rtpp != NULL;  ){
1822
1823                         if(crt_rtpp->rn_url.s)
1824                                 shm_free(crt_rtpp->rn_url.s);
1825
1826                         last_rtpp = crt_rtpp;
1827                         crt_rtpp = last_rtpp->rn_next;
1828                         shm_free(last_rtpp);
1829                 }
1830                 crt_list = last_list->rset_next;
1831                 lock_release(last_list->rset_lock);
1832
1833                 lock_destroy(last_list->rset_lock);
1834                 lock_dealloc((void*)last_list->rset_lock);
1835                 last_list->rset_lock = NULL;
1836
1837                 shm_free(last_list);
1838                 last_list = NULL;
1839         }
1840         lock_release(rtpp_set_list->rset_head_lock);
1841
1842         lock_destroy(rtpp_set_list->rset_head_lock);
1843         lock_dealloc((void*)rtpp_set_list->rset_head_lock);
1844         rtpp_set_list->rset_head_lock = NULL;
1845
1846         shm_free(rtpp_set_list);
1847         rtpp_set_list = NULL;
1848
1849         /* destroy the hastable which keeps the call-id <-> selected_node relation */
1850         if (!rtpengine_hash_table_destroy()) {
1851                 LM_ERR("rtpengine_hash_table_destroy() failed!\n");
1852         } else {
1853                 LM_DBG("rtpengine_hash_table_destroy() success!\n");
1854         }
1855 }
1856
1857
1858 static char * gencookie(void)
1859 {
1860         static char cook[34];
1861
1862         snprintf(cook, 34, "%d_%d_%u ", server_id, (int)mypid, myseqn);
1863         myseqn++;
1864         return cook;
1865 }
1866
1867
1868
1869 static const char *transports[] = {
1870         [0x00]  = "RTP/AVP",
1871         [0x01]  = "RTP/SAVP",
1872         [0x02]  = "RTP/AVPF",
1873         [0x03]  = "RTP/SAVPF",
1874 };
1875
1876 static int parse_flags(struct ng_flags_parse *ng_flags, struct sip_msg *msg, enum rtpe_operation *op,
1877                 const char *flags_str)
1878 {
1879         char *e;
1880         const char *err;
1881         str key, val, s;
1882
1883         if (!flags_str)
1884                 return 0;
1885
1886         while (1) {
1887                 while (*flags_str == ' ')
1888                         flags_str++;
1889
1890                 key.s = (void *) flags_str;
1891                 val.len = key.len = -1;
1892                 val.s = NULL;
1893
1894                 e = strpbrk(key.s, " =");
1895                 if (!e)
1896                         e = key.s + strlen(key.s);
1897                 else if (*e == '=') {
1898                         key.len = e - key.s;
1899                         val.s = e + 1;
1900                         e = strchr(val.s, ' ');
1901                         if (!e)
1902                                 e = val.s + strlen(val.s);
1903                         val.len = e - val.s;
1904                 }
1905
1906                 if (key.len == -1)
1907                         key.len = e - key.s;
1908                 if (!key.len)
1909                         break;
1910
1911                 /* check for items which have their own sub-list */
1912                 s = str_prefix(&key, "replace-");
1913                 if (s.s) {
1914                         bencode_list_add_str(ng_flags->replace, &s);
1915                         goto next;
1916                 }
1917
1918                 s = str_prefix(&key, "rtcp-mux-");
1919                 if (s.s) {
1920                         bencode_list_add_str(ng_flags->rtcp_mux, &s);
1921                         goto next;
1922                 }
1923
1924                 /* check for specially handled items */
1925                 switch (key.len) {
1926                         case 3:
1927                                 if (str_eq(&key, "RTP")) {
1928                                         ng_flags->transport |= 0x100;
1929                                         ng_flags->transport &= ~0x001;
1930                                 }
1931                                 else if (str_eq(&key, "AVP")) {
1932                                         ng_flags->transport |= 0x100;
1933                                         ng_flags->transport &= ~0x002;
1934                                 }
1935                                 else if (str_eq(&key, "TOS") && val.s)
1936                                         bencode_dictionary_add_integer(ng_flags->dict, "TOS", atoi(val.s));
1937                                 else if (str_eq(&key, "delete-delay") && val.s)
1938                                         bencode_dictionary_add_integer(ng_flags->dict, "delete delay", atoi(val.s));
1939                                 else
1940                                         goto generic;
1941                                 goto next;
1942                                 break;
1943
1944                         case 4:
1945                                 if (str_eq(&key, "SRTP"))
1946                                         ng_flags->transport |= 0x101;
1947                                 else if (str_eq(&key, "AVPF"))
1948                                         ng_flags->transport |= 0x102;
1949                                 else
1950                                         goto generic;
1951                                 goto next;
1952                                 break;
1953
1954                         case 6:
1955                                 if (str_eq(&key, "to-tag")) {
1956                                         if (val.s)
1957                                                 ng_flags->to_tag = val;
1958                                         ng_flags->to = 1;
1959                                         goto next;
1960                                 }
1961                                 break;
1962
1963                         case 7:
1964                                 if (str_eq(&key, "RTP/AVP"))
1965                                         ng_flags->transport = 0x100;
1966                                 else if (str_eq(&key, "call-id")) {
1967                                         err = "missing value";
1968                                         if (!val.s)
1969                                                 goto error;
1970                                         ng_flags->call_id = val;
1971                                 }
1972                                 else
1973                                         goto generic;
1974                                 goto next;
1975                                 break;
1976
1977                         case 8:
1978                                 if (str_eq(&key, "internal") || str_eq(&key, "external"))
1979                                         bencode_list_add_str(ng_flags->direction, &key);
1980                                 else if (str_eq(&key, "RTP/AVPF"))
1981                                         ng_flags->transport = 0x102;
1982                                 else if (str_eq(&key, "RTP/SAVP"))
1983                                         ng_flags->transport = 0x101;
1984                                 else if (str_eq(&key, "from-tag")) {
1985                                         err = "missing value";
1986                                         if (!val.s)
1987                                                 goto error;
1988                                         ng_flags->from_tag = val;
1989                                 }
1990                                 else
1991                                         goto generic;
1992                                 goto next;
1993                                 break;
1994
1995                         case 9:
1996                                 if (str_eq(&key, "RTP/SAVPF"))
1997                                         ng_flags->transport = 0x103;
1998                                 else if (str_eq(&key, "direction"))
1999                                         bencode_list_add_str(ng_flags->direction, &val);
2000                                 else
2001                                         goto generic;
2002                                 goto next;
2003                                 break;
2004
2005                         case 10:
2006                                 if (str_eq(&key, "via-branch")) {
2007                                         err = "missing value";
2008                                         if (!val.s)
2009                                                 goto error;
2010                                         err = "invalid value";
2011                                         if (*val.s == '1' || *val.s == '2')
2012                                                 ng_flags->via = *val.s - '0';
2013                                         else if (str_eq(&val, "auto"))
2014                                                 ng_flags->via = 3;
2015                                         else if (str_eq(&val, "extra"))
2016                                                 ng_flags->via = -1;
2017                                         else
2018                                                 goto error;
2019                                         goto next;
2020                                 }
2021                                 break;
2022
2023                         case 11:
2024                                 if (str_eq(&key, "repacketize")) {
2025                                         err = "missing value";
2026                                         if (!val.s)
2027                                                 goto error;
2028                                         ng_flags->packetize = 0;
2029                                         while (isdigit(*val.s)) {
2030                                                 ng_flags->packetize *= 10;
2031                                                 ng_flags->packetize += *val.s - '0';
2032                                                 val.s++;
2033                                         }
2034                                         err = "invalid value";
2035                                         if (!ng_flags->packetize)
2036                                                 goto error;
2037                                         bencode_dictionary_add_integer(ng_flags->dict, "repacketize", ng_flags->packetize);
2038                                         goto next;
2039                                 }
2040                                 break;
2041
2042                         case 12:
2043                                 if (str_eq(&key, "force-answer")) {
2044                                         err = "cannot force answer in non-offer command";
2045                                         if (*op != OP_OFFER)
2046                                                 goto error;
2047                                         *op = OP_ANSWER;
2048                                         goto next;
2049                                 }
2050                                 break;
2051                 }
2052
2053 generic:
2054                 if (!val.s)
2055                         bencode_list_add_str(ng_flags->flags, &key);
2056                 else
2057                         bencode_dictionary_str_add_str(ng_flags->dict, &key, &val);
2058                 goto next;
2059
2060 next:
2061                 flags_str = e;
2062         }
2063
2064         return 0;
2065
2066 error:
2067         if (val.s)
2068                 LM_ERR("error processing flag `%.*s' (value '%.*s'): %s\n", key.len, key.s,
2069                                 val.len, val.s, err);
2070         else
2071                 LM_ERR("error processing flag `%.*s': %s\n", key.len, key.s, err);
2072         return -1;
2073 }
2074
2075 static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_msg *msg,
2076         enum rtpe_operation op, const char *flags_str, str *body_out)
2077 {
2078         struct ng_flags_parse ng_flags;
2079         bencode_item_t *item, *resp;
2080         str viabranch = STR_NULL;
2081         str body = STR_NULL, error = STR_NULL;
2082         int ret, queried_nodes = 0;
2083         struct rtpp_node *node;
2084         char *cp;
2085         pv_value_t pv_val;
2086
2087         /*** get & init basic stuff needed ***/
2088
2089         memset(&ng_flags, 0, sizeof(ng_flags));
2090
2091         if (get_callid(msg, &ng_flags.call_id) == -1 || ng_flags.call_id.len == 0) {
2092                 LM_ERR("can't get Call-Id field\n");
2093                 return NULL;
2094         }
2095         if (get_to_tag(msg, &ng_flags.to_tag) == -1) {
2096                 LM_ERR("can't get To tag\n");
2097                 return NULL;
2098         }
2099         if (get_from_tag(msg, &ng_flags.from_tag) == -1 || ng_flags.from_tag.len == 0) {
2100                 LM_ERR("can't get From tag\n");
2101                 return NULL;
2102         }
2103         if (bencode_buffer_init(bencbuf)) {
2104                 LM_ERR("could not initialize bencode_buffer_t\n");
2105                 return NULL;
2106         }
2107         ng_flags.dict = bencode_dictionary(bencbuf);
2108
2109         body.s = NULL;
2110         if (op == OP_OFFER || op == OP_ANSWER) {
2111                 ng_flags.flags = bencode_list(bencbuf);
2112                 ng_flags.direction = bencode_list(bencbuf);
2113                 ng_flags.replace = bencode_list(bencbuf);
2114                 ng_flags.rtcp_mux = bencode_list(bencbuf);
2115
2116                 if (read_sdp_pvar!= NULL) {
2117                         if (read_sdp_pvar->getf(msg,&read_sdp_pvar->pvp, &pv_val) < 0)
2118                         {
2119                                 LM_ERR("error getting pvar value <%.*s>\n", read_sdp_pvar_str.len, read_sdp_pvar_str.s);
2120                                 goto error;
2121                         } else {
2122                                 body = pv_val.rs;
2123                         }
2124
2125                 } else if (extract_body(msg, &body) == -1) {
2126                         LM_ERR("can't extract body from the message\n");
2127                         goto error;
2128                 }
2129                 if (body_intermediate.s)
2130                         bencode_dictionary_add_str(ng_flags.dict, "sdp", &body_intermediate);
2131                 else
2132                         bencode_dictionary_add_str(ng_flags.dict, "sdp", &body);
2133         }
2134
2135         /*** parse flags & build dictionary ***/
2136
2137         ng_flags.to = (op == OP_DELETE) ? 0 : 1;
2138
2139         if (parse_flags(&ng_flags, msg, &op, flags_str))
2140                 goto error;
2141
2142         /* only add those if any flags were given at all */
2143         if (ng_flags.direction && ng_flags.direction->child)
2144                 bencode_dictionary_add(ng_flags.dict, "direction", ng_flags.direction);
2145         if (ng_flags.flags && ng_flags.flags->child)
2146                 bencode_dictionary_add(ng_flags.dict, "flags", ng_flags.flags);
2147         if (ng_flags.replace && ng_flags.replace->child)
2148                 bencode_dictionary_add(ng_flags.dict, "replace", ng_flags.replace);
2149         if ((ng_flags.transport & 0x100))
2150                 bencode_dictionary_add_string(ng_flags.dict, "transport-protocol",
2151                                 transports[ng_flags.transport & 0x003]);
2152         if (ng_flags.rtcp_mux && ng_flags.rtcp_mux->child)
2153                 bencode_dictionary_add(ng_flags.dict, "rtcp-mux", ng_flags.rtcp_mux);
2154
2155         bencode_dictionary_add_str(ng_flags.dict, "call-id", &ng_flags.call_id);
2156
2157         if (ng_flags.via) {
2158                 if (ng_flags.via == 1 || ng_flags.via == 2)
2159                         ret = get_via_branch(msg, ng_flags.via, &viabranch);
2160                 else if (ng_flags.via == -1 && extra_id_pv)
2161                         ret = get_extra_id(msg, &viabranch);
2162                 else
2163                         ret = -1;
2164                 if (ret == -1 || viabranch.len == 0) {
2165                         LM_ERR("can't get Via branch/extra ID\n");
2166                         goto error;
2167                 }
2168                 bencode_dictionary_add_str(ng_flags.dict, "via-branch", &viabranch);
2169         }
2170
2171         item = bencode_list(bencbuf);
2172         bencode_dictionary_add(ng_flags.dict, "received-from", item);
2173         bencode_list_add_string(item, (msg->rcv.src_ip.af == AF_INET) ? "IP4" : (
2174                 (msg->rcv.src_ip.af == AF_INET6) ? "IP6" :
2175                 "?"
2176         ) );
2177         bencode_list_add_string(item, ip_addr2a(&msg->rcv.src_ip));
2178
2179         if ((msg->first_line.type == SIP_REQUEST && op != OP_ANSWER)
2180                 || (msg->first_line.type == SIP_REPLY && op == OP_DELETE)
2181                 || (msg->first_line.type == SIP_REPLY && op == OP_ANSWER))
2182         {
2183                 bencode_dictionary_add_str(ng_flags.dict, "from-tag", &ng_flags.from_tag);
2184                 if (ng_flags.to && ng_flags.to_tag.s && ng_flags.to_tag.len)
2185                         bencode_dictionary_add_str(ng_flags.dict, "to-tag", &ng_flags.to_tag);
2186         }
2187         else {
2188                 if (!ng_flags.to_tag.s || !ng_flags.to_tag.len) {
2189                         LM_ERR("No to-tag present\n");
2190                         goto error;
2191                 }
2192                 bencode_dictionary_add_str(ng_flags.dict, "from-tag", &ng_flags.to_tag);
2193                 bencode_dictionary_add_str(ng_flags.dict, "to-tag", &ng_flags.from_tag);
2194         }
2195
2196         bencode_dictionary_add_string(ng_flags.dict, "command", command_strings[op]);
2197
2198         /*** send it out ***/
2199
2200         if (bencbuf->error) {
2201                 LM_ERR("out of memory - bencode failed\n");
2202                 goto error;
2203         }
2204
2205         if(msg->id != current_msg_id)
2206                 active_rtpp_set = default_rtpp_set;
2207
2208 select_node:
2209         do {
2210                 if (queried_nodes >= cfg_get(rtpengine,rtpengine_cfg,queried_nodes_limit)) {
2211                         LM_ERR("queried nodes limit reached\n");
2212                         goto error;
2213                 }
2214
2215                 node = select_rtpp_node(ng_flags.call_id, viabranch, 1, queried_nodes_ptr, queried_nodes, op);
2216                 if (!node) {
2217                         LM_ERR("no available proxies\n");
2218                         goto error;
2219                 }
2220
2221                 cp = send_rtpp_command(node, ng_flags.dict, &ret);
2222                 if (cp == NULL) {
2223                         node->rn_disabled = 1;
2224                         node->rn_recheck_ticks = get_ticks() + cfg_get(rtpengine,rtpengine_cfg,rtpengine_disable_tout);
2225                 }
2226
2227                 queried_nodes_ptr[queried_nodes++] = node;
2228         } while (cp == NULL);
2229
2230         LM_DBG("proxy reply: %.*s\n", ret, cp);
2231
2232         set_rtp_inst_pvar(msg, &node->rn_url);
2233         /*** process reply ***/
2234
2235         resp = bencode_decode_expect(bencbuf, cp, ret, BENCODE_DICTIONARY);
2236         if (!resp) {
2237                 LM_ERR("failed to decode bencoded reply from proxy: %.*s\n", ret, cp);
2238                 goto error;
2239         }
2240
2241         if (!bencode_dictionary_get_strcmp(resp, "result", "error")) {
2242                 if (!bencode_dictionary_get_str(resp, "error-reason", &error)) {
2243                         LM_ERR("proxy return error but didn't give an error reason: %.*s\n", ret, cp);
2244                 } else {
2245                         if ((RTPENGINE_SESS_LIMIT_MSG_LEN == error.len) &&
2246                                 (strncmp(error.s, RTPENGINE_SESS_LIMIT_MSG, RTPENGINE_SESS_LIMIT_MSG_LEN) == 0))
2247                         {
2248                                 LM_WARN("proxy %.*s: %.*s", node->rn_url.len, node->rn_url.s , error.len, error.s);
2249                                 goto select_node;
2250                         }
2251                         LM_ERR("proxy replied with error: %.*s\n", error.len, error.s);
2252                 }
2253                 goto error;
2254         }
2255
2256         /* add hastable entry with the node => */
2257         if (!rtpengine_hash_table_lookup(ng_flags.call_id, viabranch, op)) {
2258                 // build the entry
2259                 struct rtpengine_hash_entry *entry = shm_malloc(sizeof(struct rtpengine_hash_entry));
2260                 if (!entry) {
2261                         LM_ERR("rtpengine hash table fail to create entry for calllen=%d callid=%.*s viabranch=%.*s\n",
2262                                 ng_flags.call_id.len, ng_flags.call_id.len, ng_flags.call_id.s,
2263                                 viabranch.len, viabranch.s);
2264                         goto skip_hash_table_insert;
2265                 }
2266                 memset(entry, 0, sizeof(struct rtpengine_hash_entry));
2267
2268                 // fill the entry
2269                 if (ng_flags.call_id.s && ng_flags.call_id.len > 0) {
2270                         if (shm_str_dup(&entry->callid, &ng_flags.call_id) < 0) {
2271                                 LM_ERR("rtpengine hash table fail to duplicate calllen=%d callid=%.*s\n",
2272                                         ng_flags.call_id.len, ng_flags.call_id.len, ng_flags.call_id.s);
2273                                 rtpengine_hash_table_free_entry(entry);
2274                                 goto skip_hash_table_insert;
2275                         }
2276                 }
2277                 if (viabranch.s && viabranch.len > 0) {
2278                         if (shm_str_dup(&entry->viabranch, &viabranch) < 0) {
2279                                 LM_ERR("rtpengine hash table fail to duplicate calllen=%d viabranch=%.*s\n",
2280                                         ng_flags.call_id.len, viabranch.len, viabranch.s);
2281                                 rtpengine_hash_table_free_entry(entry);
2282                                 goto skip_hash_table_insert;
2283                         }
2284                 }
2285                 entry->node = node;
2286                 entry->next = NULL;
2287                 entry->tout = get_ticks() + hash_table_tout;
2288
2289                 // insert the key<->entry from the hashtable
2290                 if (!rtpengine_hash_table_insert(ng_flags.call_id, viabranch, entry)) {
2291                         LM_ERR("rtpengine hash table fail to insert node=%.*s for calllen=%d callid=%.*s viabranch=%.*s\n",
2292                                 node->rn_url.len, node->rn_url.s, ng_flags.call_id.len,
2293                                 ng_flags.call_id.len, ng_flags.call_id.s, viabranch.len, viabranch.s);
2294                         rtpengine_hash_table_free_entry(entry);
2295                         goto skip_hash_table_insert;
2296                 } else {
2297                         LM_DBG("rtpengine hash table insert node=%.*s for calllen=%d callid=%.*s viabranch=%.*s\n",
2298                                 node->rn_url.len, node->rn_url.s, ng_flags.call_id.len,
2299                                 ng_flags.call_id.len, ng_flags.call_id.s, viabranch.len, viabranch.s);
2300                 }
2301         }
2302
2303 skip_hash_table_insert:
2304         if (body_out)
2305                 *body_out = body;
2306
2307         if (op == OP_DELETE) {
2308                 /* Delete the key<->value from the hashtable */
2309                 if (!rtpengine_hash_table_remove(ng_flags.call_id, viabranch, op)) {
2310                         LM_ERR("rtpengine hash table failed to remove entry for callen=%d callid=%.*s viabranch=%.*s\n",
2311                                 ng_flags.call_id.len, ng_flags.call_id.len, ng_flags.call_id.s,
2312                                 viabranch.len, viabranch.s);
2313                 } else {
2314                         LM_DBG("rtpengine hash table remove entry for callen=%d callid=%.*s viabranch=%.*s\n",
2315                                 ng_flags.call_id.len, ng_flags.call_id.len, ng_flags.call_id.s,
2316                                 viabranch.len, viabranch.s);
2317                 }
2318         }
2319
2320         return resp;
2321
2322 error:
2323         bencode_buffer_free(bencbuf);
2324         return NULL;
2325 }
2326
2327 static int rtpp_function_call_simple(struct sip_msg *msg, enum rtpe_operation op, const char *flags_str)
2328 {
2329         bencode_buffer_t bencbuf;
2330
2331         if (!rtpp_function_call(&bencbuf, msg, op, flags_str, NULL))
2332                 return -1;
2333
2334         bencode_buffer_free(&bencbuf);
2335         return 1;
2336 }
2337
2338 static bencode_item_t *rtpp_function_call_ok(bencode_buffer_t *bencbuf, struct sip_msg *msg,
2339                 enum rtpe_operation op, const char *flags_str, str *body)
2340 {
2341         bencode_item_t *ret;
2342
2343         ret = rtpp_function_call(bencbuf, msg, op, flags_str, body);
2344         if (!ret)
2345                 return NULL;
2346
2347         if (bencode_dictionary_get_strcmp(ret, "result", "ok")) {
2348                 LM_ERR("proxy didn't return \"ok\" result\n");
2349                 bencode_buffer_free(bencbuf);
2350                 return NULL;
2351         }
2352
2353         return ret;
2354 }
2355
2356
2357
2358 static int
2359 rtpp_test(struct rtpp_node *node, int isdisabled, int force)
2360 {
2361         bencode_buffer_t bencbuf;
2362         bencode_item_t *dict;
2363         char *cp;
2364         int ret;
2365
2366         if(node->rn_recheck_ticks == RTPENGINE_MAX_RECHECK_TICKS){
2367                 LM_DBG("rtpp %s disabled for ever\n", node->rn_url.s);
2368                 return 1;
2369         }
2370         if (force == 0) {
2371                 if (isdisabled == 0)
2372                         return 0;
2373                 if (node->rn_recheck_ticks > get_ticks())
2374                         return 1;
2375         }
2376
2377         if (bencode_buffer_init(&bencbuf)) {
2378                 LM_ERR("could not initialized bencode_buffer_t\n");
2379                 return 1;
2380         }
2381         dict = bencode_dictionary(&bencbuf);
2382         bencode_dictionary_add_string(dict, "command", "ping");
2383         if (bencbuf.error)
2384                 goto benc_error;
2385
2386         cp = send_rtpp_command(node, dict, &ret);
2387         if (!cp) {
2388                 node->rn_disabled = 1;
2389                 node->rn_recheck_ticks = get_ticks() + cfg_get(rtpengine,rtpengine_cfg,rtpengine_disable_tout);
2390                 LM_ERR("proxy did not respond to ping\n");
2391                 goto error;
2392         }
2393
2394         dict = bencode_decode_expect(&bencbuf, cp, ret, BENCODE_DICTIONARY);
2395         if (!dict || bencode_dictionary_get_strcmp(dict, "result", "pong")) {
2396                 LM_ERR("proxy responded with invalid response\n");
2397                 goto error;
2398         }
2399
2400         LM_INFO("rtp proxy <%s> found, support for it %senabled\n",
2401                 node->rn_url.s, force == 0 ? "re-" : "");
2402
2403         bencode_buffer_free(&bencbuf);
2404         return 0;
2405
2406 benc_error:
2407         LM_ERR("out of memory - bencode failed\n");
2408 error:
2409         bencode_buffer_free(&bencbuf);
2410         return 1;
2411 }
2412
2413 static char *
2414 send_rtpp_command(struct rtpp_node *node, bencode_item_t *dict, int *outlen)
2415 {
2416         struct sockaddr_un addr;
2417         int fd, len, i, vcnt;
2418         int rtpengine_retr, rtpengine_tout_ms = 1000;
2419         char *cp;
2420         static char buf[0x10000];
2421         struct pollfd fds[1];
2422         struct iovec *v;
2423         str out = STR_NULL;
2424
2425         v = bencode_iovec(dict, &vcnt, 1, 0);
2426         if (!v) {
2427                 LM_ERR("error converting bencode to iovec\n");
2428                 return NULL;
2429         }
2430
2431         len = 0;
2432         cp = buf;
2433         if (node->rn_umode == 0) {
2434                 memset(&addr, 0, sizeof(addr));
2435                 addr.sun_family = AF_LOCAL;
2436                 strncpy(addr.sun_path, node->rn_address,
2437                         sizeof(addr.sun_path) - 1);
2438 #ifdef HAVE_SOCKADDR_SA_LEN
2439                 addr.sun_len = strlen(addr.sun_path);
2440 #endif
2441
2442                 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
2443                 if (fd < 0) {
2444                         LM_ERR("can't create socket\n");
2445                         goto badproxy;
2446                 }
2447                 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2448                         close(fd);
2449                         LM_ERR("can't connect to RTP proxy <%s>\n", node->rn_url.s);
2450                         goto badproxy;
2451                 }
2452
2453                 do {
2454                         len = writev(fd, v + 1, vcnt);
2455                 } while (len == -1 && errno == EINTR);
2456                 if (len <= 0) {
2457                         close(fd);
2458                         LM_ERR("can't send command to RTP proxy <%s>\n", node->rn_url.s);
2459                         goto badproxy;
2460                 }
2461                 do {
2462                         len = read(fd, buf, sizeof(buf) - 1);
2463                 } while (len == -1 && errno == EINTR);
2464                 close(fd);
2465                 if (len <= 0) {
2466                         LM_ERR("can't read reply from RTP proxy <%s>\n", node->rn_url.s);
2467                         goto badproxy;
2468                 }
2469         } else {
2470                 fds[0].fd = rtpp_socks[node->idx];
2471                 fds[0].events = POLLIN;
2472                 fds[0].revents = 0;
2473                 /* Drain input buffer */
2474                 while ((poll(fds, 1, 0) == 1) &&
2475                         ((fds[0].revents & POLLIN) != 0)) {
2476                         /* coverity[check_return : FALSE] */
2477                         recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
2478                         fds[0].revents = 0;
2479                 }
2480                 v[0].iov_base = gencookie();
2481                 v[0].iov_len = strlen(v[0].iov_base);
2482         rtpengine_retr = cfg_get(rtpengine,rtpengine_cfg,rtpengine_retr);
2483                 for (i = 0; i < rtpengine_retr; i++) {
2484                         do {
2485                                 len = writev(rtpp_socks[node->idx], v, vcnt + 1);
2486                         } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
2487                         if (len <= 0) {
2488                                 bencode_get_str(bencode_dictionary_get(dict, "command"), &out);
2489                                 LM_ERR("can't send command \"%.*s\" to RTP proxy <%s>\n", out.len, out.s, node->rn_url.s);
2490                                 goto badproxy;
2491                         }
2492             rtpengine_tout_ms = cfg_get(rtpengine,rtpengine_cfg,rtpengine_tout_ms);
2493                         while ((poll(fds, 1, rtpengine_tout_ms) == 1) &&
2494                                 (fds[0].revents & POLLIN) != 0) {
2495                                 do {
2496                                         len = recv(rtpp_socks[node->idx], buf, sizeof(buf)-1, 0);
2497                                 } while (len == -1 && errno == EINTR);
2498                                 if (len <= 0) {
2499                                         LM_ERR("can't read reply from RTP proxy <%s>\n", node->rn_url.s);
2500                                         goto badproxy;
2501                                 }
2502                                 if (len >= (v[0].iov_len - 1) &&
2503                                         memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
2504                                         len -= (v[0].iov_len - 1);
2505                                         cp += (v[0].iov_len - 1);
2506                                         if (len != 0) {
2507                                                 len--;
2508                                                 cp++;
2509                                         }
2510                                         goto out;
2511                                 }
2512                                 fds[0].revents = 0;
2513                         }
2514                 }
2515                 if (i == rtpengine_retr) {
2516                         LM_ERR("timeout waiting reply from RTP proxy <%s>\n", node->rn_url.s);
2517                         goto badproxy;
2518                 }
2519         }
2520
2521 out:
2522         cp[len] = '\0';
2523         *outlen = len;
2524         return cp;
2525
2526 badproxy:
2527         return NULL;
2528 }
2529
2530 /*
2531  * select the set with the id_set id
2532  */
2533
2534 static struct rtpp_set * select_rtpp_set(unsigned int id_set ){
2535
2536         struct rtpp_set * rtpp_list;
2537         /*is it a valid set_id?*/
2538
2539         if (!rtpp_set_list) {
2540                 LM_ERR("no rtpp_set_list\n");
2541                 return 0;
2542         }
2543
2544         lock_get(rtpp_set_list->rset_head_lock);
2545         if (!rtpp_set_list->rset_first) {
2546                 LM_ERR("no rtpp_set_list->rset_first\n");
2547                 lock_release(rtpp_set_list->rset_head_lock);
2548                 return 0;
2549         }
2550
2551         for (rtpp_list=rtpp_set_list->rset_first; rtpp_list!=0 &&
2552                         rtpp_list->id_set!=id_set; rtpp_list=rtpp_list->rset_next);
2553         if (!rtpp_list) {
2554                 LM_ERR(" script error-invalid id_set to be selected\n");
2555         }
2556         lock_release(rtpp_set_list->rset_head_lock);
2557
2558         return rtpp_list;
2559 }
2560
2561 /*
2562  * run the selection algorithm and return the new selected node
2563  */
2564 static struct rtpp_node *
2565 select_rtpp_node_new(str callid, str viabranch, int do_test, struct rtpp_node **queried_nodes_ptr, int queried_nodes)
2566 {
2567         struct rtpp_node* node;
2568         unsigned i, sum, sumcut, weight_sum;
2569         int was_forced = 0;
2570
2571         /* XXX Use quick-and-dirty hashing algo */
2572         sum = 0;
2573         for(i = 0; i < callid.len; i++)
2574                 sum += callid.s[i];
2575         sum &= 0xff;
2576
2577 retry:
2578         weight_sum = 0;
2579
2580         lock_get(active_rtpp_set->rset_lock);
2581         for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
2582                 /* Select only between displayed machines */
2583                 if (!node->rn_displayed) {
2584                         continue;
2585                 }
2586
2587                 /* Try to enable if it's time to try. */
2588                 if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){
2589                         node->rn_disabled = rtpp_test(node, 1, 0);
2590                 }
2591
2592                 /* Select only between enabled machines */
2593                 if (!node->rn_disabled && !is_queried_node(node, queried_nodes_ptr, queried_nodes)) {
2594                         weight_sum += node->rn_weight;
2595                 }
2596         }
2597         lock_release(active_rtpp_set->rset_lock);
2598
2599         /* No proxies? Force all to be redetected, if not yet */
2600         if (weight_sum == 0) {
2601                 if (was_forced) {
2602                         return NULL;
2603                 }
2604
2605                 was_forced = 1;
2606
2607                 lock_get(active_rtpp_set->rset_lock);
2608                 for(node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
2609                         /* Select only between displayed machines */
2610                         if (!node->rn_displayed) {
2611                                 continue;
2612                         }
2613
2614                         node->rn_disabled = rtpp_test(node, 1, 1);
2615                 }
2616                 lock_release(active_rtpp_set->rset_lock);
2617
2618                 goto retry;
2619         }
2620
2621         /* sumcut here lays from 0 to weight_sum-1 */
2622         sumcut = sum % weight_sum;
2623
2624         /*
2625          * Scan proxy list and decrease until appropriate proxy is found.
2626          */
2627         lock_get(active_rtpp_set->rset_lock);
2628         for (node=active_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
2629                 /* Select only between displayed machines */
2630                 if (!node->rn_displayed) {
2631                         continue;
2632                 }
2633
2634                 /* Select only between enabled machines */
2635                 if (node->rn_disabled)
2636                         continue;
2637
2638                 /* Select only between not already queried machines */
2639                 if (is_queried_node(node, queried_nodes_ptr, queried_nodes))
2640                         continue;
2641
2642                 /* Found machine */
2643                 if (sumcut < node->rn_weight) {
2644                         lock_release(active_rtpp_set->rset_lock);
2645                         goto found;
2646                 }
2647
2648                 /* Update sumcut if enabled machine */
2649                 sumcut -= node->rn_weight;
2650         }
2651         lock_release(active_rtpp_set->rset_lock);
2652
2653         /* No node list */
2654         return NULL;
2655
2656 found:
2657         if (do_test) {
2658                 lock_get(active_rtpp_set->rset_lock);
2659                 node->rn_disabled = rtpp_test(node, node->rn_disabled, 0);
2660                 if (node->rn_disabled) {
2661                         lock_release(active_rtpp_set->rset_lock);
2662                         goto retry;
2663                 }
2664                 lock_release(active_rtpp_set->rset_lock);
2665         }
2666
2667         /* return selected node */
2668         return node;
2669 }
2670
2671 /*
2672  * lookup the hastable (key=callid value=node) and get the old node (e.g. for answer/delete)
2673  */
2674 static struct rtpp_node *
2675 select_rtpp_node_old(str callid, str viabranch, int do_test, enum rtpe_operation op)
2676 {
2677         struct rtpp_node *node = NULL;
2678
2679         node = rtpengine_hash_table_lookup(callid, viabranch, op);
2680
2681         if (!node) {
2682                 LM_DBG("rtpengine hash table lookup failed to find node for calllen=%d callid=%.*s viabranch=%.*s\n",
2683                         callid.len, callid.len, callid.s, viabranch.len, viabranch.s);
2684                 return NULL;
2685         } else {
2686                 LM_DBG("rtpengine hash table lookup find node=%.*s for calllen=%d callid=%.*s viabranch=%.*s\n",
2687                         node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s, viabranch.len, viabranch.s);
2688         }
2689
2690         return node;
2691 }
2692
2693 /*
2694  * Main balancing routine. This DO try to keep the same proxy for
2695  * the call if some proxies were disabled or enabled (e.g. kamctl command)
2696  */
2697 static struct rtpp_node *
2698 select_rtpp_node(str callid, str viabranch, int do_test, struct rtpp_node **queried_nodes_ptr, int queried_nodes, enum rtpe_operation op)
2699 {
2700         struct rtpp_node *node = NULL;
2701
2702         if (build_rtpp_socks()) {
2703                 LM_ERR("out of memory\n");
2704                 return NULL;
2705         }
2706
2707         if (!active_rtpp_set) {
2708                 default_rtpp_set = select_rtpp_set(setid_default);
2709                 active_rtpp_set = default_rtpp_set;
2710         }
2711
2712         if (!active_rtpp_set) {
2713                 LM_ERR("script error - no valid set selected\n");
2714                 return NULL;
2715         }
2716
2717         // lookup node
2718         node = select_rtpp_node_old(callid, viabranch, do_test, op);
2719
2720         // check node
2721         if (!node) {
2722                 // run the selection algorithm
2723                 node = select_rtpp_node_new(callid, viabranch, do_test, queried_nodes_ptr, queried_nodes);
2724
2725                 // check node
2726                 if (!node) {
2727                         LM_ERR("rtpengine failed to select new for calllen=%d callid=%.*s\n",
2728                                 callid.len, callid.len, callid.s);
2729                         return NULL;
2730                 }
2731         }
2732
2733         // if node enabled, return it
2734         if (!node->rn_disabled) {
2735                 return node;
2736         }
2737
2738         // if proper configuration and node manually or timeout disabled, return it
2739         if (rtpengine_allow_op) {
2740                 if (node->rn_recheck_ticks == RTPENGINE_MAX_RECHECK_TICKS) {
2741                         LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled(permanent) (probably still UP)! Return it\n",
2742                                 node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s);
2743                 } else {
2744                         LM_DBG("node=%.*s for calllen=%d callid=%.*s is disabled, either broke or timeout disabled! Return it\n",
2745                                 node->rn_url.len, node->rn_url.s, callid.len, callid.len, callid.s);
2746                 }
2747                 return node;
2748         }
2749
2750         return NULL;
2751 }
2752
2753 static int
2754 get_extra_id(struct sip_msg* msg, str *id_str) {
2755         if (msg == NULL || extra_id_pv == NULL || id_str == NULL) {
2756                 LM_ERR("bad parameters\n");
2757                 return -1;
2758         }
2759         if (pv_printf_s(msg, extra_id_pv, id_str) < 0) {
2760                 LM_ERR("cannot print the additional id\n");
2761                 return -1;
2762         }
2763
2764         return 1;
2765
2766 }
2767
2768 static int
2769 set_rtpengine_set_from_avp(struct sip_msg *msg, int direction)
2770 {
2771         struct usr_avp *avp;
2772         int_str setid_val;
2773
2774         if ((setid_avp_param == NULL) ||
2775            (avp = search_first_avp(setid_avp_type, setid_avp, &setid_val, 0)) == NULL) {
2776                 if (direction == 1 || !selected_rtpp_set_2)
2777                         active_rtpp_set = selected_rtpp_set_1;
2778                 else
2779                         active_rtpp_set = selected_rtpp_set_2;
2780                 return 1;
2781         }
2782
2783         if (avp->flags&AVP_VAL_STR) {
2784                 LM_ERR("setid_avp must hold an integer value\n");
2785                 return -1;
2786         }
2787
2788         active_rtpp_set = select_rtpp_set(setid_val.n);
2789         if(active_rtpp_set == NULL) {
2790                 LM_ERR("could not locate rtpproxy set %u\n", setid_val.n);
2791                 return -1;
2792         }
2793
2794         LM_DBG("using rtpengine set %u\n", setid_val.n);
2795
2796         current_msg_id = msg->id;
2797
2798         return 1;
2799 }
2800
2801 static void avp_print_s(pv_elem_t *pv, char *str, int len, struct sip_msg *msg) {
2802         pv_value_t val;
2803
2804         if (!pv)
2805                 return;
2806
2807         memset(&val, 0, sizeof(val));
2808         val.flags = PV_VAL_STR;
2809         val.rs.s = str;
2810         val.rs.len = len;
2811         pv->spec->setf(msg, &pv->spec->pvp, EQ_T, &val);
2812 }
2813
2814 static void avp_print_decimal(pv_elem_t *pv, int num, struct sip_msg *msg) {
2815         int len;
2816         char buf[8];
2817
2818         len = snprintf(buf, sizeof(buf), "%i.%i", num / 10, abs(num % 10));
2819         avp_print_s(pv, buf, len, msg);
2820 }
2821 static void avp_print_int(pv_elem_t *pv, int num, struct sip_msg *msg) {
2822         int len;
2823         char buf[8];
2824
2825         len = snprintf(buf, sizeof(buf), "%i", num);
2826         avp_print_s(pv, buf, len, msg);
2827 }
2828 static void avp_print_time(pv_elem_t *pv, int num, struct sip_msg *msg) {
2829         int len;
2830         char buf[8];
2831
2832         len = snprintf(buf, sizeof(buf), "%i:%02i", num / 60, abs(num % 60));
2833         avp_print_s(pv, buf, len, msg);
2834 }
2835
2836 static void avp_print_mos(struct minmax_mos_stats *s, struct minmax_stats_vals *vals, long long created,
2837                 struct sip_msg *msg)
2838 {
2839         if (!vals->avg_samples)
2840                 return;
2841
2842         avp_print_decimal(s->mos_pv, vals->mos / vals->avg_samples, msg);
2843         avp_print_time(s->at_pv, vals->at - created, msg);
2844         avp_print_int(s->packetloss_pv, vals->packetloss / vals->avg_samples, msg);
2845         avp_print_int(s->jitter_pv, vals->jitter / vals->avg_samples, msg);
2846         avp_print_int(s->roundtrip_pv, vals->roundtrip / vals->avg_samples, msg);
2847         avp_print_int(s->samples_pv, vals->samples / vals->avg_samples, msg);
2848 }
2849
2850 static int decode_mos_vals_dict(struct minmax_stats_vals *vals, bencode_item_t *dict, const char *key) {
2851         bencode_item_t *mos_ent;
2852
2853         mos_ent = bencode_dictionary_get_expect(dict, key, BENCODE_DICTIONARY);
2854         if (!mos_ent)
2855                 return 0;
2856
2857         vals->mos = bencode_dictionary_get_integer(mos_ent, "MOS", -1);
2858         vals->at = bencode_dictionary_get_integer(mos_ent, "reported at", -1);
2859         vals->packetloss = bencode_dictionary_get_integer(mos_ent, "packet loss", -1);
2860         vals->jitter = bencode_dictionary_get_integer(mos_ent, "jitter", -1);
2861         vals->roundtrip = bencode_dictionary_get_integer(mos_ent, "round-trip time", -1);
2862         vals->samples = bencode_dictionary_get_integer(mos_ent, "samples", -1);
2863         vals->avg_samples = 1;
2864
2865         return 1;
2866 }
2867
2868 static void parse_call_stats_1(struct minmax_mos_label_stats *mmls, bencode_item_t *dict,
2869                 struct sip_msg *msg)
2870 {
2871         long long created;
2872         str label, check;
2873         long long ssrcs[4];
2874         unsigned int num_ssrcs = 0, i;
2875         long long ssrc;
2876         char *endp;
2877         bencode_item_t *ssrc_list,
2878                        *ssrc_key,
2879                        *ssrc_dict,
2880                        *tags,
2881                        *tag_key,
2882                        *tag_dict,
2883                        *medias,
2884                        *media,
2885                        *streams,
2886                        *stream;
2887         struct minmax_stats_vals min_vals = { .mos = 100 },
2888                                  max_vals = { .mos = -1  },
2889                                  average_vals = { .avg_samples = 0 },
2890                                  vals_decoded;
2891
2892         if (!mmls->got_any_pvs)
2893                 return;
2894
2895         /* check if only a subset of info is requested */
2896         if (!mmls->label_pv)
2897                 goto ssrcs_done;
2898
2899         if (pv_printf_s(msg, mmls->label_pv, &label)) {
2900                 LM_ERR("error printing label PV\n");
2901                 return;
2902         }
2903         LM_DBG("rtpengine: looking for label '%.*s'\n", label.len, label.s);
2904
2905         /* walk through tags to find the label we're looking for */
2906         tags = bencode_dictionary_get_expect(dict, "tags", BENCODE_DICTIONARY);
2907         if (!tags)
2908                 return; /* label wanted but no tags found - return nothing */
2909         LM_DBG("rtpengine: XXX got tags\n");
2910
2911         for (tag_key = tags->child; tag_key; tag_key = tag_key->sibling->sibling) {
2912                 LM_DBG("rtpengine: XXX got tag\n");
2913                 tag_dict = tag_key->sibling;
2914                 /* compare label */
2915                 if (!bencode_dictionary_get_str(tag_dict, "label", &check))
2916                         continue;
2917                 LM_DBG("rtpengine: XXX got label %.*s\n", check.len, check.s);
2918                 if (str_cmp(&check, &label))
2919                         continue;
2920                 LM_DBG("rtpengine: XXX label match\n");
2921                 medias = bencode_dictionary_get_expect(tag_dict, "medias", BENCODE_LIST);
2922                 if (!medias)
2923                         continue;
2924                 LM_DBG("rtpengine: XXX got medias\n");
2925                 for (media = medias->child; media; media = media->sibling) {
2926                         LM_DBG("rtpengine: XXX got media\n");
2927                         streams = bencode_dictionary_get_expect(media, "streams", BENCODE_LIST);
2928                         if (!streams)
2929                                 continue;
2930                         LM_DBG("rtpengine: XXX got streams\n");
2931                         /* only check the first stream (RTP) */
2932                         stream = streams->child;
2933                         if (!stream)
2934                                 continue;
2935                         LM_DBG("rtpengine: XXX got stream type %i\n", stream->type);
2936                         LM_DBG("rtpengine: XXX stream child '%.*s'\n", (int) stream->child->iov[1].iov_len, (char *) stream->child->iov[1].iov_base);
2937                         LM_DBG("rtpengine: XXX stream child val type %i\n", stream->child->sibling->type);
2938                         if ((ssrc = bencode_dictionary_get_integer(stream, "SSRC", -1)) == -1)
2939                                 continue;
2940                         /* got a valid SSRC to watch for */
2941                         ssrcs[num_ssrcs] = ssrc;
2942                         LM_DBG("rtpengine: found SSRC '%lli' for label '%.*s'\n",
2943                                         ssrc,
2944                                         label.len, label.s);
2945                         num_ssrcs++;
2946                         /* see if we can do more */
2947                         if (num_ssrcs >= (sizeof(ssrcs) / sizeof(*ssrcs)))
2948                                 goto ssrcs_done;
2949                 }
2950         }
2951         /* if we get here, we were looking for label. see if we found one. if not, return nothing */
2952         if (num_ssrcs == 0)
2953                 return;
2954
2955 ssrcs_done:
2956         /* now look for the stats values */
2957         created = bencode_dictionary_get_integer(dict, "created", 0);
2958         ssrc_list = bencode_dictionary_get_expect(dict, "SSRC", BENCODE_DICTIONARY);
2959         if (!ssrc_list)
2960                 return;
2961
2962         for (ssrc_key = ssrc_list->child; ssrc_key; ssrc_key = ssrc_key->sibling->sibling) {
2963                 /* see if this is a SSRC we're interested in */
2964                 if (num_ssrcs == 0)
2965                         goto ssrc_ok;
2966                 if (!bencode_get_str(ssrc_key, &check))
2967                         continue;
2968                 ssrc = strtoll(check.s, &endp, 10);
2969                 for (i = 0; i < num_ssrcs; i++) {
2970                         if (ssrcs[i] != ssrc)
2971                                 continue;
2972                         /* it's a match */
2973                         LM_DBG("rtpengine: considering SSRC '%.*s'\n",
2974                                         check.len, check.s);
2975                         goto ssrc_ok;
2976                 }
2977                 /* no match */
2978                 continue;
2979
2980 ssrc_ok:
2981                 ssrc_dict = ssrc_key->sibling;
2982                 if (!ssrc_dict)
2983                         continue;
2984
2985                 if (decode_mos_vals_dict(&vals_decoded, ssrc_dict, "average MOS")) {
2986                         average_vals.avg_samples++;
2987                         average_vals.mos += vals_decoded.mos;
2988                         average_vals.packetloss += vals_decoded.packetloss;
2989                         average_vals.jitter += vals_decoded.jitter;
2990                         average_vals.roundtrip += vals_decoded.roundtrip;
2991                         average_vals.samples += vals_decoded.samples;
2992                 }
2993
2994                 if (decode_mos_vals_dict(&vals_decoded, ssrc_dict, "highest MOS")) {
2995                         if (vals_decoded.mos > max_vals.mos)
2996                                 max_vals = vals_decoded;
2997                 }
2998                 if (decode_mos_vals_dict(&vals_decoded, ssrc_dict, "lowest MOS")) {
2999                         if (vals_de