Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.cpp
Warning:line 340, column 8
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ice_ctx.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D _FILE_OFFSET_BITS=64 -D CHROMIUM_BUILD -D USE_LIBJPEG_TURBO=1 -D USE_NSS=1 -D ENABLE_ONE_CLICK_SIGNIN -D GTK_DISABLE_SINGLE_INCLUDES=1 -D _ISOC99_SOURCE=1 -D ENABLE_REMOTING=1 -D ENABLE_WEBRTC=1 -D ENABLE_CONFIGURATION_POLICY -D ENABLE_INPUT_SPEECH -D ENABLE_NOTIFICATIONS -D ENABLE_GPU=1 -D ENABLE_EGLIMAGE=1 -D USE_SKIA=1 -D ENABLE_TASK_MANAGER=1 -D ENABLE_WEB_INTENTS=1 -D ENABLE_EXTENSIONS=1 -D ENABLE_PLUGIN_INSTALLATION=1 -D ENABLE_PROTECTOR_SERVICE=1 -D ENABLE_SESSION_SERVICE=1 -D ENABLE_THEMES=1 -D ENABLE_BACKGROUND=1 -D ENABLE_AUTOMATION=1 -D ENABLE_PRINTING=1 -D ENABLE_CAPTIVE_PORTAL_DETECTION=1 -D SANITY_CHECKS -D USE_RFC_3489_BACKWARDS_COMPATIBLE -D USE_STUN_PEDANTIC -D NR_SOCKET_IS_VOID_PTR -D restrict= -D R_PLATFORM_INT_TYPES=<stdint.h> -D R_DEFINED_INT2=int16_t -D R_DEFINED_UINT2=uint16_t -D R_DEFINED_INT4=int32_t -D R_DEFINED_UINT4=uint32_t -D R_DEFINED_INT8=int64_t -D R_DEFINED_UINT8=uint64_t -D LINUX -D HAVE_LIBM=1 -D HAVE_STRDUP=1 -D HAVE_STRLCPY=1 -D HAVE_SYS_TIME_H=1 -D HAVE_VFPRINTF=1 -D NEW_STDIORETSIGTYPE=void -D TIME_WITH_SYS_TIME_H=1 -D __UNUSED__=__attribute__((unused)) -D DYNAMIC_ANNOTATIONS_ENABLED=1 -D WTF_USE_DYNAMIC_ANNOTATIONS=1 -D _DEBUG -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/event -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/log -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/registry -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/share -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/util -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/port/generic/include -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/crypto -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/net -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/util -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/port/linux/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-format -Wno-format-security -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.cpp
1/*
2Copyright (c) 2007, Adobe Systems, Incorporated
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9* Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12* Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16* Neither the name of Adobe Systems, Network Resonance nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
33#include <csi_platform.h>
34#include <assert.h>
35#include <sys/types.h>
36#ifdef WIN32
37#include <winsock2.h>
38#else
39#include <sys/socket.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#endif
43#include <sys/queue.h>
44#include <string.h>
45#include <nr_api.h>
46#include <registry.h>
47#include "stun.h"
48#include "ice_ctx.h"
49#include "ice_reg.h"
50#include "nr_crypto.h"
51#include "async_timer.h"
52#include "util.h"
53#include "addrs.h"
54#include "nr_socket_local.h"
55
56#define ICE_UFRAG_LEN8 8
57#define ICE_PWD_LEN32 32
58
59int LOG_ICE = 0;
60
61static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
62static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
63static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand);
64static int no_op(void **obj) {
65 return 0;
66}
67
68static nr_socket_factory_vtbl default_socket_factory_vtbl = {
69 nr_socket_local_create,
70 no_op
71};
72
73int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
74 {
75 int r,_status;
76 nr_ice_stun_server *servers = 0;
77 int i;
78 NR_registry child;
79 char *addr=0;
80 UINT2 port;
81 in_addr_t addr_int;
82
83 if(!(servers=R_NEW_CNT(nr_ice_stun_server, ct)(nr_ice_stun_server*)calloc(ct,sizeof(nr_ice_stun_server))))
84 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
85
86 for(i=0;i<ct;i++){
87 if(r=NR_reg_get_child_registry(NR_ICE_REG_STUN_SRV_PRFX"ice.stun.server",i,child))
88 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
89 /* Assume we have a v4 addr for now */
90 if(r=NR_reg_alloc2_string(child,"addr",&addr))
91 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
92 addr_int=inet_addr(addr);
93 if(addr_int==INADDR_NONE((in_addr_t) 0xffffffff)){
94 r_log(LOG_ICE,LOG_ERR3,"Invalid address %s;",addr);
95 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
96 }
97 if(r=NR_reg_get2_uint2(child,"port",&port)) {
98 if (r != R_NOT_FOUND2)
99 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
100 port = 3478;
101 }
102 if (r = nr_ip4_port_to_transport_addr(ntohl(addr_int)__bswap_32 (addr_int), port, IPPROTO_UDPIPPROTO_UDP,
103 &servers[i].addr))
104 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
105 free(addr);
106 addr=0;
107 }
108
109 *out = servers;
110
111 _status=0;
112 abort:
113 free(addr);
114 if (_status) free(servers);
115 return(_status);
116 }
117
118int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
119 {
120 int _status;
121
122 if(ctx->stun_servers_cfg){
123 free(ctx->stun_servers_cfg);
124 ctx->stun_servers_cfg=NULL__null;
125 ctx->stun_server_ct_cfg=0;
126 }
127
128 if (ct) {
129 if(!(ctx->stun_servers_cfg=R_NEW_CNT(nr_ice_stun_server, ct)(nr_ice_stun_server*)calloc(ct,sizeof(nr_ice_stun_server))))
130 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
131
132 memcpy(ctx->stun_servers_cfg,servers,sizeof(nr_ice_stun_server)*ct);
133 ctx->stun_server_ct_cfg = ct;
134 }
135
136 _status=0;
137 abort:
138 return(_status);
139 }
140
141int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
142 {
143 int _status;
144
145 if(ctx->turn_servers_cfg){
146 for (int i = 0; i < ctx->turn_server_ct_cfg; i++) {
147 free(ctx->turn_servers_cfg[i].username);
148 r_data_destroy(&ctx->turn_servers_cfg[i].password);
149 }
150 free(ctx->turn_servers_cfg);
151 ctx->turn_servers_cfg=NULL__null;
152 ctx->turn_server_ct_cfg=0;
153 }
154
155 if(ct) {
156 if(!(ctx->turn_servers_cfg=R_NEW_CNT(nr_ice_turn_server, ct)(nr_ice_turn_server*)calloc(ct,sizeof(nr_ice_turn_server))))
157 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
158
159 memcpy(ctx->turn_servers_cfg,servers,sizeof(nr_ice_turn_server)*ct);
160 ctx->turn_server_ct_cfg = ct;
161 }
162
163 _status=0;
164 abort:
165 return(_status);
166 }
167
168static int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
169 {
170 int _status,i,r;
171
172 if(ctx->local_addrs) {
173 free(ctx->local_addrs);
174 ctx->local_addr_ct=0;
175 ctx->local_addrs=0;
176 }
177
178 if (ct) {
179 if(!(ctx->local_addrs=R_NEW_CNT(nr_local_addr, ct)(nr_local_addr*)calloc(ct,sizeof(nr_local_addr))))
180 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
181
182 for (i=0;i<ct;++i) {
183 if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
184 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
185 }
186 }
187 ctx->local_addr_ct = ct;
188 }
189
190 _status=0;
191 abort:
192 return(_status);
193 }
194
195int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
196 {
197 int _status;
198
199 if (ctx->resolver) {
200 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
201 }
202
203 ctx->resolver = resolver;
204
205 _status=0;
206 abort:
207 return(_status);
208 }
209
210int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
211 {
212 int _status;
213
214 if (ctx->interface_prioritizer) {
215 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
216 }
217
218 ctx->interface_prioritizer = ip;
219
220 _status=0;
221 abort:
222 return(_status);
223 }
224
225void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory)
226 {
227 nr_socket_factory_destroy(&ctx->socket_factory);
228 ctx->socket_factory = factory;
229 }
230
231int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
232 {
233 int r,_status;
234 nr_ice_turn_server *servers = 0;
235 int i;
236 NR_registry child;
237 char *addr=0;
238 UINT2 port;
239 in_addr_t addr_int;
240 Data data={0};
241
242 if(!(servers=R_NEW_CNT(nr_ice_turn_server, ct)(nr_ice_turn_server*)calloc(ct,sizeof(nr_ice_turn_server))))
243 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
244
245 for(i=0;i<ct;i++){
246 if(r=NR_reg_get_child_registry(NR_ICE_REG_TURN_SRV_PRFX"ice.turn.server",i,child))
247 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
248 /* Assume we have a v4 addr for now */
249 if(r=NR_reg_alloc2_string(child,"addr",&addr))
250 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
251 addr_int=inet_addr(addr);
252 if(addr_int==INADDR_NONE((in_addr_t) 0xffffffff)){
253 r_log(LOG_ICE,LOG_ERR3,"Invalid address %s",addr);
254 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
255 }
256 if(r=NR_reg_get2_uint2(child,"port",&port)) {
257 if (r != R_NOT_FOUND2)
258 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
259 port = 3478;
260 }
261 if (r = nr_ip4_port_to_transport_addr(ntohl(addr_int)__bswap_32 (addr_int), port, IPPROTO_UDPIPPROTO_UDP,
262 &servers[i].turn_server.addr))
263 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
264
265
266 if(r=NR_reg_alloc2_string(child,NR_ICE_REG_TURN_SRV_USERNAME"username",&servers[i].username)){
267 if(r!=R_NOT_FOUND2)
268 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
269 }
270
271 if(r=NR_reg_alloc2_data(child,NR_ICE_REG_TURN_SRV_PASSWORD"password",&data)){
272 if(r!=R_NOT_FOUND2)
273 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
274 }
275 else {
276 servers[i].password=R_NEW(Data)(Data*)calloc(1,sizeof(Data));
277 if(!servers[i].password)
278 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
279 servers[i].password->data = data.data;
280 servers[i].password->len = data.len;
281 data.data=0;
282 }
283
284 free(addr);
285 addr=0;
286 }
287
288 *out = servers;
289
290 _status=0;
291 abort:
292 free(data.data);
293 free(addr);
294 if (_status) free(servers);
295 return(_status);
296 }
297
298#define MAXADDRS100 100 /* Ridiculously high */
299 int nr_ice_ctx_create(char* label, UINT4 flags,
300 nr_ice_gather_handler* gather_handler,
301 nr_ice_ctx** ctxp) {
302 nr_ice_ctx *ctx=0;
303 int r,_status;
304
305 if(r=r_log_register("ice", &LOG_ICE))
306 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
307
308 if(!(ctx=R_NEW(nr_ice_ctx)(nr_ice_ctx*)calloc(1,sizeof(nr_ice_ctx))))
309 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
310
311 ctx->flags=flags;
312
313 if(!(ctx->label=strdup(label)))
314 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
315
316 ctx->gather_handler = gather_handler;
317
318 /* Get the STUN servers */
319 if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX"ice.stun.server",
320 (unsigned int *)&ctx->stun_server_ct_cfg)||ctx->stun_server_ct_cfg==0) {
321 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): No STUN servers specified in nICEr registry", ctx->label);
322 ctx->stun_server_ct_cfg=0;
323 }
324
325 /* 31 is the max for our priority algorithm */
326 if(ctx->stun_server_ct_cfg>31){
327 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Too many STUN servers specified: max=31", ctx->label);
328 ctx->stun_server_ct_cfg=31;
329 }
330
331 if(ctx->stun_server_ct_cfg>0){
332 if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct_cfg,&ctx->stun_servers_cfg)){
333 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Couldn't load STUN servers from registry", ctx->label);
334 ctx->stun_server_ct_cfg=0;
335 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
336 }
337 }
338
339 /* Get the TURN servers */
340 if(r=NR_reg_get_child_count(NR_ICE_REG_TURN_SRV_PRFX"ice.turn.server",
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
341 (unsigned int *)&ctx->turn_server_ct_cfg)||ctx->turn_server_ct_cfg==0) {
342 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): No TURN servers specified in nICEr registry", ctx->label);
343 ctx->turn_server_ct_cfg=0;
344 }
345
346 ctx->local_addrs=0;
347 ctx->local_addr_ct=0;
348
349 /* 31 is the max for our priority algorithm */
350 if((ctx->stun_server_ct_cfg+ctx->turn_server_ct_cfg)>31){
351 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Too many STUN/TURN servers specified: max=31", ctx->label);
352 ctx->turn_server_ct_cfg=31-ctx->stun_server_ct_cfg;
353 }
354
355 if(ctx->turn_server_ct_cfg>0){
356 if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct_cfg,&ctx->turn_servers_cfg)){
357 ctx->turn_server_ct_cfg=0;
358 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Couldn't load TURN servers from registry", ctx->label);
359 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
360 }
361 }
362
363
364 ctx->Ta = 20;
365
366 ctx->test_timer_divider = 0;
367
368 if (r=nr_socket_factory_create_int(NULL__null, &default_socket_factory_vtbl, &ctx->socket_factory))
369 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
370
371 if ((r=NR_reg_get_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME"ice.forced_interface_name", ctx->force_net_interface, sizeof(ctx->force_net_interface)))) {
372 if (r == R_NOT_FOUND2) {
373 ctx->force_net_interface[0] = 0;
374 } else {
375 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
376 }
377 }
378
379 ctx->target_for_default_local_address_lookup=0;
380
381 STAILQ_INIT(&ctx->streams)do { (((&ctx->streams))->stqh_first) = __null; (&
ctx->streams)->stqh_last = &(((&ctx->streams
))->stqh_first); } while (0)
;
382 STAILQ_INIT(&ctx->sockets)do { (((&ctx->sockets))->stqh_first) = __null; (&
ctx->sockets)->stqh_last = &(((&ctx->sockets
))->stqh_first); } while (0)
;
383 STAILQ_INIT(&ctx->foundations)do { (((&ctx->foundations))->stqh_first) = __null; (
&ctx->foundations)->stqh_last = &(((&ctx->
foundations))->stqh_first); } while (0)
;
384 STAILQ_INIT(&ctx->peers)do { (((&ctx->peers))->stqh_first) = __null; (&
ctx->peers)->stqh_last = &(((&ctx->peers))->
stqh_first); } while (0)
;
385 STAILQ_INIT(&ctx->ids)do { (((&ctx->ids))->stqh_first) = __null; (&ctx
->ids)->stqh_last = &(((&ctx->ids))->stqh_first
); } while (0)
;
386
387 *ctxp=ctx;
388
389 _status=0;
390 abort:
391 if (_status && ctx) nr_ice_ctx_destroy(&ctx);
392
393 return(_status);
394 }
395
396 void nr_ice_ctx_add_flags(nr_ice_ctx* ctx, UINT4 flags) {
397 ctx->flags |= flags;
398 }
399
400 void nr_ice_ctx_remove_flags(nr_ice_ctx* ctx, UINT4 flags) {
401 ctx->flags &= ~flags;
402 }
403
404 void nr_ice_ctx_destroy(nr_ice_ctx** ctxp) {
405 if (!ctxp || !*ctxp) return;
406
407 nr_ice_ctx* ctx = *ctxp;
408 nr_ice_foundation *f1,*f2;
409 nr_ice_media_stream *s1,*s2;
410 int i;
411 nr_ice_stun_id *id1,*id2;
412
413 ctx->gather_done_cb = 0;
414 ctx->trickle_cb = 0;
415
416 STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2)for ((s1) = (((&ctx->streams))->stqh_first); (s1) &&
((s2) = (((s1))->entry.stqe_next), 1); (s1) = (s2))
{
417 STAILQ_REMOVE(&ctx->streams,s1,nr_ice_media_stream_,entry)do { if ((((&ctx->streams))->stqh_first) == (s1)) {
do { if ((((((&ctx->streams)))->stqh_first) = ((((
((&ctx->streams)))->stqh_first))->entry.stqe_next
)) == __null) ((&ctx->streams))->stqh_last = &(
(((&ctx->streams)))->stqh_first); } while (0); } else
{ struct nr_ice_media_stream_ *curelm = (((&ctx->streams
))->stqh_first); while (((curelm)->entry.stqe_next) != (
s1)) curelm = ((curelm)->entry.stqe_next); if ((((curelm)->
entry.stqe_next) = ((((curelm)->entry.stqe_next))->entry
.stqe_next)) == __null) (&ctx->streams)->stqh_last =
&(((curelm))->entry.stqe_next); } } while (0)
;
418 nr_ice_media_stream_destroy(&s1);
419 }
420
421 free(ctx->label);
422
423 ctx->gather_handler = 0;
424
425 free(ctx->stun_servers_cfg);
426
427 free(ctx->local_addrs);
428
429 free(ctx->target_for_default_local_address_lookup);
430
431 for (i = 0; i < ctx->turn_server_ct_cfg; i++) {
432 free(ctx->turn_servers_cfg[i].username);
433 r_data_destroy(&ctx->turn_servers_cfg[i].password);
434 }
435 free(ctx->turn_servers_cfg);
436
437 f1=STAILQ_FIRST(&ctx->foundations)((&ctx->foundations)->stqh_first);
438 while(f1){
439 f2=STAILQ_NEXT(f1,entry)((f1)->entry.stqe_next);
440 free(f1);
441 f1=f2;
442 }
443
444 STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2)for ((id1) = (((&ctx->ids))->stqh_first); (id1) &&
((id2) = (((id1))->entry.stqe_next), 1); (id1) = (id2))
{
445 STAILQ_REMOVE(&ctx->ids,id1,nr_ice_stun_id_,entry)do { if ((((&ctx->ids))->stqh_first) == (id1)) { do
{ if ((((((&ctx->ids)))->stqh_first) = ((((((&
ctx->ids)))->stqh_first))->entry.stqe_next)) == __null
) ((&ctx->ids))->stqh_last = &((((&ctx->
ids)))->stqh_first); } while (0); } else { struct nr_ice_stun_id_
*curelm = (((&ctx->ids))->stqh_first); while (((curelm
)->entry.stqe_next) != (id1)) curelm = ((curelm)->entry
.stqe_next); if ((((curelm)->entry.stqe_next) = ((((curelm
)->entry.stqe_next))->entry.stqe_next)) == __null) (&
ctx->ids)->stqh_last = &(((curelm))->entry.stqe_next
); } } while (0)
;
446 free(id1);
447 }
448
449 nr_resolver_destroy(&ctx->resolver);
450 nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
451 nr_socket_factory_destroy(&ctx->socket_factory);
452
453 free(ctx);
454
455 *ctxp=0;
456 }
457
458void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
459 {
460 int r;
461 nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg;
462 nr_ice_ctx *ctx;
463 nr_ice_media_stream *stream;
464 int component_id;
465
466 assert(cb_arg)(static_cast <bool> (cb_arg) ? void (0) : __assert_fail
("cb_arg", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
467 if (!cb_arg)
468 return;
469 ctx = cand->ctx;
470 stream = cand->stream;
471 component_id = cand->component_id;
472
473 ctx->uninitialized_candidates--;
474 if (cand->state == NR_ICE_CAND_STATE_FAILED4) {
475 r_log(LOG_ICE, LOG_WARNING4,
476 "ICE(%s)/CAND(%s): failed to initialize, %d remaining", ctx->label,
477 cand->label, ctx->uninitialized_candidates);
478 } else {
479 r_log(LOG_ICE, LOG_DEBUG7, "ICE(%s)/CAND(%s): initialized, %d remaining",
480 ctx->label, cand->label, ctx->uninitialized_candidates);
481 }
482
483 /* Avoid the need for yet another initialization function */
484 if (cand->state == NR_ICE_CAND_STATE_INITIALIZING2 && cand->type == HOST)
485 cand->state = NR_ICE_CAND_STATE_INITIALIZED3;
486
487 if (cand->state == NR_ICE_CAND_STATE_INITIALIZED3) {
488 int was_pruned = 0;
489
490 if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
491 cand, &was_pruned)) {
492 r_log(LOG_ICE, LOG_NOTICE5, "ICE(%s): Problem pruning candidates",ctx->label);
493 }
494
495 if (was_pruned) {
496 cand = NULL__null;
497 }
498
499 /* If we are initialized, the candidate wasn't pruned,
500 and we have a trickle ICE callback fire the callback */
501 if (ctx->trickle_cb && cand &&
502 !nr_ice_ctx_hide_candidate(ctx, cand)) {
503 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
504
505 if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
506 r_log(LOG_ICE,LOG_ERR3, "ICE(%s): All could not pair new trickle candidate",ctx->label);
507 /* But continue */
508 }
509 }
510 }
511
512 if (nr_ice_media_stream_is_done_gathering(stream)) {
513 if (ctx->gather_handler && ctx->gather_handler->vtbl->stream_gathered) {
514 ctx->gather_handler->vtbl->stream_gathered(ctx->gather_handler->obj,
515 stream);
516 }
517 if (ctx->trickle_cb) {
518 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, stream, component_id, NULL__null);
519 }
520 }
521
522 if(ctx->uninitialized_candidates==0){
523 assert(nr_ice_media_stream_is_done_gathering(stream))(static_cast <bool> (nr_ice_media_stream_is_done_gathering
(stream)) ? void (0) : __assert_fail ("nr_ice_media_stream_is_done_gathering(stream)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
524 r_log(LOG_ICE, LOG_INFO6, "ICE(%s): All candidates initialized",
525 ctx->label);
526 if (ctx->gather_done_cb) {
527 ctx->gather_done_cb(0, 0, ctx->cb_arg);
528 } else {
529 r_log(LOG_ICE, LOG_INFO6,
530 "ICE(%s): No gather_done_cb. We were probably destroyed.",
531 ctx->label);
532 }
533 }
534 else {
535 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): Waiting for %d candidates to be initialized",ctx->label, ctx->uninitialized_candidates);
536 }
537 }
538
539static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
540 {
541 int r,_status;
542 nr_ice_peer_ctx *pctx;
543
544 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
545 while(pctx){
546 if (pctx->state == NR_ICE_PEER_STATE_PAIRED2) {
547 r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
548 if (r)
549 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
550 }
551
552 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
553 }
554
555 _status=0;
556 abort:
557 return(_status);
558 }
559
560/* Get the default address by creating a UDP socket, binding it to a wildcard
561 address, and connecting it to the remote IP. Because this is UDP, no packets
562 are sent. This lets us query the local address assigned to the socket by the
563 kernel.
564
565 If the context's remote address is NULL, then the application wasn't loaded
566 over the network, and we can fall back on connecting to a known public
567 address (namely Google's):
568
569 IPv4: 8.8.8.8
570 IPv6: 2001:4860:4860::8888
571*/
572static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transport_addr* addrp)
573 {
574 int r,_status;
575 nr_transport_addr addr, known_remote_addr;
576 nr_transport_addr *remote_addr=ctx->target_for_default_local_address_lookup;
577 nr_socket *sock=0;
578
579 switch(ip_version) {
580 case NR_IPV44:
581 if ((r=nr_str_port_to_transport_addr("0.0.0.0", nullptr, 0, IPPROTO_UDPIPPROTO_UDP, &addr)))
582 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
583 if (!remote_addr || nr_transport_addr_is_loopback(remote_addr)) {
584 if ((r=nr_str_port_to_transport_addr("8.8.8.8", nullptr, 53, IPPROTO_UDPIPPROTO_UDP, &known_remote_addr)))
585 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
586 remote_addr=&known_remote_addr;
587 }
588 break;
589 case NR_IPV66:
590 if ((r=nr_str_port_to_transport_addr("::0", nullptr, 0, IPPROTO_UDPIPPROTO_UDP, &addr)))
591 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
592 if (!remote_addr || nr_transport_addr_is_loopback(remote_addr)) {
593 if ((r=nr_str_port_to_transport_addr("2001:4860:4860::8888", nullptr, 53, IPPROTO_UDPIPPROTO_UDP, &known_remote_addr)))
594 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
595 remote_addr=&known_remote_addr;
596 }
597 break;
598 default:
599 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
600 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
601 }
602
603 if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
604 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
605 if ((r=nr_socket_connect(sock, remote_addr)))
606 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
607 if ((r=nr_socket_getaddr(sock, addrp)))
608 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
609
610 r_log(LOG_GENERIC0, LOG_DEBUG7, "Default address: %s", addrp->as_string);
611
612 _status=0;
613 abort:
614 nr_socket_destroy(&sock);
615 return(_status);
616 }
617
618static int nr_ice_get_default_local_address(nr_ice_ctx *ctx, int ip_version, nr_local_addr* addrs, int addr_ct, nr_local_addr *addrp)
619 {
620 int r,_status;
621 nr_transport_addr default_addr;
622 int i;
623
624 if ((r=nr_ice_get_default_address(ctx, ip_version, &default_addr)))
625 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
626
627 for (i=0; i < addr_ct; ++i) {
628 // if default addr is found in local addrs, copy the more fully
629 // complete local addr to the output arg. Don't need to worry
630 // about comparing ports here.
631 if (!nr_transport_addr_cmp(&default_addr, &addrs[i].addr,
632 NR_TRANSPORT_ADDR_CMP_MODE_ADDR3)) {
633 if ((r=nr_local_addr_copy(addrp, &addrs[i])))
634 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
635 break;
636 }
637 }
638
639 // if default addr is not in local addrs, just copy the transport addr
640 // to output arg.
641 if (i == addr_ct) {
642 if ((r=nr_transport_addr_copy(&addrp->addr, &default_addr)))
643 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
644 (void)strlcpy(addrp->addr.ifname, "default route", sizeof(addrp->addr.ifname))(strncpy((addrp->addr.ifname),("default route"),(sizeof(addrp
->addr.ifname))), ((sizeof(addrp->addr.ifname))<= 0 ?
0 : ((addrp->addr.ifname)[(sizeof(addrp->addr.ifname))
-1]='\0')), strlen(("default route")))
;
645 }
646
647 _status=0;
648 abort:
649 return(_status);
650 }
651
652/* if handed a IPv4 default_local_addr, looks for IPv6 address on same interface
653 if handed a IPv6 default_local_addr, looks for IPv4 address on same interface
654*/
655static int nr_ice_get_assoc_interface_address(nr_local_addr* default_local_addr,
656 nr_local_addr* local_addrs, int addr_ct,
657 nr_local_addr* assoc_addrp)
658 {
659 int r, _status;
660 int i, ip_version;
661
662 if (!default_local_addr || !local_addrs || !addr_ct) {
663 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
664 }
665
666 /* set _status to R_EOD in case we don't find an associated address */
667 _status = R_EOD5;
668
669 /* look for IPv6 if we have IPv4, look for IPv4 if we have IPv6 */
670 ip_version = (NR_IPV44 == default_local_addr->addr.ip_version?NR_IPV66:NR_IPV44);
671
672 for (i=0; i<addr_ct; ++i) {
673 /* if we find the ip_version we're looking for on the matching interface,
674 copy it to assoc_addrp.
675 */
676 if (local_addrs[i].addr.ip_version == ip_version &&
677 !strcmp(local_addrs[i].addr.ifname, default_local_addr->addr.ifname)) {
678 if (r=nr_local_addr_copy(assoc_addrp, &local_addrs[i])) {
679 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
680 }
681 _status = 0;
682 break;
683 }
684 }
685
686 abort:
687 return(_status);
688 }
689
690int nr_ice_set_local_addresses(nr_ice_ctx *ctx,
691 nr_local_addr* stun_addrs, int stun_addr_ct)
692 {
693 int r,_status;
694 nr_local_addr local_addrs[MAXADDRS100];
695 nr_local_addr *addrs = 0;
696 int i,addr_ct;
697 nr_local_addr default_addrs[2];
698 int default_addr_ct = 0;
699
700 if (!stun_addrs || !stun_addr_ct) {
701 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): no stun addrs provided",ctx->label);
702 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
703 }
704
705 addr_ct = MIN(stun_addr_ct, MAXADDRS)(((stun_addr_ct)<(100))?(stun_addr_ct):(100));
706 r_log(LOG_ICE, LOG_DEBUG7, "ICE(%s): copy %d pre-fetched stun addrs", ctx->label, addr_ct);
707 for (i=0; i<addr_ct; ++i) {
708 if (r=nr_local_addr_copy(&local_addrs[i], &stun_addrs[i])) {
709 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
710 }
711 }
712
713 // removes duplicates and, based on prefs, loopback and link_local addrs
714 if (r = nr_stun_filter_addrs(
715 local_addrs, !(ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LOOPBACK(1 << 7)),
716 !(ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LINK_LOCAL(1 << 8)), &addr_ct)) {
717 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
718 }
719
720 if (ctx->force_net_interface[0] && addr_ct) {
721 /* Limit us to only addresses on a single interface */
722 int force_addr_ct = 0;
723 for(i=0;i<addr_ct;i++){
724 if (!strcmp(local_addrs[i].addr.ifname, ctx->force_net_interface)) {
725 // copy it down in the array, if needed
726 if (i != force_addr_ct) {
727 if (r=nr_local_addr_copy(&local_addrs[force_addr_ct], &local_addrs[i])) {
728 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
729 }
730 }
731 force_addr_ct++;
732 }
733 }
734 addr_ct = force_addr_ct;
735 }
736
737 r_log(LOG_ICE, LOG_DEBUG7,
738 "ICE(%s): use only default local addresses: %s\n",
739 ctx->label,
740 (char*)(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS(1<<4)?"yes":"no"));
741 if ((!addr_ct) || (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS(1<<4))) {
742 if (ctx->target_for_default_local_address_lookup) {
743 /* Get just the default IPv4 or IPv6 addr */
744 if(!nr_ice_get_default_local_address(
745 ctx, ctx->target_for_default_local_address_lookup->ip_version,
746 local_addrs, addr_ct, &default_addrs[default_addr_ct])) {
747 nr_local_addr *new_addr = &default_addrs[default_addr_ct];
748
749 ++default_addr_ct;
750
751 /* If we have a default target address, check for an associated
752 address on the same interface. For example, if the default
753 target address is IPv6, this will find an associated IPv4
754 address on the same interface.
755 This makes ICE w/ dual stacks work better - Bug 1609124.
756 */
757 if(!nr_ice_get_assoc_interface_address(
758 new_addr, local_addrs, addr_ct,
759 &default_addrs[default_addr_ct])) {
760 ++default_addr_ct;
761 }
762 }
763 } else {
764 /* Get just the default IPv4 and IPv6 addrs */
765 if(!nr_ice_get_default_local_address(ctx, NR_IPV44, local_addrs, addr_ct,
766 &default_addrs[default_addr_ct])) {
767 ++default_addr_ct;
768 }
769 if(!nr_ice_get_default_local_address(ctx, NR_IPV66, local_addrs, addr_ct,
770 &default_addrs[default_addr_ct])) {
771 ++default_addr_ct;
772 }
773 }
774 if (!default_addr_ct) {
775 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): failed to find default addresses",ctx->label);
776 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; _status=_r; goto abort;} while
(0)
;
777 }
778 addrs = default_addrs;
779 addr_ct = default_addr_ct;
780 }
781 else {
782 addrs = local_addrs;
783 }
784
785 /* Sort interfaces by preference */
786 if(ctx->interface_prioritizer) {
787 for(i=0;i<addr_ct;i++){
788 if((r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) && (r!=R_ALREADY4)) {
789 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): unable to add interface ",ctx->label);
790 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
791 }
792 }
793 if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
794 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): unable to sort interface by preference",ctx->label);
795 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
796 }
797 }
798
799 if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
800 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
801 }
802
803 _status=0;
804 abort:
805 return(_status);
806 }
807
808int nr_ice_set_target_for_default_local_address_lookup(nr_ice_ctx *ctx, const char *target_ip, UINT2 target_port)
809 {
810 int r,_status;
811
812 if (ctx->target_for_default_local_address_lookup) {
813 free(ctx->target_for_default_local_address_lookup);
814 ctx->target_for_default_local_address_lookup=0;
815 }
816
817 if (!(ctx->target_for_default_local_address_lookup=R_NEW(nr_transport_addr)(nr_transport_addr*)calloc(1,sizeof(nr_transport_addr))))
818 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
819
820 if ((r=nr_str_port_to_transport_addr(target_ip, nullptr, target_port, IPPROTO_UDPIPPROTO_UDP, ctx->target_for_default_local_address_lookup))) {
821 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
822 }
823
824 /* Default local address lookup uses a UDP connect() to the target. An
825 * FQDN target would need DNS resolution that this code does not do. */
826 if (ctx->target_for_default_local_address_lookup->fqdn[0] != '\0') {
827 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
828 }
829
830 _status=0;
831 abort:
832 if (_status) {
833 free(ctx->target_for_default_local_address_lookup);
834 ctx->target_for_default_local_address_lookup=0;
835 }
836 return(_status);
837 }
838
839 int nr_ice_gather(nr_ice_ctx* ctx, NR_async_cb gather_done_cb, void* cb_arg) {
840 int r,_status;
841 nr_ice_media_stream *stream;
842 nr_local_addr stun_addrs[MAXADDRS100];
843 int stun_addr_ct;
844
845 if (!ctx->local_addrs) {
846 if((r=nr_stun_get_addrs(stun_addrs,MAXADDRS100,&stun_addr_ct))) {
847 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
848 }
849 if((r=nr_ice_set_local_addresses(ctx,stun_addrs,stun_addr_ct))) {
850 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
851 }
852 }
853
854 if(STAILQ_EMPTY(&ctx->streams)((&ctx->streams)->stqh_first == __null)) {
855 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Missing streams to initialize",ctx->label);
856 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
857 }
858
859 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): Initializing candidates",ctx->label);
860 ctx->gather_done_cb = gather_done_cb;
861 ctx->cb_arg=cb_arg;
862
863 /* Initialize all the media stream/component pairs */
864 stream=STAILQ_FIRST(&ctx->streams)((&ctx->streams)->stqh_first);
865 while(stream){
866 if(!stream->obsolete) {
867 if(r=nr_ice_media_stream_initialize(ctx,stream)) {
868 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Failed to initialize a stream; this might not be an unrecoverable error, if this stream will be marked obsolete soon due to an ICE restart.",ctx->label);
869 }
870 }
871
872 stream=STAILQ_NEXT(stream,entry)((stream)->entry.stqe_next);
873 }
874
875 if(ctx->uninitialized_candidates)
876 ABORT(R_WOULDBLOCK)do { int _r=8; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
877
878 _status=0;
879 abort:
880 return(_status);
881 }
882
883int nr_ice_add_media_stream(nr_ice_ctx *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp)
884 {
885 int r,_status;
886
887 if(r=nr_ice_media_stream_create(ctx,label,ufrag,pwd,components,streamp))
888 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
889
890 STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry)do { (((*streamp))->entry.stqe_next) = __null; *(&ctx->
streams)->stqh_last = (*streamp); (&ctx->streams)->
stqh_last = &(((*streamp))->entry.stqe_next); } while (
0)
;
891
892 _status=0;
893 abort:
894 return(_status);
895 }
896
897int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp)
898 {
899 int r,_status;
900 nr_ice_peer_ctx *pctx;
901 nr_ice_media_stream *peer_stream;
902
903 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
904 while(pctx){
905 if(!nr_ice_peer_ctx_find_pstream(pctx, *streamp, &peer_stream)) {
906 if(r=nr_ice_peer_ctx_remove_pstream(pctx, &peer_stream)) {
907 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
908 }
909 }
910
911 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
912 }
913
914 STAILQ_REMOVE(&ctx->streams,*streamp,nr_ice_media_stream_,entry)do { if ((((&ctx->streams))->stqh_first) == (*streamp
)) { do { if ((((((&ctx->streams)))->stqh_first) = (
(((((&ctx->streams)))->stqh_first))->entry.stqe_next
)) == __null) ((&ctx->streams))->stqh_last = &(
(((&ctx->streams)))->stqh_first); } while (0); } else
{ struct nr_ice_media_stream_ *curelm = (((&ctx->streams
))->stqh_first); while (((curelm)->entry.stqe_next) != (
*streamp)) curelm = ((curelm)->entry.stqe_next); if ((((curelm
)->entry.stqe_next) = ((((curelm)->entry.stqe_next))->
entry.stqe_next)) == __null) (&ctx->streams)->stqh_last
= &(((curelm))->entry.stqe_next); } } while (0)
;
915 if(r=nr_ice_media_stream_destroy(streamp)) {
916 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
917 }
918
919 _status=0;
920 abort:
921 return(_status);
922 }
923
924int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp)
925 {
926 *attrctp=0;
927 *attrsp=0;
928 return(0);
929 }
930
931/* This is incredibly annoying: we now have a datagram but we don't
932 know which peer it's from, and we need to be able to tell the
933 API user. So, offer it to each peer and if one bites, assume
934 the others don't want it
935*/
936int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
937 {
938 nr_ice_peer_ctx *pctx;
939 int r;
940
941 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
942 while(pctx){
943 r=nr_ice_peer_ctx_deliver_packet_maybe(pctx, comp, source_addr, data, len);
944 if(!r)
945 break;
946
947 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
948 }
949
950 if(!pctx)
951 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Packet received from %s which doesn't match any known peer",ctx->label,source_addr->as_string);
952
953 return(0);
954 }
955
956int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
957 {
958 nr_ice_stun_id *xid;
959
960 xid=STAILQ_FIRST(&ctx->ids)((&ctx->ids)->stqh_first);
961 while(xid){
962 if (!memcmp(xid->id, id, 12))
963 return 1;
964
965 xid=STAILQ_NEXT(xid,entry)((xid)->entry.stqe_next);
966 }
967
968 return 0;
969 }
970
971int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg)
972{
973 int _status;
974 nr_ice_stun_id *xid;
975
976 xid = R_NEW(nr_ice_stun_id)(nr_ice_stun_id*)calloc(1,sizeof(nr_ice_stun_id));
977 if (!xid)
978 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
979
980 assert(sizeof(xid->id) == sizeof(msg->header.id))(static_cast <bool> (sizeof(xid->id) == sizeof(msg->
header.id)) ? void (0) : __assert_fail ("sizeof(xid->id) == sizeof(msg->header.id)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
981#if __STDC_VERSION__ >= 201112L
982 _Static_assert(sizeof(xid->id) == sizeof(msg->header.id),"Message ID Size Mismatch");
983#endif
984 memcpy(xid->id, &msg->header.id, sizeof(xid->id));
985
986 STAILQ_INSERT_TAIL(&ctx->ids,xid,entry)do { (((xid))->entry.stqe_next) = __null; *(&ctx->ids
)->stqh_last = (xid); (&ctx->ids)->stqh_last = &
(((xid))->entry.stqe_next); } while (0)
;
987
988 _status=0;
989 abort:
990 return(_status);
991}
992
993
994int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
995{
996 ctx->trickle_cb = cb;
997 ctx->trickle_cb_arg = cb_arg;
998
999 return 0;
1000}
1001
1002int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
1003 {
1004 if (cand->state != NR_ICE_CAND_STATE_INITIALIZED3) {
1005 return 1;
1006 }
1007
1008 if (ctx->flags & NR_ICE_CTX_FLAGS_DISABLE_HOST_CANDIDATES(1<<3)) {
1009 if (cand->type == HOST)
1010 return 1;
1011 }
1012
1013 if (cand->stream->obsolete) {
1014 return 1;
1015 }
1016
1017 return 0;
1018 }
1019