Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c
Warning:line 525, column 11
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 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_c_third_party_nICEr0.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -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-21/lib/clang/21 -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/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -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_TURN -D USE_ICE -D USE_RFC_3489_BACKWARDS_COMPATIBLE -D USE_STUND_0_96 -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/plugin -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/stats -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/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -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-unknown-warning-option -Wno-parentheses -Wno-strict-prototypes -Wno-format -Wno-format-security -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c Unified_c_third_party_nICEr0.c
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 "nr_socket_local.h"
54
55#define ICE_UFRAG_LEN8 8
56#define ICE_PWD_LEN32 32
57
58int LOG_ICE = 0;
59
60static int nr_ice_random_string(char *str, int len);
61static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
62#ifdef USE_TURN1
63static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
64#endif /* USE_TURN */
65static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand);
66static int no_op(void **obj) {
67 return 0;
68}
69
70static nr_socket_factory_vtbl default_socket_factory_vtbl = {
71 nr_socket_local_create,
72 no_op
73};
74
75int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
76 {
77 int r,_status;
78 nr_ice_stun_server *servers = 0;
79 int i;
80 NR_registry child;
81 char *addr=0;
82 UINT2 port;
83 in_addr_t addr_int;
84
85 if(!(servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)r_calloc(0,1,sizeof(nr_ice_stun_server)*ct)))
86 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
87
88 for(i=0;i<ct;i++){
89 if(r=NR_reg_get_child_registry(NR_ICE_REG_STUN_SRV_PRFX"ice.stun.server",i,child))
90 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
91 /* Assume we have a v4 addr for now */
92 if(r=NR_reg_alloc2_string(child,"addr",&addr))
93 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
94 addr_int=inet_addr(addr);
95 if(addr_int==INADDR_NONE((in_addr_t) 0xffffffff)){
96 r_log(LOG_ICE,LOG_ERR3,"Invalid address %s;",addr);
97 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
98 }
99 if(r=NR_reg_get2_uint2(child,"port",&port)) {
100 if (r != R_NOT_FOUND2)
101 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
102 port = 3478;
103 }
104 if (r = nr_ip4_port_to_transport_addr(ntohl(addr_int)__bswap_32 (addr_int), port, IPPROTO_UDPIPPROTO_UDP,
105 &servers[i].addr))
106 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
107 RFREE(addr)if(addr) r_free(addr);
108 addr=0;
109 }
110
111 *out = servers;
112
113 _status=0;
114 abort:
115 RFREE(addr)if(addr) r_free(addr);
116 if (_status) RFREE(servers)if(servers) r_free(servers);
117 return(_status);
118 }
119
120int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
121 {
122 int _status;
123
124 if(ctx->stun_servers_cfg){
125 RFREE(ctx->stun_servers_cfg)if(ctx->stun_servers_cfg) r_free(ctx->stun_servers_cfg);
126 ctx->stun_servers_cfg=NULL((void*)0);
127 ctx->stun_server_ct_cfg=0;
128 }
129
130 if (ct) {
131 if(!(ctx->stun_servers_cfg=RCALLOC(sizeof(nr_ice_stun_server)*ct)r_calloc(0,1,sizeof(nr_ice_stun_server)*ct)))
132 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
133
134 memcpy(ctx->stun_servers_cfg,servers,sizeof(nr_ice_stun_server)*ct);
135 ctx->stun_server_ct_cfg = ct;
136 }
137
138 _status=0;
139 abort:
140 return(_status);
141 }
142
143int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
144 {
145 int _status;
146
147 if(ctx->turn_servers_cfg){
148 for (int i = 0; i < ctx->turn_server_ct_cfg; i++) {
149 RFREE(ctx->turn_servers_cfg[i].username)if(ctx->turn_servers_cfg[i].username) r_free(ctx->turn_servers_cfg
[i].username)
;
150 r_data_destroy(&ctx->turn_servers_cfg[i].password);
151 }
152 RFREE(ctx->turn_servers_cfg)if(ctx->turn_servers_cfg) r_free(ctx->turn_servers_cfg);
153 ctx->turn_servers_cfg=NULL((void*)0);
154 ctx->turn_server_ct_cfg=0;
155 }
156
157 if(ct) {
158 if(!(ctx->turn_servers_cfg=RCALLOC(sizeof(nr_ice_turn_server)*ct)r_calloc(0,1,sizeof(nr_ice_turn_server)*ct)))
159 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
160
161 memcpy(ctx->turn_servers_cfg,servers,sizeof(nr_ice_turn_server)*ct);
162 ctx->turn_server_ct_cfg = ct;
163 }
164
165 _status=0;
166 abort:
167 return(_status);
168 }
169
170int nr_ice_ctx_copy_turn_servers(nr_ice_ctx *ctx, nr_ice_turn_server *servers, int ct)
171 {
172 int _status, i, r;
173
174 if (r = nr_ice_ctx_set_turn_servers(ctx, servers, ct)) {
175 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
176 }
177
178 // make copies of the username and password so they aren't freed twice
179 for (i = 0; i < ct; ++i) {
180 if (!(ctx->turn_servers_cfg[i].username = r_strdup(servers[i].username))) {
181 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
182 }
183 if (r = r_data_create(&ctx->turn_servers_cfg[i].password,
184 servers[i].password->data,
185 servers[i].password->len)) {
186 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
187 }
188 }
189
190 _status=0;
191 abort:
192 return(_status);
193 }
194
195static int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
196 {
197 int _status,i,r;
198
199 if(ctx->local_addrs) {
200 RFREE(ctx->local_addrs)if(ctx->local_addrs) r_free(ctx->local_addrs);
201 ctx->local_addr_ct=0;
202 ctx->local_addrs=0;
203 }
204
205 if (ct) {
206 if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct)r_calloc(0,1,sizeof(nr_local_addr)*ct)))
207 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
208
209 for (i=0;i<ct;++i) {
210 if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
211 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
212 }
213 }
214 ctx->local_addr_ct = ct;
215 }
216
217 _status=0;
218 abort:
219 return(_status);
220 }
221
222int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
223 {
224 int _status;
225
226 if (ctx->resolver) {
227 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
228 }
229
230 ctx->resolver = resolver;
231
232 _status=0;
233 abort:
234 return(_status);
235 }
236
237int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
238 {
239 int _status;
240
241 if (ctx->interface_prioritizer) {
242 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
243 }
244
245 ctx->interface_prioritizer = ip;
246
247 _status=0;
248 abort:
249 return(_status);
250 }
251
252void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory)
253 {
254 nr_socket_factory_destroy(&ctx->socket_factory);
255 ctx->socket_factory = factory;
256 }
257
258#ifdef USE_TURN1
259int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
260 {
261 int r,_status;
262 nr_ice_turn_server *servers = 0;
263 int i;
264 NR_registry child;
265 char *addr=0;
266 UINT2 port;
267 in_addr_t addr_int;
268 Data data={0};
269
270 if(!(servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)r_calloc(0,1,sizeof(nr_ice_turn_server)*ct)))
271 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
272
273 for(i=0;i<ct;i++){
274 if(r=NR_reg_get_child_registry(NR_ICE_REG_TURN_SRV_PRFX"ice.turn.server",i,child))
275 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
276 /* Assume we have a v4 addr for now */
277 if(r=NR_reg_alloc2_string(child,"addr",&addr))
278 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
279 addr_int=inet_addr(addr);
280 if(addr_int==INADDR_NONE((in_addr_t) 0xffffffff)){
281 r_log(LOG_ICE,LOG_ERR3,"Invalid address %s",addr);
282 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
283 }
284 if(r=NR_reg_get2_uint2(child,"port",&port)) {
285 if (r != R_NOT_FOUND2)
286 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
287 port = 3478;
288 }
289 if (r = nr_ip4_port_to_transport_addr(ntohl(addr_int)__bswap_32 (addr_int), port, IPPROTO_UDPIPPROTO_UDP,
290 &servers[i].turn_server.addr))
291 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
292
293
294 if(r=NR_reg_alloc2_string(child,NR_ICE_REG_TURN_SRV_USERNAME"username",&servers[i].username)){
295 if(r!=R_NOT_FOUND2)
296 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
297 }
298
299 if(r=NR_reg_alloc2_data(child,NR_ICE_REG_TURN_SRV_PASSWORD"password",&data)){
300 if(r!=R_NOT_FOUND2)
301 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
302 }
303 else {
304 servers[i].password=RCALLOC(sizeof(*servers[i].password))r_calloc(0,1,sizeof(*servers[i].password));
305 if(!servers[i].password)
306 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
307 servers[i].password->data = data.data;
308 servers[i].password->len = data.len;
309 data.data=0;
310 }
311
312 RFREE(addr)if(addr) r_free(addr);
313 addr=0;
314 }
315
316 *out = servers;
317
318 _status=0;
319 abort:
320 RFREE(data.data)if(data.data) r_free(data.data);
321 RFREE(addr)if(addr) r_free(addr);
322 if (_status) RFREE(servers)if(servers) r_free(servers);
323 return(_status);
324 }
325#endif /* USE_TURN */
326
327#define MAXADDRS100 100 /* Ridiculously high */
328 int nr_ice_ctx_create(char* label, UINT4 flags,
329 nr_ice_gather_handler* gather_handler,
330 nr_ice_ctx** ctxp) {
331 nr_ice_ctx *ctx=0;
332 int r,_status;
333
334 if(r=r_log_register("ice", &LOG_ICE))
335 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
336
337 if(!(ctx=RCALLOC(sizeof(nr_ice_ctx))r_calloc(0,1,sizeof(nr_ice_ctx))))
338 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
339
340 ctx->flags=flags;
341
342 if(!(ctx->label=r_strdup(label)))
343 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
344
345 ctx->gather_handler = gather_handler;
346
347 /* Get the STUN servers */
348 if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX"ice.stun.server",
349 (unsigned int *)&ctx->stun_server_ct_cfg)||ctx->stun_server_ct_cfg==0) {
350 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): No STUN servers specified in nICEr registry", ctx->label);
351 ctx->stun_server_ct_cfg=0;
352 }
353
354 /* 31 is the max for our priority algorithm */
355 if(ctx->stun_server_ct_cfg>31){
356 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Too many STUN servers specified: max=31", ctx->label);
357 ctx->stun_server_ct_cfg=31;
358 }
359
360 if(ctx->stun_server_ct_cfg>0){
361 if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct_cfg,&ctx->stun_servers_cfg)){
362 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Couldn't load STUN servers from registry", ctx->label);
363 ctx->stun_server_ct_cfg=0;
364 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
365 }
366 }
367
368#ifdef USE_TURN1
369 /* Get the TURN servers */
370 if(r=NR_reg_get_child_count(NR_ICE_REG_TURN_SRV_PRFX"ice.turn.server",
371 (unsigned int *)&ctx->turn_server_ct_cfg)||ctx->turn_server_ct_cfg==0) {
372 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): No TURN servers specified in nICEr registry", ctx->label);
373 ctx->turn_server_ct_cfg=0;
374 }
375#else
376 ctx->turn_server_ct_cfg=0;
377#endif /* USE_TURN */
378
379 ctx->local_addrs=0;
380 ctx->local_addr_ct=0;
381
382 /* 31 is the max for our priority algorithm */
383 if((ctx->stun_server_ct_cfg+ctx->turn_server_ct_cfg)>31){
384 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Too many STUN/TURN servers specified: max=31", ctx->label);
385 ctx->turn_server_ct_cfg=31-ctx->stun_server_ct_cfg;
386 }
387
388#ifdef USE_TURN1
389 if(ctx->turn_server_ct_cfg>0){
390 if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct_cfg,&ctx->turn_servers_cfg)){
391 ctx->turn_server_ct_cfg=0;
392 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Couldn't load TURN servers from registry", ctx->label);
393 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
394 }
395 }
396#endif /* USE_TURN */
397
398
399 ctx->Ta = 20;
400
401 ctx->test_timer_divider = 0;
402
403 if (r=nr_socket_factory_create_int(NULL((void*)0), &default_socket_factory_vtbl, &ctx->socket_factory))
404 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
405
406 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)))) {
407 if (r == R_NOT_FOUND2) {
408 ctx->force_net_interface[0] = 0;
409 } else {
410 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
411 }
412 }
413
414 ctx->target_for_default_local_address_lookup=0;
415
416 STAILQ_INIT(&ctx->streams)do { (((&ctx->streams))->stqh_first) = ((void*)0); (
&ctx->streams)->stqh_last = &(((&ctx->streams
))->stqh_first); } while (0)
;
417 STAILQ_INIT(&ctx->sockets)do { (((&ctx->sockets))->stqh_first) = ((void*)0); (
&ctx->sockets)->stqh_last = &(((&ctx->sockets
))->stqh_first); } while (0)
;
418 STAILQ_INIT(&ctx->foundations)do { (((&ctx->foundations))->stqh_first) = ((void*)
0); (&ctx->foundations)->stqh_last = &(((&ctx
->foundations))->stqh_first); } while (0)
;
419 STAILQ_INIT(&ctx->peers)do { (((&ctx->peers))->stqh_first) = ((void*)0); (&
ctx->peers)->stqh_last = &(((&ctx->peers))->
stqh_first); } while (0)
;
420 STAILQ_INIT(&ctx->ids)do { (((&ctx->ids))->stqh_first) = ((void*)0); (&
ctx->ids)->stqh_last = &(((&ctx->ids))->stqh_first
); } while (0)
;
421
422 *ctxp=ctx;
423
424 _status=0;
425 abort:
426 if (_status && ctx) nr_ice_ctx_destroy(&ctx);
427
428 return(_status);
429 }
430
431 void nr_ice_ctx_add_flags(nr_ice_ctx* ctx, UINT4 flags) {
432 ctx->flags |= flags;
433 }
434
435 void nr_ice_ctx_remove_flags(nr_ice_ctx* ctx, UINT4 flags) {
436 ctx->flags &= ~flags;
437 }
438
439 void nr_ice_ctx_destroy(nr_ice_ctx** ctxp) {
440 if (!ctxp || !*ctxp) return;
441
442 nr_ice_ctx* ctx = *ctxp;
443 nr_ice_foundation *f1,*f2;
444 nr_ice_media_stream *s1,*s2;
445 int i;
446 nr_ice_stun_id *id1,*id2;
447
448 ctx->gather_done_cb = 0;
449 ctx->trickle_cb = 0;
450
451 STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2)for ((s1) = (((&ctx->streams))->stqh_first); (s1) &&
((s2) = (((s1))->entry.stqe_next), 1); (s1) = (s2))
{
452 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
)) == ((void*)0)) ((&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)) == ((void*)0)) (&ctx->streams)->stqh_last
= &(((curelm))->entry.stqe_next); } } while (0)
;
453 nr_ice_media_stream_destroy(&s1);
454 }
455
456 RFREE(ctx->label)if(ctx->label) r_free(ctx->label);
457
458 ctx->gather_handler = 0;
459
460 RFREE(ctx->stun_servers_cfg)if(ctx->stun_servers_cfg) r_free(ctx->stun_servers_cfg);
461
462 RFREE(ctx->local_addrs)if(ctx->local_addrs) r_free(ctx->local_addrs);
463
464 RFREE(ctx->target_for_default_local_address_lookup)if(ctx->target_for_default_local_address_lookup) r_free(ctx
->target_for_default_local_address_lookup)
;
465
466 for (i = 0; i < ctx->turn_server_ct_cfg; i++) {
467 RFREE(ctx->turn_servers_cfg[i].username)if(ctx->turn_servers_cfg[i].username) r_free(ctx->turn_servers_cfg
[i].username)
;
468 r_data_destroy(&ctx->turn_servers_cfg[i].password);
469 }
470 RFREE(ctx->turn_servers_cfg)if(ctx->turn_servers_cfg) r_free(ctx->turn_servers_cfg);
471
472 f1=STAILQ_FIRST(&ctx->foundations)((&ctx->foundations)->stqh_first);
473 while(f1){
474 f2=STAILQ_NEXT(f1,entry)((f1)->entry.stqe_next);
475 RFREE(f1)if(f1) r_free(f1);
476 f1=f2;
477 }
478
479 STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2)for ((id1) = (((&ctx->ids))->stqh_first); (id1) &&
((id2) = (((id1))->entry.stqe_next), 1); (id1) = (id2))
{
480 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)) == ((void
*)0)) ((&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)) == ((void*)0)) (
&ctx->ids)->stqh_last = &(((curelm))->entry.
stqe_next); } } while (0)
;
481 RFREE(id1)if(id1) r_free(id1);
482 }
483
484 nr_resolver_destroy(&ctx->resolver);
485 nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
486 nr_socket_factory_destroy(&ctx->socket_factory);
487
488 RFREE(ctx)if(ctx) r_free(ctx);
489
490 *ctxp=0;
491 }
492
493void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
494 {
495 int r;
496 nr_ice_candidate *cand=cb_arg;
497 nr_ice_ctx *ctx;
498 nr_ice_media_stream *stream;
499 int component_id;
500
501 assert(cb_arg)((void) sizeof ((cb_arg) ? 1 : 0), __extension__ ({ if (cb_arg
) ; else __assert_fail ("cb_arg", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c"
, 501, __extension__ __PRETTY_FUNCTION__); }))
;
502 if (!cb_arg)
503 return;
504 ctx = cand->ctx;
505 stream = cand->stream;
506 component_id = cand->component_id;
507
508 ctx->uninitialized_candidates--;
509 if (cand->state == NR_ICE_CAND_STATE_FAILED4) {
510 r_log(LOG_ICE, LOG_WARNING4,
511 "ICE(%s)/CAND(%s): failed to initialize, %d remaining", ctx->label,
512 cand->label, ctx->uninitialized_candidates);
513 } else {
514 r_log(LOG_ICE, LOG_DEBUG7, "ICE(%s)/CAND(%s): initialized, %d remaining",
515 ctx->label, cand->label, ctx->uninitialized_candidates);
516 }
517
518 /* Avoid the need for yet another initialization function */
519 if (cand->state == NR_ICE_CAND_STATE_INITIALIZING2 && cand->type == HOST)
520 cand->state = NR_ICE_CAND_STATE_INITIALIZED3;
521
522 if (cand->state == NR_ICE_CAND_STATE_INITIALIZED3) {
523 int was_pruned = 0;
524
525 if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
526 cand, &was_pruned)) {
527 r_log(LOG_ICE, LOG_NOTICE5, "ICE(%s): Problem pruning candidates",ctx->label);
528 }
529
530 if (was_pruned) {
531 cand = NULL((void*)0);
532 }
533
534 /* If we are initialized, the candidate wasn't pruned,
535 and we have a trickle ICE callback fire the callback */
536 if (ctx->trickle_cb && cand &&
537 !nr_ice_ctx_hide_candidate(ctx, cand)) {
538 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
539
540 if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
541 r_log(LOG_ICE,LOG_ERR3, "ICE(%s): All could not pair new trickle candidate",ctx->label);
542 /* But continue */
543 }
544 }
545 }
546
547 if (nr_ice_media_stream_is_done_gathering(stream)) {
548 if (ctx->gather_handler && ctx->gather_handler->vtbl->stream_gathered) {
549 ctx->gather_handler->vtbl->stream_gathered(ctx->gather_handler->obj,
550 stream);
551 }
552 if (ctx->trickle_cb) {
553 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, stream, component_id, NULL((void*)0));
554 }
555 }
556
557 if(ctx->uninitialized_candidates==0){
558 assert(nr_ice_media_stream_is_done_gathering(stream))((void) sizeof ((nr_ice_media_stream_is_done_gathering(stream
)) ? 1 : 0), __extension__ ({ if (nr_ice_media_stream_is_done_gathering
(stream)) ; else __assert_fail ("nr_ice_media_stream_is_done_gathering(stream)"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c"
, 558, __extension__ __PRETTY_FUNCTION__); }))
;
559 r_log(LOG_ICE, LOG_INFO6, "ICE(%s): All candidates initialized",
560 ctx->label);
561 if (ctx->gather_done_cb) {
562 ctx->gather_done_cb(0, 0, ctx->cb_arg);
563 } else {
564 r_log(LOG_ICE, LOG_INFO6,
565 "ICE(%s): No gather_done_cb. We were probably destroyed.",
566 ctx->label);
567 }
568 }
569 else {
570 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): Waiting for %d candidates to be initialized",ctx->label, ctx->uninitialized_candidates);
571 }
572 }
573
574static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
575 {
576 int r,_status;
577 nr_ice_peer_ctx *pctx;
578
579 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
580 while(pctx){
581 if (pctx->state == NR_ICE_PEER_STATE_PAIRED2) {
582 r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
583 if (r)
584 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
585 }
586
587 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
588 }
589
590 _status=0;
591 abort:
592 return(_status);
593 }
594
595/* Get the default address by creating a UDP socket, binding it to a wildcard
596 address, and connecting it to the remote IP. Because this is UDP, no packets
597 are sent. This lets us query the local address assigned to the socket by the
598 kernel.
599
600 If the context's remote address is NULL, then the application wasn't loaded
601 over the network, and we can fall back on connecting to a known public
602 address (namely Google's):
603
604 IPv4: 8.8.8.8
605 IPv6: 2001:4860:4860::8888
606*/
607static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transport_addr* addrp)
608 {
609 int r,_status;
610 nr_transport_addr addr, known_remote_addr;
611 nr_transport_addr *remote_addr=ctx->target_for_default_local_address_lookup;
612 nr_socket *sock=0;
613
614 switch(ip_version) {
615 case NR_IPV44:
616 if ((r=nr_str_port_to_transport_addr("0.0.0.0", 0, IPPROTO_UDPIPPROTO_UDP, &addr)))
617 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
618 if (!remote_addr || nr_transport_addr_is_loopback(remote_addr)) {
619 if ((r=nr_str_port_to_transport_addr("8.8.8.8", 53, IPPROTO_UDPIPPROTO_UDP, &known_remote_addr)))
620 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
621 remote_addr=&known_remote_addr;
622 }
623 break;
624 case NR_IPV66:
625 if ((r=nr_str_port_to_transport_addr("::0", 0, IPPROTO_UDPIPPROTO_UDP, &addr)))
626 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
627 if (!remote_addr || nr_transport_addr_is_loopback(remote_addr)) {
628 if ((r=nr_str_port_to_transport_addr("2001:4860:4860::8888", 53, IPPROTO_UDPIPPROTO_UDP, &known_remote_addr)))
629 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
630 remote_addr=&known_remote_addr;
631 }
632 break;
633 default:
634 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c"
, 634, __extension__ __PRETTY_FUNCTION__); }))
;
635 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
636 }
637
638 if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
639 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
640 if ((r=nr_socket_connect(sock, remote_addr)))
641 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
642 if ((r=nr_socket_getaddr(sock, addrp)))
643 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
644
645 r_log(LOG_GENERIC0, LOG_DEBUG7, "Default address: %s", addrp->as_string);
646
647 _status=0;
648 abort:
649 nr_socket_destroy(&sock);
650 return(_status);
651 }
652
653static 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)
654 {
655 int r,_status;
656 nr_transport_addr default_addr;
657 int i;
658
659 if ((r=nr_ice_get_default_address(ctx, ip_version, &default_addr)))
660 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
661
662 for (i=0; i < addr_ct; ++i) {
663 // if default addr is found in local addrs, copy the more fully
664 // complete local addr to the output arg. Don't need to worry
665 // about comparing ports here.
666 if (!nr_transport_addr_cmp(&default_addr, &addrs[i].addr,
667 NR_TRANSPORT_ADDR_CMP_MODE_ADDR3)) {
668 if ((r=nr_local_addr_copy(addrp, &addrs[i])))
669 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
670 break;
671 }
672 }
673
674 // if default addr is not in local addrs, just copy the transport addr
675 // to output arg.
676 if (i == addr_ct) {
677 if ((r=nr_transport_addr_copy(&addrp->addr, &default_addr)))
678 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
679 (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")))
;
680 }
681
682 _status=0;
683 abort:
684 return(_status);
685 }
686
687/* if handed a IPv4 default_local_addr, looks for IPv6 address on same interface
688 if handed a IPv6 default_local_addr, looks for IPv4 address on same interface
689*/
690static int nr_ice_get_assoc_interface_address(nr_local_addr* default_local_addr,
691 nr_local_addr* local_addrs, int addr_ct,
692 nr_local_addr* assoc_addrp)
693 {
694 int r, _status;
695 int i, ip_version;
696
697 if (!default_local_addr || !local_addrs || !addr_ct) {
698 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
699 }
700
701 /* set _status to R_EOD in case we don't find an associated address */
702 _status = R_EOD5;
703
704 /* look for IPv6 if we have IPv4, look for IPv4 if we have IPv6 */
705 ip_version = (NR_IPV44 == default_local_addr->addr.ip_version?NR_IPV66:NR_IPV44);
706
707 for (i=0; i<addr_ct; ++i) {
708 /* if we find the ip_version we're looking for on the matching interface,
709 copy it to assoc_addrp.
710 */
711 if (local_addrs[i].addr.ip_version == ip_version &&
712 !strcmp(local_addrs[i].addr.ifname, default_local_addr->addr.ifname)) {
713 if (r=nr_local_addr_copy(assoc_addrp, &local_addrs[i])) {
714 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
715 }
716 _status = 0;
717 break;
718 }
719 }
720
721 abort:
722 return(_status);
723 }
724
725int nr_ice_set_local_addresses(nr_ice_ctx *ctx,
726 nr_local_addr* stun_addrs, int stun_addr_ct)
727 {
728 int r,_status;
729 nr_local_addr local_addrs[MAXADDRS100];
730 nr_local_addr *addrs = 0;
731 int i,addr_ct;
732 nr_local_addr default_addrs[2];
733 int default_addr_ct = 0;
734
735 if (!stun_addrs || !stun_addr_ct) {
736 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): no stun addrs provided",ctx->label);
737 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
738 }
739
740 addr_ct = MIN(stun_addr_ct, MAXADDRS)(((stun_addr_ct)<(100))?(stun_addr_ct):(100));
741 r_log(LOG_ICE, LOG_DEBUG7, "ICE(%s): copy %d pre-fetched stun addrs", ctx->label, addr_ct);
742 for (i=0; i<addr_ct; ++i) {
743 if (r=nr_local_addr_copy(&local_addrs[i], &stun_addrs[i])) {
744 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
745 }
746 }
747
748 // removes duplicates and, based on prefs, loopback and link_local addrs
749 if (r=nr_stun_filter_local_addresses(local_addrs, &addr_ct)) {
750 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
751 }
752
753 if (ctx->force_net_interface[0] && addr_ct) {
754 /* Limit us to only addresses on a single interface */
755 int force_addr_ct = 0;
756 for(i=0;i<addr_ct;i++){
757 if (!strcmp(local_addrs[i].addr.ifname, ctx->force_net_interface)) {
758 // copy it down in the array, if needed
759 if (i != force_addr_ct) {
760 if (r=nr_local_addr_copy(&local_addrs[force_addr_ct], &local_addrs[i])) {
761 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
762 }
763 }
764 force_addr_ct++;
765 }
766 }
767 addr_ct = force_addr_ct;
768 }
769
770 r_log(LOG_ICE, LOG_DEBUG7,
771 "ICE(%s): use only default local addresses: %s\n",
772 ctx->label,
773 (char*)(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS(1<<4)?"yes":"no"));
774 if ((!addr_ct) || (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS(1<<4))) {
775 if (ctx->target_for_default_local_address_lookup) {
776 /* Get just the default IPv4 or IPv6 addr */
777 if(!nr_ice_get_default_local_address(
778 ctx, ctx->target_for_default_local_address_lookup->ip_version,
779 local_addrs, addr_ct, &default_addrs[default_addr_ct])) {
780 nr_local_addr *new_addr = &default_addrs[default_addr_ct];
781
782 ++default_addr_ct;
783
784 /* If we have a default target address, check for an associated
785 address on the same interface. For example, if the default
786 target address is IPv6, this will find an associated IPv4
787 address on the same interface.
788 This makes ICE w/ dual stacks work better - Bug 1609124.
789 */
790 if(!nr_ice_get_assoc_interface_address(
791 new_addr, local_addrs, addr_ct,
792 &default_addrs[default_addr_ct])) {
793 ++default_addr_ct;
794 }
795 }
796 } else {
797 /* Get just the default IPv4 and IPv6 addrs */
798 if(!nr_ice_get_default_local_address(ctx, NR_IPV44, local_addrs, addr_ct,
799 &default_addrs[default_addr_ct])) {
800 ++default_addr_ct;
801 }
802 if(!nr_ice_get_default_local_address(ctx, NR_IPV66, local_addrs, addr_ct,
803 &default_addrs[default_addr_ct])) {
804 ++default_addr_ct;
805 }
806 }
807 if (!default_addr_ct) {
808 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): failed to find default addresses",ctx->label);
809 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
810 }
811 addrs = default_addrs;
812 addr_ct = default_addr_ct;
813 }
814 else {
815 addrs = local_addrs;
816 }
817
818 /* Sort interfaces by preference */
819 if(ctx->interface_prioritizer) {
820 for(i=0;i<addr_ct;i++){
821 if((r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) && (r!=R_ALREADY4)) {
822 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): unable to add interface ",ctx->label);
823 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
824 }
825 }
826 if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
827 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): unable to sort interface by preference",ctx->label);
828 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
829 }
830 }
831
832 if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
833 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
834 }
835
836 _status=0;
837 abort:
838 return(_status);
839 }
840
841int nr_ice_set_target_for_default_local_address_lookup(nr_ice_ctx *ctx, const char *target_ip, UINT2 target_port)
842 {
843 int r,_status;
844
845 if (ctx->target_for_default_local_address_lookup) {
846 RFREE(ctx->target_for_default_local_address_lookup)if(ctx->target_for_default_local_address_lookup) r_free(ctx
->target_for_default_local_address_lookup)
;
847 ctx->target_for_default_local_address_lookup=0;
848 }
849
850 if (!(ctx->target_for_default_local_address_lookup=RCALLOC(sizeof(nr_transport_addr))r_calloc(0,1,sizeof(nr_transport_addr))))
851 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
852
853 if ((r=nr_str_port_to_transport_addr(target_ip, target_port, IPPROTO_UDPIPPROTO_UDP, ctx->target_for_default_local_address_lookup))) {
854 RFREE(ctx->target_for_default_local_address_lookup)if(ctx->target_for_default_local_address_lookup) r_free(ctx
->target_for_default_local_address_lookup)
;
855 ctx->target_for_default_local_address_lookup=0;
856 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
857 }
858
859 _status=0;
860 abort:
861 return(_status);
862 }
863
864 int nr_ice_gather(nr_ice_ctx* ctx, NR_async_cb gather_done_cb, void* cb_arg) {
865 int r,_status;
866 nr_ice_media_stream *stream;
867 nr_local_addr stun_addrs[MAXADDRS100];
868 int stun_addr_ct;
869
870 if (!ctx->local_addrs) {
871 if((r=nr_stun_find_local_addresses(stun_addrs,MAXADDRS100,&stun_addr_ct))) {
872 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
873 }
874 if((r=nr_ice_set_local_addresses(ctx,stun_addrs,stun_addr_ct))) {
875 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
876 }
877 }
878
879 if(STAILQ_EMPTY(&ctx->streams)((&ctx->streams)->stqh_first == ((void*)0))) {
880 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Missing streams to initialize",ctx->label);
881 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
882 }
883
884 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): Initializing candidates",ctx->label);
885 ctx->gather_done_cb = gather_done_cb;
886 ctx->cb_arg=cb_arg;
887
888 /* Initialize all the media stream/component pairs */
889 stream=STAILQ_FIRST(&ctx->streams)((&ctx->streams)->stqh_first);
890 while(stream){
891 if(!stream->obsolete) {
892 if(r=nr_ice_media_stream_initialize(ctx,stream)) {
893 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);
894 }
895 }
896
897 stream=STAILQ_NEXT(stream,entry)((stream)->entry.stqe_next);
898 }
899
900 if(ctx->uninitialized_candidates)
901 ABORT(R_WOULDBLOCK)do { int _r=8; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
902
903 _status=0;
904 abort:
905 return(_status);
906 }
907
908int 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)
909 {
910 int r,_status;
911
912 if(r=nr_ice_media_stream_create(ctx,label,ufrag,pwd,components,streamp))
913 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
914
915 STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry)do { (((*streamp))->entry.stqe_next) = ((void*)0); *(&
ctx->streams)->stqh_last = (*streamp); (&ctx->streams
)->stqh_last = &(((*streamp))->entry.stqe_next); } while
(0)
;
916
917 _status=0;
918 abort:
919 return(_status);
920 }
921
922int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp)
923 {
924 int r,_status;
925 nr_ice_peer_ctx *pctx;
926 nr_ice_media_stream *peer_stream;
927
928 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
929 while(pctx){
930 if(!nr_ice_peer_ctx_find_pstream(pctx, *streamp, &peer_stream)) {
931 if(r=nr_ice_peer_ctx_remove_pstream(pctx, &peer_stream)) {
932 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
933 }
934 }
935
936 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
937 }
938
939 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
)) == ((void*)0)) ((&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)) == ((void*)0)) (&ctx->streams)->stqh_last
= &(((curelm))->entry.stqe_next); } } while (0)
;
940 if(r=nr_ice_media_stream_destroy(streamp)) {
941 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
942 }
943
944 _status=0;
945 abort:
946 return(_status);
947 }
948
949int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp)
950 {
951 *attrctp=0;
952 *attrsp=0;
953 return(0);
954 }
955
956static int nr_ice_random_string(char *str, int len)
957 {
958 unsigned char bytes[100];
959 size_t needed;
960 int r,_status;
961
962 if(len%2) ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
963 needed=len/2;
964
965 if(needed>sizeof(bytes)) ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
966
967 if(r=nr_crypto_random_bytes(bytes,needed)nr_crypto_vtbl->random_bytes(bytes,needed))
968 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
969
970 if(r=nr_bin2hex(bytes,needed,(unsigned char *)str))
971 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
972
973 _status=0;
974 abort:
975 return(_status);
976 }
977
978/* This is incredibly annoying: we now have a datagram but we don't
979 know which peer it's from, and we need to be able to tell the
980 API user. So, offer it to each peer and if one bites, assume
981 the others don't want it
982*/
983int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
984 {
985 nr_ice_peer_ctx *pctx;
986 int r;
987
988 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
989 while(pctx){
990 r=nr_ice_peer_ctx_deliver_packet_maybe(pctx, comp, source_addr, data, len);
991 if(!r)
992 break;
993
994 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
995 }
996
997 if(!pctx)
998 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);
999
1000 return(0);
1001 }
1002
1003int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
1004 {
1005 nr_ice_stun_id *xid;
1006
1007 xid=STAILQ_FIRST(&ctx->ids)((&ctx->ids)->stqh_first);
1008 while(xid){
1009 if (!memcmp(xid->id, id, 12))
1010 return 1;
1011
1012 xid=STAILQ_NEXT(xid,entry)((xid)->entry.stqe_next);
1013 }
1014
1015 return 0;
1016 }
1017
1018int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg)
1019{
1020 int _status;
1021 nr_ice_stun_id *xid;
1022
1023 xid = RCALLOC(sizeof(*xid))r_calloc(0,1,sizeof(*xid));
1024 if (!xid)
1025 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1026
1027 assert(sizeof(xid->id) == sizeof(msg->header.id))((void) sizeof ((sizeof(xid->id) == sizeof(msg->header.
id)) ? 1 : 0), __extension__ ({ if (sizeof(xid->id) == sizeof
(msg->header.id)) ; else __assert_fail ("sizeof(xid->id) == sizeof(msg->header.id)"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c"
, 1027, __extension__ __PRETTY_FUNCTION__); }))
;
1028#if __STDC_VERSION__201710L >= 201112L
1029 _Static_assert(sizeof(xid->id) == sizeof(msg->header.id),"Message ID Size Mismatch");
1030#endif
1031 memcpy(xid->id, &msg->header.id, sizeof(xid->id));
1032
1033 STAILQ_INSERT_TAIL(&ctx->ids,xid,entry)do { (((xid))->entry.stqe_next) = ((void*)0); *(&ctx->
ids)->stqh_last = (xid); (&ctx->ids)->stqh_last =
&(((xid))->entry.stqe_next); } while (0)
;
1034
1035 _status=0;
1036 abort:
1037 return(_status);
1038}
1039
1040
1041/* Clean up some of the resources (mostly file descriptors) used
1042 by candidates we didn't choose. Note that this still leaves
1043 a fair amount of non-system stuff floating around. This gets
1044 cleaned up when you destroy the ICE ctx */
1045int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx)
1046 {
1047 nr_ice_media_stream *lstr,*rstr;
1048
1049 r_log(LOG_ICE,LOG_DEBUG7,"Finalizing ICE ctx %s, peer=%s",ctx->label,pctx->label);
1050 /*
1051 First find the peer stream, if any
1052 */
1053 lstr=STAILQ_FIRST(&ctx->streams)((&ctx->streams)->stqh_first);
1054 while(lstr){
1055 rstr=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
1056
1057 while(rstr){
1058 if(rstr->local_stream==lstr)
1059 break;
1060
1061 rstr=STAILQ_NEXT(rstr,entry)((rstr)->entry.stqe_next);
1062 }
1063
1064 nr_ice_media_stream_finalize(lstr,rstr);
1065
1066 lstr=STAILQ_NEXT(lstr,entry)((lstr)->entry.stqe_next);
1067 }
1068
1069 return(0);
1070 }
1071
1072
1073int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
1074{
1075 ctx->trickle_cb = cb;
1076 ctx->trickle_cb_arg = cb_arg;
1077
1078 return 0;
1079}
1080
1081int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
1082 {
1083 if (cand->state != NR_ICE_CAND_STATE_INITIALIZED3) {
1084 return 1;
1085 }
1086
1087 if (ctx->flags & NR_ICE_CTX_FLAGS_DISABLE_HOST_CANDIDATES(1<<3)) {
1088 if (cand->type == HOST)
1089 return 1;
1090 }
1091
1092 if (cand->stream->obsolete) {
1093 return 1;
1094 }
1095
1096 return 0;
1097 }
1098
1099int nr_ice_get_new_ice_ufrag(char** ufrag)
1100 {
1101 int r,_status;
1102 char buf[ICE_UFRAG_LEN8+1];
1103
1104 if(r=nr_ice_random_string(buf,ICE_UFRAG_LEN8))
1105 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1106 if(!(*ufrag=r_strdup(buf)))
1107 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1108
1109 _status=0;
1110 abort:
1111 if(_status) {
1112 RFREE(*ufrag)if(*ufrag) r_free(*ufrag);
1113 *ufrag = 0;
1114 }
1115 return(_status);
1116 }
1117
1118int nr_ice_get_new_ice_pwd(char** pwd)
1119 {
1120 int r,_status;
1121 char buf[ICE_PWD_LEN32+1];
1122
1123 if(r=nr_ice_random_string(buf,ICE_PWD_LEN32))
1124 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1125 if(!(*pwd=r_strdup(buf)))
1126 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1127
1128 _status=0;
1129 abort:
1130 if(_status) {
1131 RFREE(*pwd)if(*pwd) r_free(*pwd);
1132 *pwd = 0;
1133 }
1134 return(_status);
1135 }