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