Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.cpp
Warning:line 345, 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_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/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-09-01-224014-2642839-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);
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=R_NEW_CNT(nr_ice_stun_server, ct)(nr_ice_stun_server*)calloc(ct,sizeof(nr_ice_stun_server))))
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 free(addr);
108 addr=0;
109 }
110
111 *out = servers;
112
113 _status=0;
114 abort:
115 free(addr);
116 if (_status) 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 free(ctx->stun_servers_cfg);
126 ctx->stun_servers_cfg=NULL__null;
127 ctx->stun_server_ct_cfg=0;
128 }
129
130 if (ct) {
131 if(!(ctx->stun_servers_cfg=R_NEW_CNT(nr_ice_stun_server, ct)(nr_ice_stun_server*)calloc(ct,sizeof(nr_ice_stun_server))))
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 free(ctx->turn_servers_cfg[i].username);
150 r_data_destroy(&ctx->turn_servers_cfg[i].password);
151 }
152 free(ctx->turn_servers_cfg);
153 ctx->turn_servers_cfg=NULL__null;
154 ctx->turn_server_ct_cfg=0;
155 }
156
157 if(ct) {
158 if(!(ctx->turn_servers_cfg=R_NEW_CNT(nr_ice_turn_server, ct)(nr_ice_turn_server*)calloc(ct,sizeof(nr_ice_turn_server))))
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
170static int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
171 {
172 int _status,i,r;
173
174 if(ctx->local_addrs) {
175 free(ctx->local_addrs);
176 ctx->local_addr_ct=0;
177 ctx->local_addrs=0;
178 }
179
180 if (ct) {
181 if(!(ctx->local_addrs=R_NEW_CNT(nr_local_addr, ct)(nr_local_addr*)calloc(ct,sizeof(nr_local_addr))))
182 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
183
184 for (i=0;i<ct;++i) {
185 if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
186 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
187 }
188 }
189 ctx->local_addr_ct = ct;
190 }
191
192 _status=0;
193 abort:
194 return(_status);
195 }
196
197int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
198 {
199 int _status;
200
201 if (ctx->resolver) {
202 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
203 }
204
205 ctx->resolver = resolver;
206
207 _status=0;
208 abort:
209 return(_status);
210 }
211
212int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
213 {
214 int _status;
215
216 if (ctx->interface_prioritizer) {
217 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
218 }
219
220 ctx->interface_prioritizer = ip;
221
222 _status=0;
223 abort:
224 return(_status);
225 }
226
227void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory)
228 {
229 nr_socket_factory_destroy(&ctx->socket_factory);
230 ctx->socket_factory = factory;
231 }
232
233#ifdef USE_TURN1
234int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
235 {
236 int r,_status;
237 nr_ice_turn_server *servers = 0;
238 int i;
239 NR_registry child;
240 char *addr=0;
241 UINT2 port;
242 in_addr_t addr_int;
243 Data data={0};
244
245 if(!(servers=R_NEW_CNT(nr_ice_turn_server, ct)(nr_ice_turn_server*)calloc(ct,sizeof(nr_ice_turn_server))))
246 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
247
248 for(i=0;i<ct;i++){
249 if(r=NR_reg_get_child_registry(NR_ICE_REG_TURN_SRV_PRFX"ice.turn.server",i,child))
250 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
251 /* Assume we have a v4 addr for now */
252 if(r=NR_reg_alloc2_string(child,"addr",&addr))
253 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
254 addr_int=inet_addr(addr);
255 if(addr_int==INADDR_NONE((in_addr_t) 0xffffffff)){
256 r_log(LOG_ICE,LOG_ERR3,"Invalid address %s",addr);
257 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
258 }
259 if(r=NR_reg_get2_uint2(child,"port",&port)) {
260 if (r != R_NOT_FOUND2)
261 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
262 port = 3478;
263 }
264 if (r = nr_ip4_port_to_transport_addr(ntohl(addr_int)__bswap_32 (addr_int), port, IPPROTO_UDPIPPROTO_UDP,
265 &servers[i].turn_server.addr))
266 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
267
268
269 if(r=NR_reg_alloc2_string(child,NR_ICE_REG_TURN_SRV_USERNAME"username",&servers[i].username)){
270 if(r!=R_NOT_FOUND2)
271 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
272 }
273
274 if(r=NR_reg_alloc2_data(child,NR_ICE_REG_TURN_SRV_PASSWORD"password",&data)){
275 if(r!=R_NOT_FOUND2)
276 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
277 }
278 else {
279 servers[i].password=R_NEW(Data)(Data*)calloc(1,sizeof(Data));
280 if(!servers[i].password)
281 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
282 servers[i].password->data = data.data;
283 servers[i].password->len = data.len;
284 data.data=0;
285 }
286
287 free(addr);
288 addr=0;
289 }
290
291 *out = servers;
292
293 _status=0;
294 abort:
295 free(data.data);
296 free(addr);
297 if (_status) free(servers);
298 return(_status);
299 }
300#endif /* USE_TURN */
301
302#define MAXADDRS100 100 /* Ridiculously high */
303 int nr_ice_ctx_create(char* label, UINT4 flags,
304 nr_ice_gather_handler* gather_handler,
305 nr_ice_ctx** ctxp) {
306 nr_ice_ctx *ctx=0;
307 int r,_status;
308
309 if(r=r_log_register("ice", &LOG_ICE))
310 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
311
312 if(!(ctx=R_NEW(nr_ice_ctx)(nr_ice_ctx*)calloc(1,sizeof(nr_ice_ctx))))
313 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
314
315 ctx->flags=flags;
316
317 if(!(ctx->label=strdup(label)))
318 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
319
320 ctx->gather_handler = gather_handler;
321
322 /* Get the STUN servers */
323 if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX"ice.stun.server",
324 (unsigned int *)&ctx->stun_server_ct_cfg)||ctx->stun_server_ct_cfg==0) {
325 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): No STUN servers specified in nICEr registry", ctx->label);
326 ctx->stun_server_ct_cfg=0;
327 }
328
329 /* 31 is the max for our priority algorithm */
330 if(ctx->stun_server_ct_cfg>31){
331 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Too many STUN servers specified: max=31", ctx->label);
332 ctx->stun_server_ct_cfg=31;
333 }
334
335 if(ctx->stun_server_ct_cfg>0){
336 if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct_cfg,&ctx->stun_servers_cfg)){
337 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Couldn't load STUN servers from registry", ctx->label);
338 ctx->stun_server_ct_cfg=0;
339 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
340 }
341 }
342
343#ifdef USE_TURN1
344 /* Get the TURN servers */
345 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'
346 (unsigned int *)&ctx->turn_server_ct_cfg)||ctx->turn_server_ct_cfg==0) {
347 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): No TURN servers specified in nICEr registry", ctx->label);
348 ctx->turn_server_ct_cfg=0;
349 }
350#else
351 ctx->turn_server_ct_cfg=0;
352#endif /* USE_TURN */
353
354 ctx->local_addrs=0;
355 ctx->local_addr_ct=0;
356
357 /* 31 is the max for our priority algorithm */
358 if((ctx->stun_server_ct_cfg+ctx->turn_server_ct_cfg)>31){
359 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): Too many STUN/TURN servers specified: max=31", ctx->label);
360 ctx->turn_server_ct_cfg=31-ctx->stun_server_ct_cfg;
361 }
362
363#ifdef USE_TURN1
364 if(ctx->turn_server_ct_cfg>0){
365 if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct_cfg,&ctx->turn_servers_cfg)){
366 ctx->turn_server_ct_cfg=0;
367 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Couldn't load TURN servers from registry", ctx->label);
368 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
369 }
370 }
371#endif /* USE_TURN */
372
373
374 ctx->Ta = 20;
375
376 ctx->test_timer_divider = 0;
377
378 if (r=nr_socket_factory_create_int(NULL__null, &default_socket_factory_vtbl, &ctx->socket_factory))
379 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
380
381 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)))) {
382 if (r == R_NOT_FOUND2) {
383 ctx->force_net_interface[0] = 0;
384 } else {
385 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
386 }
387 }
388
389 ctx->target_for_default_local_address_lookup=0;
390
391 STAILQ_INIT(&ctx->streams)do { (((&ctx->streams))->stqh_first) = __null; (&
ctx->streams)->stqh_last = &(((&ctx->streams
))->stqh_first); } while (0)
;
392 STAILQ_INIT(&ctx->sockets)do { (((&ctx->sockets))->stqh_first) = __null; (&
ctx->sockets)->stqh_last = &(((&ctx->sockets
))->stqh_first); } while (0)
;
393 STAILQ_INIT(&ctx->foundations)do { (((&ctx->foundations))->stqh_first) = __null; (
&ctx->foundations)->stqh_last = &(((&ctx->
foundations))->stqh_first); } while (0)
;
394 STAILQ_INIT(&ctx->peers)do { (((&ctx->peers))->stqh_first) = __null; (&
ctx->peers)->stqh_last = &(((&ctx->peers))->
stqh_first); } while (0)
;
395 STAILQ_INIT(&ctx->ids)do { (((&ctx->ids))->stqh_first) = __null; (&ctx
->ids)->stqh_last = &(((&ctx->ids))->stqh_first
); } while (0)
;
396
397 *ctxp=ctx;
398
399 _status=0;
400 abort:
401 if (_status && ctx) nr_ice_ctx_destroy(&ctx);
402
403 return(_status);
404 }
405
406 void nr_ice_ctx_add_flags(nr_ice_ctx* ctx, UINT4 flags) {
407 ctx->flags |= flags;
408 }
409
410 void nr_ice_ctx_remove_flags(nr_ice_ctx* ctx, UINT4 flags) {
411 ctx->flags &= ~flags;
412 }
413
414 void nr_ice_ctx_destroy(nr_ice_ctx** ctxp) {
415 if (!ctxp || !*ctxp) return;
416
417 nr_ice_ctx* ctx = *ctxp;
418 nr_ice_foundation *f1,*f2;
419 nr_ice_media_stream *s1,*s2;
420 int i;
421 nr_ice_stun_id *id1,*id2;
422
423 ctx->gather_done_cb = 0;
424 ctx->trickle_cb = 0;
425
426 STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2)for ((s1) = (((&ctx->streams))->stqh_first); (s1) &&
((s2) = (((s1))->entry.stqe_next), 1); (s1) = (s2))
{
427 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)
;
428 nr_ice_media_stream_destroy(&s1);
429 }
430
431 free(ctx->label);
432
433 ctx->gather_handler = 0;
434
435 free(ctx->stun_servers_cfg);
436
437 free(ctx->local_addrs);
438
439 free(ctx->target_for_default_local_address_lookup);
440
441 for (i = 0; i < ctx->turn_server_ct_cfg; i++) {
442 free(ctx->turn_servers_cfg[i].username);
443 r_data_destroy(&ctx->turn_servers_cfg[i].password);
444 }
445 free(ctx->turn_servers_cfg);
446
447 f1=STAILQ_FIRST(&ctx->foundations)((&ctx->foundations)->stqh_first);
448 while(f1){
449 f2=STAILQ_NEXT(f1,entry)((f1)->entry.stqe_next);
450 free(f1);
451 f1=f2;
452 }
453
454 STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2)for ((id1) = (((&ctx->ids))->stqh_first); (id1) &&
((id2) = (((id1))->entry.stqe_next), 1); (id1) = (id2))
{
455 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)
;
456 free(id1);
457 }
458
459 nr_resolver_destroy(&ctx->resolver);
460 nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
461 nr_socket_factory_destroy(&ctx->socket_factory);
462
463 free(ctx);
464
465 *ctxp=0;
466 }
467
468void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
469 {
470 int r;
471 nr_ice_candidate *cand=(nr_ice_candidate*)cb_arg;
472 nr_ice_ctx *ctx;
473 nr_ice_media_stream *stream;
474 int component_id;
475
476 assert(cb_arg)(static_cast <bool> (cb_arg) ? void (0) : __assert_fail
("cb_arg", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
477 if (!cb_arg)
478 return;
479 ctx = cand->ctx;
480 stream = cand->stream;
481 component_id = cand->component_id;
482
483 ctx->uninitialized_candidates--;
484 if (cand->state == NR_ICE_CAND_STATE_FAILED4) {
485 r_log(LOG_ICE, LOG_WARNING4,
486 "ICE(%s)/CAND(%s): failed to initialize, %d remaining", ctx->label,
487 cand->label, ctx->uninitialized_candidates);
488 } else {
489 r_log(LOG_ICE, LOG_DEBUG7, "ICE(%s)/CAND(%s): initialized, %d remaining",
490 ctx->label, cand->label, ctx->uninitialized_candidates);
491 }
492
493 /* Avoid the need for yet another initialization function */
494 if (cand->state == NR_ICE_CAND_STATE_INITIALIZING2 && cand->type == HOST)
495 cand->state = NR_ICE_CAND_STATE_INITIALIZED3;
496
497 if (cand->state == NR_ICE_CAND_STATE_INITIALIZED3) {
498 int was_pruned = 0;
499
500 if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
501 cand, &was_pruned)) {
502 r_log(LOG_ICE, LOG_NOTICE5, "ICE(%s): Problem pruning candidates",ctx->label);
503 }
504
505 if (was_pruned) {
506 cand = NULL__null;
507 }
508
509 /* If we are initialized, the candidate wasn't pruned,
510 and we have a trickle ICE callback fire the callback */
511 if (ctx->trickle_cb && cand &&
512 !nr_ice_ctx_hide_candidate(ctx, cand)) {
513 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
514
515 if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
516 r_log(LOG_ICE,LOG_ERR3, "ICE(%s): All could not pair new trickle candidate",ctx->label);
517 /* But continue */
518 }
519 }
520 }
521
522 if (nr_ice_media_stream_is_done_gathering(stream)) {
523 if (ctx->gather_handler && ctx->gather_handler->vtbl->stream_gathered) {
524 ctx->gather_handler->vtbl->stream_gathered(ctx->gather_handler->obj,
525 stream);
526 }
527 if (ctx->trickle_cb) {
528 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, stream, component_id, NULL__null);
529 }
530 }
531
532 if(ctx->uninitialized_candidates==0){
533 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__
))
;
534 r_log(LOG_ICE, LOG_INFO6, "ICE(%s): All candidates initialized",
535 ctx->label);
536 if (ctx->gather_done_cb) {
537 ctx->gather_done_cb(0, 0, ctx->cb_arg);
538 } else {
539 r_log(LOG_ICE, LOG_INFO6,
540 "ICE(%s): No gather_done_cb. We were probably destroyed.",
541 ctx->label);
542 }
543 }
544 else {
545 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): Waiting for %d candidates to be initialized",ctx->label, ctx->uninitialized_candidates);
546 }
547 }
548
549static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
550 {
551 int r,_status;
552 nr_ice_peer_ctx *pctx;
553
554 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
555 while(pctx){
556 if (pctx->state == NR_ICE_PEER_STATE_PAIRED2) {
557 r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
558 if (r)
559 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
560 }
561
562 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
563 }
564
565 _status=0;
566 abort:
567 return(_status);
568 }
569
570/* Get the default address by creating a UDP socket, binding it to a wildcard
571 address, and connecting it to the remote IP. Because this is UDP, no packets
572 are sent. This lets us query the local address assigned to the socket by the
573 kernel.
574
575 If the context's remote address is NULL, then the application wasn't loaded
576 over the network, and we can fall back on connecting to a known public
577 address (namely Google's):
578
579 IPv4: 8.8.8.8
580 IPv6: 2001:4860:4860::8888
581*/
582static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transport_addr* addrp)
583 {
584 int r,_status;
585 nr_transport_addr addr, known_remote_addr;
586 nr_transport_addr *remote_addr=ctx->target_for_default_local_address_lookup;
587 nr_socket *sock=0;
588
589 switch(ip_version) {
590 case NR_IPV44:
591 if ((r=nr_str_port_to_transport_addr("0.0.0.0", 0, IPPROTO_UDPIPPROTO_UDP, &addr)))
592 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
593 if (!remote_addr || nr_transport_addr_is_loopback(remote_addr)) {
594 if ((r=nr_str_port_to_transport_addr("8.8.8.8", 53, IPPROTO_UDPIPPROTO_UDP, &known_remote_addr)))
595 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
596 remote_addr=&known_remote_addr;
597 }
598 break;
599 case NR_IPV66:
600 if ((r=nr_str_port_to_transport_addr("::0", 0, IPPROTO_UDPIPPROTO_UDP, &addr)))
601 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
602 if (!remote_addr || nr_transport_addr_is_loopback(remote_addr)) {
603 if ((r=nr_str_port_to_transport_addr("2001:4860:4860::8888", 53, IPPROTO_UDPIPPROTO_UDP, &known_remote_addr)))
604 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
605 remote_addr=&known_remote_addr;
606 }
607 break;
608 default:
609 assert(0)(static_cast <bool> (0) ? void (0) : __assert_fail ("0"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
610 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
611 }
612
613 if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
614 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
615 if ((r=nr_socket_connect(sock, remote_addr)))
616 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
617 if ((r=nr_socket_getaddr(sock, addrp)))
618 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
619
620 r_log(LOG_GENERIC0, LOG_DEBUG7, "Default address: %s", addrp->as_string);
621
622 _status=0;
623 abort:
624 nr_socket_destroy(&sock);
625 return(_status);
626 }
627
628static 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)
629 {
630 int r,_status;
631 nr_transport_addr default_addr;
632 int i;
633
634 if ((r=nr_ice_get_default_address(ctx, ip_version, &default_addr)))
635 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
636
637 for (i=0; i < addr_ct; ++i) {
638 // if default addr is found in local addrs, copy the more fully
639 // complete local addr to the output arg. Don't need to worry
640 // about comparing ports here.
641 if (!nr_transport_addr_cmp(&default_addr, &addrs[i].addr,
642 NR_TRANSPORT_ADDR_CMP_MODE_ADDR3)) {
643 if ((r=nr_local_addr_copy(addrp, &addrs[i])))
644 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
645 break;
646 }
647 }
648
649 // if default addr is not in local addrs, just copy the transport addr
650 // to output arg.
651 if (i == addr_ct) {
652 if ((r=nr_transport_addr_copy(&addrp->addr, &default_addr)))
653 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
654 (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")))
;
655 }
656
657 _status=0;
658 abort:
659 return(_status);
660 }
661
662/* if handed a IPv4 default_local_addr, looks for IPv6 address on same interface
663 if handed a IPv6 default_local_addr, looks for IPv4 address on same interface
664*/
665static int nr_ice_get_assoc_interface_address(nr_local_addr* default_local_addr,
666 nr_local_addr* local_addrs, int addr_ct,
667 nr_local_addr* assoc_addrp)
668 {
669 int r, _status;
670 int i, ip_version;
671
672 if (!default_local_addr || !local_addrs || !addr_ct) {
673 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
674 }
675
676 /* set _status to R_EOD in case we don't find an associated address */
677 _status = R_EOD5;
678
679 /* look for IPv6 if we have IPv4, look for IPv4 if we have IPv6 */
680 ip_version = (NR_IPV44 == default_local_addr->addr.ip_version?NR_IPV66:NR_IPV44);
681
682 for (i=0; i<addr_ct; ++i) {
683 /* if we find the ip_version we're looking for on the matching interface,
684 copy it to assoc_addrp.
685 */
686 if (local_addrs[i].addr.ip_version == ip_version &&
687 !strcmp(local_addrs[i].addr.ifname, default_local_addr->addr.ifname)) {
688 if (r=nr_local_addr_copy(assoc_addrp, &local_addrs[i])) {
689 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
690 }
691 _status = 0;
692 break;
693 }
694 }
695
696 abort:
697 return(_status);
698 }
699
700int nr_ice_set_local_addresses(nr_ice_ctx *ctx,
701 nr_local_addr* stun_addrs, int stun_addr_ct)
702 {
703 int r,_status;
704 nr_local_addr local_addrs[MAXADDRS100];
705 nr_local_addr *addrs = 0;
706 int i,addr_ct;
707 nr_local_addr default_addrs[2];
708 int default_addr_ct = 0;
709
710 if (!stun_addrs || !stun_addr_ct) {
711 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): no stun addrs provided",ctx->label);
712 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
713 }
714
715 addr_ct = MIN(stun_addr_ct, MAXADDRS)(((stun_addr_ct)<(100))?(stun_addr_ct):(100));
716 r_log(LOG_ICE, LOG_DEBUG7, "ICE(%s): copy %d pre-fetched stun addrs", ctx->label, addr_ct);
717 for (i=0; i<addr_ct; ++i) {
718 if (r=nr_local_addr_copy(&local_addrs[i], &stun_addrs[i])) {
719 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
720 }
721 }
722
723 // removes duplicates and, based on prefs, loopback and link_local addrs
724 if (r = nr_stun_filter_addrs(
725 local_addrs, !(ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LOOPBACK(1 << 7)),
726 !(ctx->flags & NR_ICE_CTX_FLAGS_ALLOW_LINK_LOCAL(1 << 8)), &addr_ct)) {
727 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
728 }
729
730 if (ctx->force_net_interface[0] && addr_ct) {
731 /* Limit us to only addresses on a single interface */
732 int force_addr_ct = 0;
733 for(i=0;i<addr_ct;i++){
734 if (!strcmp(local_addrs[i].addr.ifname, ctx->force_net_interface)) {
735 // copy it down in the array, if needed
736 if (i != force_addr_ct) {
737 if (r=nr_local_addr_copy(&local_addrs[force_addr_ct], &local_addrs[i])) {
738 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
739 }
740 }
741 force_addr_ct++;
742 }
743 }
744 addr_ct = force_addr_ct;
745 }
746
747 r_log(LOG_ICE, LOG_DEBUG7,
748 "ICE(%s): use only default local addresses: %s\n",
749 ctx->label,
750 (char*)(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS(1<<4)?"yes":"no"));
751 if ((!addr_ct) || (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS(1<<4))) {
752 if (ctx->target_for_default_local_address_lookup) {
753 /* Get just the default IPv4 or IPv6 addr */
754 if(!nr_ice_get_default_local_address(
755 ctx, ctx->target_for_default_local_address_lookup->ip_version,
756 local_addrs, addr_ct, &default_addrs[default_addr_ct])) {
757 nr_local_addr *new_addr = &default_addrs[default_addr_ct];
758
759 ++default_addr_ct;
760
761 /* If we have a default target address, check for an associated
762 address on the same interface. For example, if the default
763 target address is IPv6, this will find an associated IPv4
764 address on the same interface.
765 This makes ICE w/ dual stacks work better - Bug 1609124.
766 */
767 if(!nr_ice_get_assoc_interface_address(
768 new_addr, local_addrs, addr_ct,
769 &default_addrs[default_addr_ct])) {
770 ++default_addr_ct;
771 }
772 }
773 } else {
774 /* Get just the default IPv4 and IPv6 addrs */
775 if(!nr_ice_get_default_local_address(ctx, NR_IPV44, local_addrs, addr_ct,
776 &default_addrs[default_addr_ct])) {
777 ++default_addr_ct;
778 }
779 if(!nr_ice_get_default_local_address(ctx, NR_IPV66, local_addrs, addr_ct,
780 &default_addrs[default_addr_ct])) {
781 ++default_addr_ct;
782 }
783 }
784 if (!default_addr_ct) {
785 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): failed to find default addresses",ctx->label);
786 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; _status=_r; goto abort;} while
(0)
;
787 }
788 addrs = default_addrs;
789 addr_ct = default_addr_ct;
790 }
791 else {
792 addrs = local_addrs;
793 }
794
795 /* Sort interfaces by preference */
796 if(ctx->interface_prioritizer) {
797 for(i=0;i<addr_ct;i++){
798 if((r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) && (r!=R_ALREADY4)) {
799 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): unable to add interface ",ctx->label);
800 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
801 }
802 }
803 if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
804 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): unable to sort interface by preference",ctx->label);
805 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
806 }
807 }
808
809 if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
810 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
811 }
812
813 _status=0;
814 abort:
815 return(_status);
816 }
817
818int nr_ice_set_target_for_default_local_address_lookup(nr_ice_ctx *ctx, const char *target_ip, UINT2 target_port)
819 {
820 int r,_status;
821
822 if (ctx->target_for_default_local_address_lookup) {
823 free(ctx->target_for_default_local_address_lookup);
824 ctx->target_for_default_local_address_lookup=0;
825 }
826
827 if (!(ctx->target_for_default_local_address_lookup=R_NEW(nr_transport_addr)(nr_transport_addr*)calloc(1,sizeof(nr_transport_addr))))
828 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
829
830 if ((r=nr_str_port_to_transport_addr(target_ip, target_port, IPPROTO_UDPIPPROTO_UDP, ctx->target_for_default_local_address_lookup))) {
831 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
832 }
833
834 /* Default local address lookup uses a UDP connect() to the target. An
835 * FQDN target would need DNS resolution that this code does not do. */
836 if (ctx->target_for_default_local_address_lookup->fqdn[0] != '\0') {
837 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
838 }
839
840 _status=0;
841 abort:
842 if (_status) {
843 free(ctx->target_for_default_local_address_lookup);
844 ctx->target_for_default_local_address_lookup=0;
845 }
846 return(_status);
847 }
848
849 int nr_ice_gather(nr_ice_ctx* ctx, NR_async_cb gather_done_cb, void* cb_arg) {
850 int r,_status;
851 nr_ice_media_stream *stream;
852 nr_local_addr stun_addrs[MAXADDRS100];
853 int stun_addr_ct;
854
855 if (!ctx->local_addrs) {
856 if((r=nr_stun_get_addrs(stun_addrs,MAXADDRS100,&stun_addr_ct))) {
857 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
858 }
859 if((r=nr_ice_set_local_addresses(ctx,stun_addrs,stun_addr_ct))) {
860 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
861 }
862 }
863
864 if(STAILQ_EMPTY(&ctx->streams)((&ctx->streams)->stqh_first == __null)) {
865 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): Missing streams to initialize",ctx->label);
866 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
867 }
868
869 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): Initializing candidates",ctx->label);
870 ctx->gather_done_cb = gather_done_cb;
871 ctx->cb_arg=cb_arg;
872
873 /* Initialize all the media stream/component pairs */
874 stream=STAILQ_FIRST(&ctx->streams)((&ctx->streams)->stqh_first);
875 while(stream){
876 if(!stream->obsolete) {
877 if(r=nr_ice_media_stream_initialize(ctx,stream)) {
878 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);
879 }
880 }
881
882 stream=STAILQ_NEXT(stream,entry)((stream)->entry.stqe_next);
883 }
884
885 if(ctx->uninitialized_candidates)
886 ABORT(R_WOULDBLOCK)do { int _r=8; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
887
888 _status=0;
889 abort:
890 return(_status);
891 }
892
893int 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)
894 {
895 int r,_status;
896
897 if(r=nr_ice_media_stream_create(ctx,label,ufrag,pwd,components,streamp))
898 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
899
900 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)
;
901
902 _status=0;
903 abort:
904 return(_status);
905 }
906
907int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp)
908 {
909 int r,_status;
910 nr_ice_peer_ctx *pctx;
911 nr_ice_media_stream *peer_stream;
912
913 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
914 while(pctx){
915 if(!nr_ice_peer_ctx_find_pstream(pctx, *streamp, &peer_stream)) {
916 if(r=nr_ice_peer_ctx_remove_pstream(pctx, &peer_stream)) {
917 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
918 }
919 }
920
921 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
922 }
923
924 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)
;
925 if(r=nr_ice_media_stream_destroy(streamp)) {
926 ABORT(r)do { int _r=r; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
927 }
928
929 _status=0;
930 abort:
931 return(_status);
932 }
933
934int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp)
935 {
936 *attrctp=0;
937 *attrsp=0;
938 return(0);
939 }
940
941/* This is incredibly annoying: we now have a datagram but we don't
942 know which peer it's from, and we need to be able to tell the
943 API user. So, offer it to each peer and if one bites, assume
944 the others don't want it
945*/
946int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
947 {
948 nr_ice_peer_ctx *pctx;
949 int r;
950
951 pctx=STAILQ_FIRST(&ctx->peers)((&ctx->peers)->stqh_first);
952 while(pctx){
953 r=nr_ice_peer_ctx_deliver_packet_maybe(pctx, comp, source_addr, data, len);
954 if(!r)
955 break;
956
957 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
958 }
959
960 if(!pctx)
961 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);
962
963 return(0);
964 }
965
966int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
967 {
968 nr_ice_stun_id *xid;
969
970 xid=STAILQ_FIRST(&ctx->ids)((&ctx->ids)->stqh_first);
971 while(xid){
972 if (!memcmp(xid->id, id, 12))
973 return 1;
974
975 xid=STAILQ_NEXT(xid,entry)((xid)->entry.stqe_next);
976 }
977
978 return 0;
979 }
980
981int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg)
982{
983 int _status;
984 nr_ice_stun_id *xid;
985
986 xid = R_NEW(nr_ice_stun_id)(nr_ice_stun_id*)calloc(1,sizeof(nr_ice_stun_id));
987 if (!xid)
988 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; _status=_r; goto abort;} while(
0)
;
989
990 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__
))
;
991#if __STDC_VERSION__ >= 201112L
992 _Static_assert(sizeof(xid->id) == sizeof(msg->header.id),"Message ID Size Mismatch");
993#endif
994 memcpy(xid->id, &msg->header.id, sizeof(xid->id));
995
996 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)
;
997
998 _status=0;
999 abort:
1000 return(_status);
1001}
1002
1003
1004int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
1005{
1006 ctx->trickle_cb = cb;
1007 ctx->trickle_cb_arg = cb_arg;
1008
1009 return 0;
1010}
1011
1012int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
1013 {
1014 if (cand->state != NR_ICE_CAND_STATE_INITIALIZED3) {
1015 return 1;
1016 }
1017
1018 if (ctx->flags & NR_ICE_CTX_FLAGS_DISABLE_HOST_CANDIDATES(1<<3)) {
1019 if (cand->type == HOST)
1020 return 1;
1021 }
1022
1023 if (cand->stream->obsolete) {
1024 return 1;
1025 }
1026
1027 return 0;
1028 }
1029