Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c
Warning:line 587, column 13
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 <string.h>
34#include <assert.h>
35#include <nr_api.h>
36#include <registry.h>
37#include <async_timer.h>
38#include "ice_ctx.h"
39#include "ice_codeword.h"
40#include "stun.h"
41#include "nr_socket_local.h"
42#include "nr_socket_turn.h"
43#include "nr_socket_wrapper.h"
44#include "nr_socket_buffered_stun.h"
45#include "nr_socket_multi_tcp.h"
46#include "ice_reg.h"
47#include "nr_crypto.h"
48#include "r_time.h"
49
50static void nr_ice_component_refresh_consent_cb(NR_SOCKET s, int how, void *cb_arg);
51static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error);
52static int nr_ice_pre_answer_request_destroy(nr_ice_pre_answer_request **parp);
53int nr_ice_component_can_candidate_addr_pair(nr_transport_addr *local, nr_transport_addr *remote);
54int nr_ice_component_can_candidate_tcptype_pair(nr_socket_tcp_type left, nr_socket_tcp_type right);
55void nr_ice_component_consent_calc_consent_timer(nr_ice_component *comp);
56void nr_ice_component_consent_schedule_consent_timer(nr_ice_component *comp);
57int nr_ice_component_refresh_consent(nr_stun_client_ctx *ctx, NR_async_cb finished_cb, void *cb_arg);
58int nr_ice_component_setup_consent(nr_ice_component *comp);
59int nr_ice_pre_answer_enqueue(nr_ice_component *comp, nr_socket *sock, nr_stun_server_request *req, int *dont_free);
60
61/* This function takes ownership of the contents of req (but not req itself) */
62static int nr_ice_pre_answer_request_create(nr_transport_addr *dst, nr_stun_server_request *req, nr_ice_pre_answer_request **parp)
63 {
64 int r, _status;
65 nr_ice_pre_answer_request *par = 0;
66 nr_stun_message_attribute *attr;
67
68 if (!(par = RCALLOC(sizeof(nr_ice_pre_answer_request))r_calloc(0,1,sizeof(nr_ice_pre_answer_request))))
69 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
70
71 par->req = *req; /* Struct assignment */
72 memset(req, 0, sizeof(*req)); /* Zero contents to avoid confusion */
73
74 if (r=nr_transport_addr_copy(&par->local_addr, dst))
75 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
76 if (!nr_stun_message_has_attribute(par->req.request, NR_STUN_ATTR_USERNAME0x0006, &attr))
77 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
78 if (!(par->username = r_strdup(attr->u.username)))
79 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
80
81 *parp=par;
82 _status=0;
83 abort:
84 if (_status) {
85 /* Erase the request so we don't free it */
86 memset(&par->req, 0, sizeof(nr_stun_server_request));
87 nr_ice_pre_answer_request_destroy(&par);
88 }
89
90 return(_status);
91 }
92
93static int nr_ice_pre_answer_request_destroy(nr_ice_pre_answer_request **parp)
94 {
95 nr_ice_pre_answer_request *par;
96
97 if (!parp || !*parp)
98 return(0);
99
100 par = *parp;
101 *parp = 0;
102
103 nr_stun_message_destroy(&par->req.request);
104 nr_stun_message_destroy(&par->req.response);
105
106 RFREE(par->username)if(par->username) r_free(par->username);
107 RFREE(par)if(par) r_free(par);
108
109 return(0);
110 }
111
112int nr_ice_component_create(nr_ice_media_stream *stream, int component_id, nr_ice_component **componentp)
113 {
114 int _status;
115 nr_ice_component *comp=0;
116
117 if(!(comp=RCALLOC(sizeof(nr_ice_component))r_calloc(0,1,sizeof(nr_ice_component))))
118 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
119
120 comp->state=NR_ICE_COMPONENT_UNPAIRED0;
121 comp->component_id=component_id;
122 comp->stream=stream;
123 comp->ctx=stream->ctx;
124
125 STAILQ_INIT(&comp->sockets)do { (((&comp->sockets))->stqh_first) = ((void*)0);
(&comp->sockets)->stqh_last = &(((&comp->
sockets))->stqh_first); } while (0)
;
126 TAILQ_INIT(&comp->candidates)do { (((&comp->candidates))->tqh_first) = ((void*)0
); (&comp->candidates)->tqh_last = &(((&comp
->candidates))->tqh_first); ; } while (0)
;
127 STAILQ_INIT(&comp->pre_answer_reqs)do { (((&comp->pre_answer_reqs))->stqh_first) = ((void
*)0); (&comp->pre_answer_reqs)->stqh_last = &((
(&comp->pre_answer_reqs))->stqh_first); } while (0)
;
128
129 STAILQ_INSERT_TAIL(&stream->components,comp,entry)do { (((comp))->entry.stqe_next) = ((void*)0); *(&stream
->components)->stqh_last = (comp); (&stream->components
)->stqh_last = &(((comp))->entry.stqe_next); } while
(0)
;
130
131 _status=0;
132 abort:
133 return(_status);
134 }
135
136int nr_ice_component_destroy(nr_ice_component **componentp)
137 {
138 nr_ice_component *component;
139 nr_ice_socket *s1,*s2;
140 nr_ice_candidate *c1,*c2;
141 nr_ice_pre_answer_request *r1,*r2;
142
143 if(!componentp || !*componentp)
144 return(0);
145
146 component=*componentp;
147 *componentp=0;
148
149 nr_ice_component_consent_destroy(component);
150
151 /* Detach ourselves from the sockets */
152 if (component->local_component){
153 nr_ice_socket *isock=STAILQ_FIRST(&component->local_component->sockets)((&component->local_component->sockets)->stqh_first
)
;
154 while(isock){
155 nr_stun_server_remove_client(isock->stun_server, component);
156 isock=STAILQ_NEXT(isock, entry)((isock)->entry.stqe_next);
157 }
158 }
159
160 /* candidates MUST be destroyed before the sockets so that
161 they can deregister */
162 TAILQ_FOREACH_SAFE(c1, &component->candidates, entry_comp, c2)for ((c1) = (((&component->candidates))->tqh_first)
; (c1) && ((c2) = (((c1))->entry_comp.tqe_next), 1
); (c1) = (c2))
{
163 TAILQ_REMOVE(&component->candidates,c1,entry_comp)do { if (((((c1))->entry_comp.tqe_next)) != ((void*)0)) ((
(c1))->entry_comp.tqe_next)->entry_comp.tqe_prev = (c1)
->entry_comp.tqe_prev; else { (&component->candidates
)->tqh_last = (c1)->entry_comp.tqe_prev; ; } *(c1)->
entry_comp.tqe_prev = (((c1))->entry_comp.tqe_next); ; ; ;
} while (0)
;
164 nr_ice_candidate_destroy(&c1);
165 }
166
167 STAILQ_FOREACH_SAFE(s1, &component->sockets, entry, s2)for ((s1) = (((&component->sockets))->stqh_first); (
s1) && ((s2) = (((s1))->entry.stqe_next), 1); (s1)
= (s2))
{
168 STAILQ_REMOVE(&component->sockets,s1,nr_ice_socket_,entry)do { if ((((&component->sockets))->stqh_first) == (
s1)) { do { if ((((((&component->sockets)))->stqh_first
) = ((((((&component->sockets)))->stqh_first))->
entry.stqe_next)) == ((void*)0)) ((&component->sockets
))->stqh_last = &((((&component->sockets)))->
stqh_first); } while (0); } else { struct nr_ice_socket_ *curelm
= (((&component->sockets))->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)) (
&component->sockets)->stqh_last = &(((curelm))->
entry.stqe_next); } } while (0)
;
169 nr_ice_socket_destroy(&s1);
170 }
171
172 STAILQ_FOREACH_SAFE(r1, &component->pre_answer_reqs, entry, r2)for ((r1) = (((&component->pre_answer_reqs))->stqh_first
); (r1) && ((r2) = (((r1))->entry.stqe_next), 1); (
r1) = (r2))
{
173 STAILQ_REMOVE(&component->pre_answer_reqs,r1,nr_ice_pre_answer_request_, entry)do { if ((((&component->pre_answer_reqs))->stqh_first
) == (r1)) { do { if ((((((&component->pre_answer_reqs
)))->stqh_first) = ((((((&component->pre_answer_reqs
)))->stqh_first))->entry.stqe_next)) == ((void*)0)) ((&
component->pre_answer_reqs))->stqh_last = &((((&
component->pre_answer_reqs)))->stqh_first); } while (0)
; } else { struct nr_ice_pre_answer_request_ *curelm = (((&
component->pre_answer_reqs))->stqh_first); while (((curelm
)->entry.stqe_next) != (r1)) curelm = ((curelm)->entry.
stqe_next); if ((((curelm)->entry.stqe_next) = ((((curelm)
->entry.stqe_next))->entry.stqe_next)) == ((void*)0)) (
&component->pre_answer_reqs)->stqh_last = &(((curelm
))->entry.stqe_next); } } while (0)
;
174 nr_ice_pre_answer_request_destroy(&r1);
175 }
176
177 RFREE(component)if(component) r_free(component);
178 return(0);
179 }
180
181static int nr_ice_component_create_stun_server_ctx(nr_ice_component *component, nr_ice_socket *isock, nr_transport_addr *addr, char *lufrag, Data *pwd)
182 {
183 char label[256];
184 int r,_status;
185
186 /* Create a STUN server context for this socket */
187 snprintf(label, sizeof(label), "server(%s)", addr->as_string);
188 if(r=nr_stun_server_ctx_create(label,&isock->stun_server))
189 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
190
191 /* Add the default STUN credentials so that we can respond before
192 we hear about the peer.*/
193 if(r=nr_stun_server_add_default_client(isock->stun_server, lufrag, pwd, nr_ice_component_stun_server_default_cb, component))
194 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
195
196 /* Do this last; if this function fails, we should not be taking a reference to isock */
197 if(r=nr_ice_socket_register_stun_server(isock,isock->stun_server,&isock->stun_server_handle))
198 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
199
200 _status = 0;
201 abort:
202 return(_status);
203 }
204
205static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_local_addr *addrs, int addr_ct, char *lufrag, Data *pwd)
206 {
207 nr_socket *sock;
208 nr_ice_socket *isock=0;
209 nr_ice_candidate *cand=0;
210 int i;
211 int j;
212 int r,_status;
213
214 if(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_PROXY(1<<5)) {
215 /* No UDP support if we must use a proxy */
216 return 0;
217 }
218
219 /* Now one ice_socket for each address */
220 for(i=0;i<addr_ct;i++){
221 char suppress;
222
223 if(r=NR_reg_get2_char(NR_ICE_REG_SUPPRESS_INTERFACE_PRFX"ice.suppress.interface",addrs[i].addr.ifname,&suppress)){
224 if(r!=R_NOT_FOUND2)
225 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
226 }
227 else{
228 if(suppress)
229 continue;
230 }
231 r_log(LOG_ICE,LOG_DEBUG7,"ICE-STREAM(%s): host address %s",component->stream->label,addrs[i].addr.as_string);
232 if((r=nr_socket_factory_create_socket(ctx->socket_factory,&addrs[i].addr,&sock))){
233 r_log(LOG_ICE,LOG_WARNING4,"ICE-STREAM(%s): couldn't create socket for address %s",component->stream->label,addrs[i].addr.as_string);
234 continue;
235 }
236
237 if(r=nr_ice_socket_create(ctx,component,sock,NR_ICE_SOCKET_TYPE_DGRAM1,&isock))
238 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
239
240 /* Create a STUN server context for this socket */
241 if ((r=nr_ice_component_create_stun_server_ctx(component,isock,&addrs[i].addr,lufrag,pwd)))
242 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
243
244 /* Make sure we don't leak this. Failures might result in it being
245 * unused, but we hand off references to this in enough places below
246 * that unwinding it all becomes impractical. */
247 STAILQ_INSERT_TAIL(&component->sockets,isock,entry)do { (((isock))->entry.stqe_next) = ((void*)0); *(&component
->sockets)->stqh_last = (isock); (&component->sockets
)->stqh_last = &(((isock))->entry.stqe_next); } while
(0)
;
248
249 if (!(component->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY(1<<2))) {
250 /* Create one host candidate */
251 if(r=nr_ice_candidate_create(ctx,component,isock,sock,HOST,0,0,
252 component->component_id,&cand))
253 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
254
255 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
256 component->candidate_ct++;
257 cand=0;
258
259 /* And a srvrflx candidate for each STUN server */
260 for(j=0;j<component->stream->stun_server_ct;j++){
261 r_log(LOG_ICE,LOG_DEBUG7,"ICE-STREAM(%s): Checking STUN server %s %s", component->stream->label, component->stream->stun_servers[j].addr.fqdn, component->stream->stun_servers[j].addr.as_string);
262 /* Skip non-UDP */
263 if (component->stream->stun_servers[j].addr.protocol != IPPROTO_UDPIPPROTO_UDP) continue;
264
265 if (nr_transport_addr_check_compatibility(
266 &addrs[i].addr, &component->stream->stun_servers[j].addr)) {
267 r_log(LOG_ICE,LOG_INFO6,"ICE-STREAM(%s): Skipping STUN server because of address type mis-match",component->stream->label);
268 continue;
269 }
270
271 /* Ensure id is set (nr_ice_ctx_set_stun_servers does not) */
272 component->stream->stun_servers[j].id = j;
273 if(r=nr_ice_candidate_create(ctx,component,
274 isock,sock,SERVER_REFLEXIVE,0,
275 &component->stream->stun_servers[j],component->component_id,&cand))
276 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
277 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
278 component->candidate_ct++;
279 cand=0;
280 }
281 }
282 else{
283 r_log(LOG_ICE,LOG_WARNING4,"ICE-STREAM(%s): relay only option results in no host candidate for %s",component->stream->label,addrs[i].addr.as_string);
284 }
285
286#ifdef USE_TURN1
287 if ((component->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY(1<<2)) &&
288 (component->stream->turn_server_ct == 0)) {
289 r_log(LOG_ICE,LOG_ERR3,"ICE-STREAM(%s): relay only option is set without any TURN server configured",component->stream->label);
290 }
291 /* And both a srvrflx and relayed candidate for each TURN server (unless
292 we're in relay-only mode, in which case just the relayed one) */
293 for(j=0;j<component->stream->turn_server_ct;j++){
294 nr_socket *turn_sock;
295 nr_ice_candidate *srvflx_cand=0;
296
297 r_log(LOG_ICE,LOG_DEBUG7,"ICE-STREAM(%s): Checking TURN server %s %s", component->stream->label, component->stream->turn_servers[j].turn_server.addr.fqdn, component->stream->turn_servers[j].turn_server.addr.as_string);
298
299 /* Skip non-UDP */
300 if (component->stream->turn_servers[j].turn_server.addr.protocol != IPPROTO_UDPIPPROTO_UDP)
301 continue;
302
303 if (nr_transport_addr_check_compatibility(
304 &addrs[i].addr, &component->stream->turn_servers[j].turn_server.addr)) {
305 r_log(LOG_ICE,LOG_INFO6,"ICE-STREAM(%s): Skipping TURN server because of address type mis-match",component->stream->label);
306 continue;
307 }
308
309 if (!(component->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY(1<<2))) {
310 /* Ensure id is set with a unique value */
311 component->stream->turn_servers[j].turn_server.id = j + component->stream->stun_server_ct;
312 /* srvrflx */
313 if(r=nr_ice_candidate_create(ctx,component,
314 isock,sock,SERVER_REFLEXIVE,0,
315 &component->stream->turn_servers[j].turn_server,component->component_id,&cand))
316 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
317 cand->state=NR_ICE_CAND_STATE_INITIALIZING2; /* Don't start */
318 cand->done_cb=nr_ice_gather_finished_cb;
319 cand->cb_arg=cand;
320
321 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
322 component->candidate_ct++;
323 srvflx_cand=cand;
324 cand=0;
325 }
326 /* relayed*/
327 if(r=nr_socket_turn_create(&turn_sock))
328 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
329 if(r=nr_ice_candidate_create(ctx,component,
330 isock,turn_sock,RELAYED,0,
331 &component->stream->turn_servers[j].turn_server,component->component_id,&cand))
332 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
333 if (srvflx_cand) {
334 cand->u.relayed.srvflx_candidate=srvflx_cand;
335 srvflx_cand->u.srvrflx.relay_candidate=cand;
336 }
337 cand->u.relayed.server=&component->stream->turn_servers[j];
338 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
339 component->candidate_ct++;
340
341 cand=0;
342 }
343#endif /* USE_TURN */
344 }
345
346 _status = 0;
347 abort:
348 return(_status);
349 }
350
351static int nr_ice_component_get_port_from_ephemeral_range(uint16_t *port)
352 {
353 int _status, r;
354 void *buf = port;
355 if(r=nr_crypto_random_bytes(buf, 2)nr_crypto_vtbl->random_bytes(buf,2))
356 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
357 *port|=49152; /* make it fit into IANA ephemeral port range >= 49152 */
358 _status=0;
359abort:
360 return(_status);
361 }
362
363static int nr_ice_component_create_tcp_host_candidate(struct nr_ice_ctx_ *ctx,
364 nr_ice_component *component, nr_transport_addr *interface_addr, nr_socket_tcp_type tcp_type,
365 int backlog, int so_sock_ct, char *lufrag, Data *pwd, nr_ice_socket **isock)
366 {
367 int r,_status;
368 nr_ice_candidate *cand=0;
369 int tries=3;
370 nr_ice_socket *isock_tmp=0;
371 nr_socket *nrsock=0;
372 nr_transport_addr addr;
373 uint16_t local_port;
374
375 if ((r=nr_transport_addr_copy(&addr,interface_addr)))
376 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
377 addr.protocol=IPPROTO_TCPIPPROTO_TCP;
378
379 do{
380 if (!tries--)
381 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
382
383 if((r=nr_ice_component_get_port_from_ephemeral_range(&local_port)))
384 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
385
386 if ((r=nr_transport_addr_set_port(&addr, local_port)))
387 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
388
389 if((r=nr_transport_addr_fmt_addr_string(&addr)))
390 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
391
392 /* It would be better to stop trying if there is error other than
393 port already used, but it'd require significant work to support this. */
394 r=nr_socket_multi_tcp_create(ctx,component,&addr,tcp_type,so_sock_ct,NR_STUN_MAX_MESSAGE_SIZE2048,&nrsock);
395
396 } while(r);
397
398 if((tcp_type == TCP_TYPE_PASSIVE) && (r=nr_socket_listen(nrsock,backlog)))
399 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
400
401 if((r=nr_ice_socket_create(ctx,component,nrsock,NR_ICE_SOCKET_TYPE_STREAM_TCP3,&isock_tmp)))
402 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
403
404 /* nr_ice_socket took ownership of nrsock */
405 nrsock=NULL((void*)0);
406
407 /* Create a STUN server context for this socket */
408 if ((r=nr_ice_component_create_stun_server_ctx(component,isock_tmp,&addr,lufrag,pwd)))
409 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
410
411 if((r=nr_ice_candidate_create(ctx,component,isock_tmp,isock_tmp->sock,HOST,tcp_type,0,
412 component->component_id,&cand)))
413 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
414
415 if (isock)
416 *isock=isock_tmp;
417
418 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
419 component->candidate_ct++;
420
421 STAILQ_INSERT_TAIL(&component->sockets,isock_tmp,entry)do { (((isock_tmp))->entry.stqe_next) = ((void*)0); *(&
component->sockets)->stqh_last = (isock_tmp); (&component
->sockets)->stqh_last = &(((isock_tmp))->entry.stqe_next
); } while (0)
;
422
423 _status=0;
424abort:
425 if (_status) {
426 nr_ice_socket_destroy(&isock_tmp);
427 nr_socket_destroy(&nrsock);
428 }
429 return(_status);
430 }
431
432static int nr_ice_component_initialize_tcp(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_local_addr *addrs, int addr_ct, char *lufrag, Data *pwd)
433 {
434 nr_ice_candidate *cand=0;
435 int i;
436 int j;
437 int r,_status;
438 int so_sock_ct=0;
439 int backlog=10;
440 char ice_tcp_disabled=1;
441
442 r_log(LOG_ICE,LOG_DEBUG7,"nr_ice_component_initialize_tcp");
443
444 if(r=NR_reg_get_int4(NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT"ice.tcp.so_sock_count",&so_sock_ct)){
445 if(r!=R_NOT_FOUND2)
446 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
447 }
448
449 if(r=NR_reg_get_int4(NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG"ice.tcp.listen_backlog",&backlog)){
450 if(r!=R_NOT_FOUND2)
451 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
452 }
453
454 if ((r=NR_reg_get_char(NR_ICE_REG_ICE_TCP_DISABLE"ice.tcp.disable", &ice_tcp_disabled))) {
455 if (r != R_NOT_FOUND2)
456 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
457 }
458 if ((component->stream->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY(1<<2)) ||
459 (component->stream->flags & NR_ICE_CTX_FLAGS_ONLY_PROXY(1<<5))) {
460 r_log(LOG_ICE,LOG_WARNING4,"ICE-STREAM(%s): relay/proxy only option results in ICE TCP being disabled",component->stream->label);
461 ice_tcp_disabled = 1;
462 }
463
464 for(i=0;i<addr_ct;i++){
465 char suppress;
466 nr_ice_socket *isock_psv=0;
467 nr_ice_socket *isock_so=0;
468
469 if(r=NR_reg_get2_char(NR_ICE_REG_SUPPRESS_INTERFACE_PRFX"ice.suppress.interface",addrs[i].addr.ifname,&suppress)){
470 if(r!=R_NOT_FOUND2)
471 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
472 }
473 else if(suppress) {
474 continue;
475 }
476
477 if (!ice_tcp_disabled) {
478 /* passive host candidate */
479 if ((r=nr_ice_component_create_tcp_host_candidate(ctx, component, &addrs[i].addr,
480 TCP_TYPE_PASSIVE, backlog, 0, lufrag, pwd, &isock_psv))) {
481 r_log(LOG_ICE,LOG_WARNING4,"ICE-STREAM(%s): failed to create passive TCP host candidate: %d",component->stream->label,r);
482 }
483
484 /* active host candidate */
485 if ((r=nr_ice_component_create_tcp_host_candidate(ctx, component, &addrs[i].addr,
486 TCP_TYPE_ACTIVE, 0, 0, lufrag, pwd, NULL((void*)0)))) {
487 r_log(LOG_ICE,LOG_WARNING4,"ICE-STREAM(%s): failed to create active TCP host candidate: %d",component->stream->label,r);
488 }
489
490 /* simultaneous-open host candidate */
491 if (so_sock_ct) {
492 if ((r=nr_ice_component_create_tcp_host_candidate(ctx, component, &addrs[i].addr,
493 TCP_TYPE_SO, 0, so_sock_ct, lufrag, pwd, &isock_so))) {
494 r_log(LOG_ICE,LOG_WARNING4,"ICE-STREAM(%s): failed to create simultanous open TCP host candidate: %d",component->stream->label,r);
495 }
496 }
497
498 /* And srvrflx candidates for each STUN server */
499 for(j=0;j<component->stream->stun_server_ct;j++){
500 if (component->stream->stun_servers[j].addr.protocol != IPPROTO_TCPIPPROTO_TCP) continue;
501
502 if (isock_psv) {
503 if(r=nr_ice_candidate_create(ctx,component,
504 isock_psv,isock_psv->sock,SERVER_REFLEXIVE,TCP_TYPE_PASSIVE,
505 &component->stream->stun_servers[j],component->component_id,&cand))
506 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
507 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
508 component->candidate_ct++;
509 cand=0;
510 }
511
512 if (isock_so) {
513 if(r=nr_ice_candidate_create(ctx,component,
514 isock_so,isock_so->sock,SERVER_REFLEXIVE,TCP_TYPE_SO,
515 &component->stream->stun_servers[j],component->component_id,&cand))
516 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
517 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
518 component->candidate_ct++;
519 cand=0;
520 }
521 }
522 }
523
524#ifdef USE_TURN1
525 /* Create a new relayed candidate for each addr/TURN server pair */
526 for(j=0;j<component->stream->turn_server_ct;j++){
527 nr_transport_addr addr;
528 nr_socket *local_sock;
529 nr_socket *buffered_sock;
530 nr_socket *turn_sock;
531 nr_ice_socket *turn_isock;
532
533 r_log(LOG_ICE,LOG_DEBUG7,"ICE-STREAM(%s): Checking TURN server %s %s", component->stream->label, component->stream->turn_servers[j].turn_server.addr.fqdn, component->stream->turn_servers[j].turn_server.addr.as_string);
534
535 /* Skip non-TCP */
536 if (component->stream->turn_servers[j].turn_server.addr.protocol != IPPROTO_TCPIPPROTO_TCP)
537 continue;
538
539 /* Create relay candidate */
540 if ((r=nr_transport_addr_copy(&addr, &addrs[i].addr)))
541 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
542 addr.protocol = IPPROTO_TCPIPPROTO_TCP;
543
544 if (nr_transport_addr_check_compatibility(
545 &addr, &component->stream->turn_servers[j].turn_server.addr)) {
546 r_log(LOG_ICE,LOG_INFO6,"ICE-STREAM(%s): Skipping TURN server because of address type mis-match",component->stream->label);
547 continue;
548 }
549
550 if (!ice_tcp_disabled) {
551 /* Use TURN server to get srflx candidates */
552 if (isock_psv) {
553 if(r=nr_ice_candidate_create(ctx,component,
554 isock_psv,isock_psv->sock,SERVER_REFLEXIVE,TCP_TYPE_PASSIVE,
555 &component->stream->turn_servers[j].turn_server,component->component_id,&cand))
556 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
557 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
558 component->candidate_ct++;
559 cand=0;
560 }
561
562 if (isock_so) {
563 if(r=nr_ice_candidate_create(ctx,component,
564 isock_so,isock_so->sock,SERVER_REFLEXIVE,TCP_TYPE_SO,
565 &component->stream->turn_servers[j].turn_server,component->component_id,&cand))
566 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
567 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
568 component->candidate_ct++;
569 cand=0;
570 }
571 }
572
573 if (component->stream->turn_servers[j].turn_server.addr.fqdn[0] != 0) {
574 /* If we're going to use TLS, make sure that's recorded */
575 addr.tls = component->stream->turn_servers[j].turn_server.addr.tls;
576 }
577
578 if ((r=nr_transport_addr_fmt_addr_string(&addr)))
579 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
580
581 r_log(LOG_ICE, LOG_DEBUG7,
582 "ICE-STREAM(%s): Creating socket for address %s (turn server %s)",
583 component->stream->label, addr.as_string,
584 component->stream->turn_servers[j].turn_server.addr.as_string);
585
586 /* Create a local socket */
587 if((r=nr_socket_factory_create_socket(ctx->socket_factory,&addr,&local_sock))){
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
588 r_log(LOG_ICE,LOG_DEBUG7,"ICE-STREAM(%s): couldn't create socket for address %s",component->stream->label,addr.as_string);
589 continue;
590 }
591
592 r_log(LOG_ICE,LOG_DEBUG7,"nr_ice_component_initialize_tcp creating TURN TCP wrappers");
593
594 /* The TCP buffered socket */
595 if((r=nr_socket_buffered_stun_create(local_sock, NR_STUN_MAX_MESSAGE_SIZE2048, TURN_TCP_FRAMING, &buffered_sock)))
596 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
597
598 /* The TURN socket */
599 if(r=nr_socket_turn_create(&turn_sock))
600 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
601
602 /* Create an ICE socket */
603 if((r=nr_ice_socket_create(ctx, component, buffered_sock, NR_ICE_SOCKET_TYPE_STREAM_TURN2, &turn_isock)))
604 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
605
606
607 /* Create a STUN server context for this socket */
608 if ((r=nr_ice_component_create_stun_server_ctx(component,turn_isock,&addr,lufrag,pwd)))
609 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
610
611 /* Make sure we don't leak this. Failures might result in it being
612 * unused, but we hand off references to this in enough places below
613 * that unwinding it all becomes impractical. */
614 STAILQ_INSERT_TAIL(&component->sockets,turn_isock,entry)do { (((turn_isock))->entry.stqe_next) = ((void*)0); *(&
component->sockets)->stqh_last = (turn_isock); (&component
->sockets)->stqh_last = &(((turn_isock))->entry.
stqe_next); } while (0)
;
615
616 /* Attach ourselves to it */
617 if(r=nr_ice_candidate_create(ctx,component,
618 turn_isock,turn_sock,RELAYED,TCP_TYPE_NONE,
619 &component->stream->turn_servers[j].turn_server,component->component_id,&cand))
620 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
621 cand->u.relayed.srvflx_candidate=NULL((void*)0);
622 cand->u.relayed.server=&component->stream->turn_servers[j];
623 TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&component->candidates)->tqh_last
; *(&component->candidates)->tqh_last = (cand); (&
component->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
624 component->candidate_ct++;
625 cand=0;
626 }
627#endif /* USE_TURN */
628 }
629
630 _status = 0;
631 abort:
632 return(_status);
633 }
634
635
636/* Make all the candidates we can make at the beginning */
637int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component)
638 {
639 int r,_status;
640 nr_local_addr *addrs=ctx->local_addrs;
641 int addr_ct=ctx->local_addr_ct;
642 char *lufrag;
643 char *lpwd;
644 Data pwd;
645 nr_ice_candidate *cand;
646
647 if (component->candidate_ct) {
648 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): component with id %d already has candidates, probably restarting gathering because of a new stream",ctx->label,component->component_id);
649 return(0);
650 }
651
652 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): initializing component with id %d",ctx->label,component->component_id);
653
654 if(addr_ct==0){
655 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): no local addresses available",ctx->label);
656 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
657 }
658
659 /* Note: we need to recompute these because
660 we have not yet computed the values in the peer media stream.*/
661 lufrag=component->stream->ufrag;
662 assert(lufrag)((void) sizeof ((lufrag) ? 1 : 0), __extension__ ({ if (lufrag
) ; else __assert_fail ("lufrag", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 662, __extension__ __PRETTY_FUNCTION__); }))
;
663 if (!lufrag)
664 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
665 lpwd=component->stream->pwd;
666 assert(lpwd)((void) sizeof ((lpwd) ? 1 : 0), __extension__ ({ if (lpwd) ;
else __assert_fail ("lpwd", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 666, __extension__ __PRETTY_FUNCTION__); }))
;
667 if (!lpwd)
668 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
669 INIT_DATA(pwd, (UCHAR *)lpwd, strlen(lpwd))(pwd).data=(UCHAR *)lpwd; (pwd).len=strlen(lpwd);
670
671 /* Initialize the UDP candidates */
672 if (r=nr_ice_component_initialize_udp(ctx, component, addrs, addr_ct, lufrag, &pwd))
673 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): failed to create UDP candidates with error %d",ctx->label,r);
674 /* And the TCP candidates */
675 if (r=nr_ice_component_initialize_tcp(ctx, component, addrs, addr_ct, lufrag, &pwd))
676 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): failed to create TCP candidates with error %d",ctx->label,r);
677
678 /* count the candidates that will be initialized */
679 cand=TAILQ_FIRST(&component->candidates)((&component->candidates)->tqh_first);
680 if(!cand){
681 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): couldn't create any valid candidates",ctx->label);
682 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
683 }
684
685 while(cand){
686 ctx->uninitialized_candidates++;
687 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
688 }
689
690 /* Now initialize all the candidates */
691 cand=TAILQ_FIRST(&component->candidates)((&component->candidates)->tqh_first);
692 while(cand){
693 if(cand->state!=NR_ICE_CAND_STATE_INITIALIZING2){
694 nr_ice_candidate_initialize(cand,nr_ice_gather_finished_cb,cand);
695 }
696 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
697 }
698 _status=0;
699 abort:
700 return(_status);
701 }
702
703void nr_ice_component_stop_gathering(nr_ice_component *component)
704 {
705 nr_ice_candidate *c1,*c2;
706 TAILQ_FOREACH_SAFE(c1, &component->candidates, entry_comp, c2)for ((c1) = (((&component->candidates))->tqh_first)
; (c1) && ((c2) = (((c1))->entry_comp.tqe_next), 1
); (c1) = (c2))
{
707 nr_ice_candidate_stop_gathering(c1);
708 }
709 }
710
711int nr_ice_component_is_done_gathering(nr_ice_component *comp)
712 {
713 nr_ice_candidate *cand=TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
714 while(cand){
715 if(cand->state != NR_ICE_CAND_STATE_INITIALIZED3 &&
716 cand->state != NR_ICE_CAND_STATE_FAILED4){
717 return 0;
718 }
719 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
720 }
721 return 1;
722 }
723
724
725static int nr_ice_any_peer_paired(nr_ice_candidate* cand) {
726 nr_ice_peer_ctx* pctx=STAILQ_FIRST(&cand->ctx->peers)((&cand->ctx->peers)->stqh_first);
727 while(pctx && pctx->state == NR_ICE_PEER_STATE_UNPAIRED1){
728 /* Is it worth actually looking through the check lists? Probably not. */
729 pctx=STAILQ_NEXT(pctx,entry)((pctx)->entry.stqe_next);
730 }
731 return pctx != NULL((void*)0);
732}
733
734/*
735 Compare this newly initialized candidate against the other initialized
736 candidates and discard the lower-priority one if they are redundant.
737
738 This algorithm combined with the other algorithms, favors
739 host > srflx > relay
740 */
741int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *comp, nr_ice_candidate *c1, int *was_pruned)
742 {
743 nr_ice_candidate *c2, *tmp = NULL((void*)0);
744
745 *was_pruned = 0;
746 c2 = TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
747 while(c2){
748 if((c1 != c2) &&
749 (c2->state == NR_ICE_CAND_STATE_INITIALIZED3) &&
750 !nr_transport_addr_cmp(&c1->base,&c2->base,NR_TRANSPORT_ADDR_CMP_MODE_ALL4) &&
751 !nr_transport_addr_cmp(&c1->addr,&c2->addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4)){
752
753 if((c1->type == c2->type) ||
754 (!(ctx->flags & NR_ICE_CTX_FLAGS_DISABLE_HOST_CANDIDATES(1<<3)) &&
755 !(ctx->flags & NR_ICE_CTX_FLAGS_OBFUSCATE_HOST_ADDRESSES(1<<6)) &&
756 ((c1->type==HOST && c2->type == SERVER_REFLEXIVE) ||
757 (c2->type==HOST && c1->type == SERVER_REFLEXIVE)))){
758
759 /*
760 These are redundant. Remove the lower pri one, or if pairing has
761 already occurred, remove the newest one.
762
763 Since this algorithmis run whenever a new candidate
764 is initialized, there should at most one duplicate.
765 */
766 if ((c1->priority <= c2->priority) || nr_ice_any_peer_paired(c2)) {
767 tmp = c1;
768 *was_pruned = 1;
769 }
770 else {
771 tmp = c2;
772 }
773 break;
774 }
775 }
776
777 c2=TAILQ_NEXT(c2,entry_comp)((c2)->entry_comp.tqe_next);
778 }
779
780 if (tmp) {
781 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s)/CAND(%s): Removing redundant candidate",
782 ctx->label,tmp->label);
783
784 TAILQ_REMOVE(&comp->candidates,tmp,entry_comp)do { if (((((tmp))->entry_comp.tqe_next)) != ((void*)0)) (
((tmp))->entry_comp.tqe_next)->entry_comp.tqe_prev = (tmp
)->entry_comp.tqe_prev; else { (&comp->candidates)->
tqh_last = (tmp)->entry_comp.tqe_prev; ; } *(tmp)->entry_comp
.tqe_prev = (((tmp))->entry_comp.tqe_next); ; ; ; } while (
0)
;
785 comp->candidate_ct--;
786 TAILQ_REMOVE(&tmp->isock->candidates,tmp,entry_sock)do { if (((((tmp))->entry_sock.tqe_next)) != ((void*)0)) (
((tmp))->entry_sock.tqe_next)->entry_sock.tqe_prev = (tmp
)->entry_sock.tqe_prev; else { (&tmp->isock->candidates
)->tqh_last = (tmp)->entry_sock.tqe_prev; ; } *(tmp)->
entry_sock.tqe_prev = (((tmp))->entry_sock.tqe_next); ; ; ;
} while (0)
;
787
788 nr_ice_candidate_destroy(&tmp);
789 }
790
791 return 0;
792 }
793
794static int nr_ice_component_pair_matches_check(nr_ice_component *comp, nr_ice_cand_pair *pair, nr_transport_addr *local_addr, nr_stun_server_request *req)
795 {
796 if(pair->remote->component->component_id!=comp->component_id)
797 return(0);
798
799 if(nr_transport_addr_cmp(&pair->local->base,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4))
800 return(0);
801
802 if(nr_transport_addr_cmp(&pair->remote->addr,&req->src_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4))
803 return(0);
804
805 return(1);
806 }
807
808static int nr_ice_component_handle_use_candidate(nr_ice_component *comp, nr_ice_cand_pair *pair, int *error)
809 {
810 int r=0,_status;
811
812 if(comp->stream->pctx->controlling){
813 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s)/CAND_PAIR(%s): Peer sent USE-CANDIDATE but is controlled",comp->stream->pctx->label, pair->codeword);
814 }
815 else{
816 /* If this is the first time we've noticed this is nominated...*/
817 pair->peer_nominated=1;
818
819 if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED5 && !pair->nominated){
820 pair->nominated=1;
821
822 if(r=nr_ice_component_nominated_pair(pair->remote->component, pair)) {
823 *error=(r==R_NO_MEMORY1)?500:400;
824 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
825 }
826 }
827 }
828
829 _status=0;
830 abort:
831 return(_status);
832 }
833
834/* Section 7.2.1 */
835static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_transport_addr *local_addr, nr_stun_server_request *req, int *error)
836 {
837 nr_ice_cand_pair *pair;
838 nr_ice_candidate *pcand=0;
839 nr_stun_message *sreq=req->request;
840 nr_stun_message_attribute *attr;
841 int r=0,_status;
842 int found_valid=0;
843
844 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): received request from %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,req->src_addr.as_string);
845
846 if (comp->state == NR_ICE_COMPONENT_DISABLED4)
847 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
848
849 /* Check for role conficts (7.2.1.1) */
850 if(comp->stream->pctx->controlling){
851 if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_ICE_CONTROLLING0x802A,&attr)){
852 /* OK, there is a conflict. Who's right? */
853 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): role conflict, both controlling",comp->stream->pctx->label);
854
855 if(attr->u.ice_controlling > comp->stream->pctx->tiebreaker){
856 /* Update the peer ctx. This will propagate to all candidate pairs
857 in the context. */
858 nr_ice_peer_ctx_switch_controlling_role(comp->stream->pctx);
859 }
860 else {
861 /* We are: throw an error */
862 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s): returning 487 role conflict",comp->stream->pctx->label);
863
864 *error=487;
865 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
866 }
867 }
868 }
869 else{
870 if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_ICE_CONTROLLED0x8029,&attr)){
871 /* OK, there is a conflict. Who's right? */
872 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): role conflict, both controlled",comp->stream->pctx->label);
873
874 if(attr->u.ice_controlled < comp->stream->pctx->tiebreaker){
875 /* Update the peer ctx. This will propagate to all candidate pairs
876 in the context. */
877 nr_ice_peer_ctx_switch_controlling_role(comp->stream->pctx);
878 }
879 else {
880 /* We are: throw an error */
881 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s): returning 487 role conflict",comp->stream->pctx->label);
882
883 *error=487;
884 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
885 }
886 }
887 }
888
889 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): This STUN request appears to map to local addr %s",comp->stream->pctx->label,local_addr->as_string);
890
891 pair=TAILQ_FIRST(&comp->stream->check_list)((&comp->stream->check_list)->tqh_first);
892 while(pair){
893 /* Since triggered checks create duplicate pairs (in this implementation)
894 * we are willing to handle multiple matches here. */
895 if(nr_ice_component_pair_matches_check(comp, pair, local_addr, req)){
896 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND_PAIR(%s): Found a matching pair for received check: %s",comp->stream->pctx->label,pair->codeword,pair->as_string);
897 int peer_nominated = pair->peer_nominated;
898 if(nr_stun_message_has_attribute(req->request,NR_STUN_ATTR_USE_CANDIDATE0x0025,0)){
899 if(r=nr_ice_component_handle_use_candidate(comp, pair, error)) {
900 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
901 }
902 }
903
904 int new_peer_nomination = !peer_nominated && pair->peer_nominated;
905 int might_select = !comp->nominated ||
906 (comp->nominated->priority < pair->priority);
907 int force = new_peer_nomination && might_select;
908
909 /* Note: the RFC says to trigger first and then nominate. But in that
910 * case the canceled trigger pair would get nominated and the cloned
911 * trigger pair would not get the nomination status cloned with it.*/
912 if(!found_valid && (r=nr_ice_candidate_pair_do_triggered_check(comp->stream->pctx, pair, force))) {
913 *error=(r==R_NO_MEMORY1)?500:400;
914 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
915 }
916 found_valid=1;
917 }
918 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
919 }
920
921 if(!found_valid){
922 /* There were no matching pairs, so we need to create a new peer
923 * reflexive candidate pair. */
924
925 if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY0x0024,&attr)){
926 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
927 *error=400;
928 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
929 }
930
931 /* Find our local component candidate */
932 nr_ice_candidate *cand;
933
934 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): no matching pair",comp->stream->pctx->label);
935 cand=TAILQ_FIRST(&comp->local_component->candidates)((&comp->local_component->candidates)->tqh_first
)
;
936 while(cand){
937 if(!nr_transport_addr_cmp(&cand->addr,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL4))
938 break;
939
940 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
941 }
942
943 /* Well, this really shouldn't happen, but it's an error from the
944 other side, so we just throw an error and keep going */
945 if(!cand){
946 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s): stun request to unknown local address %s, discarding",comp->stream->pctx->label,local_addr->as_string);
947
948 *error=400;
949 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
950 }
951
952 /* Now make a peer reflexive (remote) candidate */
953 if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
954 *error=(r==R_NO_MEMORY1)?500:400;
955 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
956 }
957 pcand->priority=attr->u.priority;
958 pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED10;
959
960 /* Finally, create the candidate pair, insert into the check list, and
961 * apply the incoming check to it. */
962 if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
963 &pair)) {
964 *error=(r==R_NO_MEMORY1)?500:400;
965 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
966 }
967
968 nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN1);
969 if(r=nr_ice_component_insert_pair(comp,pair)) {
970 *error=(r==R_NO_MEMORY1)?500:400;
971 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
972 }
973
974 /* Do this last, since any call to ABORT will destroy pcand */
975 TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp)do { (((pcand))->entry_comp.tqe_next) = ((void*)0); (pcand
)->entry_comp.tqe_prev = (&comp->candidates)->tqh_last
; *(&comp->candidates)->tqh_last = (pcand); (&comp
->candidates)->tqh_last = &(((pcand))->entry_comp
.tqe_next); ; ; } while (0)
;
976 pcand=0;
977
978 if(nr_stun_message_has_attribute(req->request,NR_STUN_ATTR_USE_CANDIDATE0x0025,0)){
979 if(r=nr_ice_component_handle_use_candidate(comp, pair, error)) {
980 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
981 }
982 }
983
984 /* Finally start the trigger check if needed */
985 if(r=nr_ice_candidate_pair_do_triggered_check(comp->stream->pctx, pair, 0)) {
986 *error=(r==R_NO_MEMORY1)?500:400;
987 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
988 }
989 }
990
991 _status=0;
992 abort:
993 if(_status){
994 nr_ice_candidate_destroy(&pcand);
995 assert(*error != 0)((void) sizeof ((*error != 0) ? 1 : 0), __extension__ ({ if (
*error != 0) ; else __assert_fail ("*error != 0", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 995, __extension__ __PRETTY_FUNCTION__); }))
;
996 if(r!=R_NO_MEMORY1) assert(*error != 500)((void) sizeof ((*error != 500) ? 1 : 0), __extension__ ({ if
(*error != 500) ; else __assert_fail ("*error != 500", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 996, __extension__ __PRETTY_FUNCTION__); }))
;
997 }
998 return(_status);
999 }
1000
1001static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error)
1002 {
1003 nr_ice_component *pcomp=cb_arg;
1004 nr_transport_addr local_addr;
1005 int r,_status;
1006
1007 if(pcomp->state==NR_ICE_COMPONENT_FAILED3) {
1008 *error=400;
1009 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1010 }
1011
1012 if (pcomp->local_component->stream->obsolete) {
1013 /* Don't do any triggered check stuff in thiis case. */
1014 return 0;
1015 }
1016
1017 /* Find the candidate pair that this maps to */
1018 if(r=nr_socket_getaddr(sock,&local_addr)) {
1019 *error=500;
1020 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1021 }
1022
1023 if (r=nr_ice_component_process_incoming_check(pcomp, &local_addr, req, error))
1024 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1025
1026 _status=0;
1027 abort:
1028 return(_status);
1029 }
1030
1031int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced)
1032 {
1033 nr_ice_pre_answer_request *r1,*r2;
1034 nr_ice_component *comp = pcomp->local_component;
1035 int r,_status;
1036
1037 if (serviced)
1038 *serviced = 0;
1039
1040 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): looking for pre-answer requests",pctx->label,comp->stream->label,comp->component_id);
1041
1042 STAILQ_FOREACH_SAFE(r1, &comp->pre_answer_reqs, entry, r2)for ((r1) = (((&comp->pre_answer_reqs))->stqh_first
); (r1) && ((r2) = (((r1))->entry.stqe_next), 1); (
r1) = (r2))
{
1043 if (!strcmp(r1->username, username)) {
1044 int error = 0;
1045
1046 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): found pre-answer request",pctx->label,comp->stream->label,comp->component_id);
1047 r = nr_ice_component_process_incoming_check(pcomp, &r1->local_addr, &r1->req, &error);
1048 if (r) {
1049 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): error processing pre-answer request. Would have returned %d",pctx->label,comp->stream->label,comp->component_id, error);
1050 }
1051 (*serviced)++;
1052 STAILQ_REMOVE(&comp->pre_answer_reqs,r1,nr_ice_pre_answer_request_, entry)do { if ((((&comp->pre_answer_reqs))->stqh_first) ==
(r1)) { do { if ((((((&comp->pre_answer_reqs)))->stqh_first
) = ((((((&comp->pre_answer_reqs)))->stqh_first))->
entry.stqe_next)) == ((void*)0)) ((&comp->pre_answer_reqs
))->stqh_last = &((((&comp->pre_answer_reqs)))->
stqh_first); } while (0); } else { struct nr_ice_pre_answer_request_
*curelm = (((&comp->pre_answer_reqs))->stqh_first)
; while (((curelm)->entry.stqe_next) != (r1)) curelm = ((curelm
)->entry.stqe_next); if ((((curelm)->entry.stqe_next) =
((((curelm)->entry.stqe_next))->entry.stqe_next)) == (
(void*)0)) (&comp->pre_answer_reqs)->stqh_last = &
(((curelm))->entry.stqe_next); } } while (0)
;
1053 nr_ice_pre_answer_request_destroy(&r1);
1054 }
1055 }
1056
1057 _status=0;
1058 return(_status);
1059 }
1060
1061int nr_ice_component_can_candidate_tcptype_pair(nr_socket_tcp_type left, nr_socket_tcp_type right)
1062 {
1063 if (left && !right)
1064 return(0);
1065 if (!left && right)
1066 return(0);
1067 if (left == TCP_TYPE_ACTIVE && right != TCP_TYPE_PASSIVE)
1068 return(0);
1069 if (left == TCP_TYPE_SO && right != TCP_TYPE_SO)
1070 return(0);
1071 if (left == TCP_TYPE_PASSIVE)
1072 return(0);
1073
1074 return(1);
1075 }
1076
1077/* filter out pairings which won't work. */
1078int nr_ice_component_can_candidate_addr_pair(nr_transport_addr *local, nr_transport_addr *remote)
1079 {
1080 if(local->ip_version != remote->ip_version)
1081 return(0);
1082 if(local->protocol != remote->protocol)
1083 return(0);
1084 if(nr_transport_addr_is_link_local(local) !=
1085 nr_transport_addr_is_link_local(remote))
1086 return(0);
1087 /* This prevents our ice_unittest (or broken clients) from pairing a
1088 * loopback with a host candidate. */
1089 if(nr_transport_addr_is_loopback(local) !=
1090 nr_transport_addr_is_loopback(remote))
1091 return(0);
1092
1093 return(1);
1094 }
1095
1096int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, nr_ice_candidate *lcand, int pair_all_remote)
1097 {
1098 int r, _status;
1099 nr_ice_candidate *pcand;
1100 nr_ice_cand_pair *pair=0;
1101 char codeword[5];
1102
1103 nr_ice_compute_codeword(lcand->label,strlen(lcand->label),codeword);
1104 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND(%s): Pairing local candidate %s",pctx->label,codeword,lcand->label);
1105
1106 switch(lcand->type){
1107 case HOST:
1108 break;
1109 case SERVER_REFLEXIVE:
1110 case PEER_REFLEXIVE:
1111 /* Don't actually pair these candidates */
1112 goto done;
1113 break;
1114 case RELAYED:
1115 break;
1116 default:
1117 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_component.c"
, 1117, __extension__ __PRETTY_FUNCTION__); }))
;
1118 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1119 break;
1120 }
1121
1122 TAILQ_FOREACH(pcand, &pcomp->candidates, entry_comp)for ((pcand) = (((&pcomp->candidates))->tqh_first);
(pcand); (pcand) = (((pcand))->entry_comp.tqe_next))
{
1123 if(!nr_ice_component_can_candidate_addr_pair(&lcand->addr, &pcand->addr))
1124 continue;
1125 if(!nr_ice_component_can_candidate_tcptype_pair(lcand->tcp_type, pcand->tcp_type))
1126 continue;
1127
1128 /* https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-03#section-3.3.2 */
1129 if(lcand->type == RELAYED && pcand->mdns_addr && strlen(pcand->mdns_addr)) {
1130 continue;
1131 }
1132
1133 /*
1134 Two modes, depending on |pair_all_remote|
1135
1136 1. Pair remote candidates which have not been paired
1137 (used in initial pairing or in processing the other side's
1138 trickle candidates).
1139 2. Pair any remote candidate (used when processing our own
1140 trickle candidates).
1141 */
1142 if (pair_all_remote || (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED9)) {
1143 if (pair_all_remote) {
1144 /* When a remote candidate arrives after the start of checking, but
1145 * before the gathering of local candidates, it can be in UNPAIRED */
1146 pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED10;
1147 }
1148
1149 nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
1150 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND(%s): Pairing with peer candidate %s", pctx->label, codeword, pcand->label);
1151
1152 if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
1153 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1154
1155 if(r=nr_ice_component_insert_pair(pcomp, pair))
1156 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1157 }
1158 }
1159
1160 done:
1161 _status = 0;
1162 abort:
1163 return(_status);
1164 }
1165
1166int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp)
1167 {
1168 nr_ice_candidate *lcand, *pcand;
1169 nr_ice_socket *isock;
1170 int r,_status;
1171
1172 r_log(LOG_ICE,LOG_DEBUG7,"Pairing candidates======");
1173
1174 /* Create the candidate pairs */
1175 lcand=TAILQ_FIRST(&lcomp->candidates)((&lcomp->candidates)->tqh_first);
1176
1177 if (!lcand) {
1178 /* No local candidates, initialized or not! */
1179 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1180 }
1181
1182 while(lcand){
1183 if (lcand->state == NR_ICE_CAND_STATE_INITIALIZED3) {
1184 if ((r = nr_ice_component_pair_candidate(pctx, pcomp, lcand, 0)))
1185 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1186 }
1187
1188 lcand=TAILQ_NEXT(lcand,entry_comp)((lcand)->entry_comp.tqe_next);
1189 }
1190
1191 /* Mark all peer candidates as paired */
1192 pcand=TAILQ_FIRST(&pcomp->candidates)((&pcomp->candidates)->tqh_first);
1193 while(pcand){
1194 pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED10;
1195
1196 pcand=TAILQ_NEXT(pcand,entry_comp)((pcand)->entry_comp.tqe_next);
1197
1198 }
1199
1200 /* Now register the STUN server callback for this component.
1201 Note that this is a per-component CB so we only need to
1202 do this once.
1203 */
1204 if (pcomp->state != NR_ICE_COMPONENT_RUNNING1) {
1205 isock=STAILQ_FIRST(&lcomp->sockets)((&lcomp->sockets)->stqh_first);
1206 while(isock){
1207 if(r=nr_stun_server_add_client(isock->stun_server,pctx->label,
1208 pcomp->stream->r2l_user,&pcomp->stream->r2l_pass,nr_ice_component_stun_server_cb,pcomp)) {
1209 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1210 }
1211 isock=STAILQ_NEXT(isock,entry)((isock)->entry.stqe_next);
1212 }
1213 }
1214
1215 pcomp->state = NR_ICE_COMPONENT_RUNNING1;
1216
1217 _status=0;
1218 abort:
1219 return(_status);
1220 }
1221
1222int nr_ice_pre_answer_enqueue(nr_ice_component *comp, nr_socket *sock, nr_stun_server_request *req, int *dont_free)
1223 {
1224 int r = 0;
1225 int _status;
1226 nr_ice_pre_answer_request *r1, *r2;
1227 nr_transport_addr dst_addr;
1228 nr_ice_pre_answer_request *par = 0;
1229
1230 if (r=nr_socket_getaddr(sock, &dst_addr))
1231 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1232
1233 STAILQ_FOREACH_SAFE(r1, &comp->pre_answer_reqs, entry, r2)for ((r1) = (((&comp->pre_answer_reqs))->stqh_first
); (r1) && ((r2) = (((r1))->entry.stqe_next), 1); (
r1) = (r2))
{
1234 if (!nr_transport_addr_cmp(&r1->local_addr, &dst_addr,
1235 NR_TRANSPORT_ADDR_CMP_MODE_ALL4) &&
1236 !nr_transport_addr_cmp(&r1->req.src_addr, &req->src_addr,
1237 NR_TRANSPORT_ADDR_CMP_MODE_ALL4)) {
1238 return(0);
1239 }
1240 }
1241
1242 if (r=nr_ice_pre_answer_request_create(&dst_addr, req, &par))
1243 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1244
1245 r_log(LOG_ICE,LOG_DEBUG7, "ICE(%s)/STREAM(%s)/COMP(%d): Enqueuing STUN request pre-answer from %s",
1246 comp->ctx->label, comp->stream->label, comp->component_id,
1247 req->src_addr.as_string);
1248
1249 *dont_free = 1;
1250 STAILQ_INSERT_TAIL(&comp->pre_answer_reqs, par, entry)do { (((par))->entry.stqe_next) = ((void*)0); *(&comp->
pre_answer_reqs)->stqh_last = (par); (&comp->pre_answer_reqs
)->stqh_last = &(((par))->entry.stqe_next); } while
(0)
;
1251
1252 _status=0;
1253abort:
1254 return(_status);
1255 }
1256
1257/* Fires when we have an incoming candidate that doesn't correspond to an existing
1258 remote peer. This is either pre-answer or just spurious. Store it in the
1259 component for use when we see the actual answer, at which point we need
1260 to do the procedures from S 7.2.1 in nr_ice_component_stun_server_cb.
1261 */
1262static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error)
1263 {
1264 int r, _status;
1265 nr_ice_component *comp = (nr_ice_component *)cb_arg;
1266
1267 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s)/STREAM(%s)/COMP(%d): Received STUN request pre-answer from %s",
1268 comp->ctx->label, comp->stream->label, comp->component_id,
1269 req->src_addr.as_string);
1270
1271 if (r=nr_ice_pre_answer_enqueue(comp, sock, req, dont_free)) {
1272 r_log(LOG_ICE,LOG_ERR3,"ICE(%s)/STREAM(%s)/COMP(%d): Failed (%d) to enque pre-answer request from %s",
1273 comp->ctx->label, comp->stream->label, comp->component_id, r,
1274 req->src_addr.as_string);
1275 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1276 }
1277
1278 _status=0;
1279 abort:
1280 return(_status);
1281 }
1282
1283#define NR_ICE_CONSENT_TIMER_DEFAULT5000 5000
1284#define NR_ICE_CONSENT_TIMEOUT_DEFAULT30000 30000
1285
1286static void nr_ice_component_consent_failed(nr_ice_component *comp)
1287 {
1288 if (!comp->can_send) {
1289 return;
1290 }
1291
1292 r_log(LOG_ICE,LOG_INFO6,"ICE(%s)/STREAM(%s)/COMP(%d): Consent refresh failed",
1293 comp->ctx->label, comp->stream->label, comp->component_id);
1294 comp->can_send = 0;
1295
1296 if (comp->consent_timeout) {
1297 NR_async_timer_cancel(comp->consent_timeout);
1298 comp->consent_timeout = 0;
1299 }
1300 if (comp->consent_timer) {
1301 NR_async_timer_cancel(comp->consent_timer);
1302 comp->consent_timer = 0;
1303 }
1304 /* We are turning the consent failure into a ICE component failure to
1305 * alert the browser via ICE connection state change about this event. */
1306 nr_ice_media_stream_component_failed(comp->stream, comp);
1307 }
1308
1309static void nr_ice_component_consent_timeout_cb(NR_SOCKET s, int how, void *cb_arg)
1310 {
1311 nr_ice_component *comp=cb_arg;
1312
1313 comp->consent_timeout = 0;
1314
1315 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s)/STREAM(%s)/COMP(%d): Consent refresh final time out",
1316 comp->ctx->label, comp->stream->label, comp->component_id);
1317 nr_ice_component_consent_failed(comp);
1318 }
1319
1320
1321void nr_ice_component_disconnected(nr_ice_component *comp)
1322 {
1323 if (!comp->can_send) {
1324 return;
1325 }
1326
1327 if (comp->disconnected) {
1328 return;
1329 }
1330
1331 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s)/STREAM(%s)/COMP(%d): component disconnected",
1332 comp->ctx->label, comp->stream->label, comp->component_id);
1333 comp->disconnected = 1;
1334
1335 /* a single disconnected component disconnects the stream */
1336 nr_ice_media_stream_set_disconnected(comp->stream, NR_ICE_MEDIA_STREAM_DISCONNECTED1);
1337 }
1338
1339static void nr_ice_component_consent_refreshed(nr_ice_component *comp)
1340 {
1341 uint16_t tval;
1342
1343 if (!comp->can_send) {
1344 return;
1345 }
1346
1347 gettimeofday(&comp->consent_last_seen, 0);
1348 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s)/STREAM(%s)/COMP(%d): consent_last_seen is now %lu",
1349 comp->ctx->label, comp->stream->label, comp->component_id,
1350 comp->consent_last_seen.tv_sec);
1351
1352 comp->disconnected = 0;
1353
1354 nr_ice_media_stream_check_if_connected(comp->stream);
1355
1356 if (comp->consent_timeout)
1357 NR_async_timer_cancel(comp->consent_timeout);
1358
1359 tval = NR_ICE_CONSENT_TIMEOUT_DEFAULT30000;
1360 if (comp->ctx->test_timer_divider)
1361 tval = tval / comp->ctx->test_timer_divider;
1362
1363 NR_ASYNC_TIMER_SET(tval, nr_ice_component_consent_timeout_cb, comp,NR_async_timer_set(tval,nr_ice_component_consent_timeout_cb,comp
,(char *)__FUNCTION__,1364,&comp->consent_timeout)
1364 &comp->consent_timeout)NR_async_timer_set(tval,nr_ice_component_consent_timeout_cb,comp
,(char *)__FUNCTION__,1364,&comp->consent_timeout)
;
1365 }
1366
1367static void nr_ice_component_refresh_consent_cb(NR_SOCKET s, int how, void *cb_arg)
1368 {
1369 nr_ice_cand_pair *pair=cb_arg;
1370 assert(pair && pair->remote && pair->remote->component)((void) sizeof ((pair && pair->remote && pair
->remote->component) ? 1 : 0), __extension__ ({ if (pair
&& pair->remote && pair->remote->component
) ; else __assert_fail ("pair && pair->remote && pair->remote->component"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 1370, __extension__ __PRETTY_FUNCTION__); }))
;
1371 nr_ice_component *comp=pair->remote->component;
1372
1373 switch (comp->consent_ctx->state) {
1374 case NR_STUN_CLIENT_STATE_FAILED3:
1375 if (comp->consent_ctx->error_code == 403) {
1376 r_log(LOG_ICE, LOG_INFO6, "ICE(%s)/STREAM(%s)/COMP(%d): Consent revoked by peer",
1377 comp->ctx->label, comp->stream->label, comp->component_id);
1378 nr_ice_component_consent_failed(comp);
1379 }
1380 break;
1381 case NR_STUN_CLIENT_STATE_DONE2:
1382 r_log(LOG_ICE, LOG_INFO6, "ICE(%s)/STREAM(%s)/COMP(%d): Consent refreshed",
1383 comp->ctx->label, comp->stream->label, comp->component_id);
1384 if (comp->consent_ctx->rtt_valid) {
1385 nr_ice_candidate_pair_update_rtt(pair, comp->consent_ctx->rtt_ms);
1386 // clear rtt_ms so we can't double process it.
1387 comp->consent_ctx->rtt_valid = 0;
1388 comp->consent_ctx->rtt_ms = 0;
1389 }
1390 nr_ice_component_consent_refreshed(comp);
1391 break;
1392 case NR_STUN_CLIENT_STATE_TIMED_OUT4:
1393 r_log(LOG_ICE, LOG_INFO6, "ICE(%s)/STREAM(%s)/COMP(%d): A single consent refresh request timed out",
1394 comp->ctx->label, comp->stream->label, comp->component_id);
1395 nr_ice_component_disconnected(comp);
1396 break;
1397 default:
1398 break;
1399 }
1400 }
1401
1402int nr_ice_component_refresh_consent(nr_stun_client_ctx *ctx, NR_async_cb finished_cb, void *cb_arg)
1403 {
1404 int r,_status;
1405
1406 nr_stun_client_reset(ctx);
1407
1408 if (r=nr_stun_client_start(ctx, NR_ICE_CLIENT_MODE_BINDING_REQUEST11, finished_cb, cb_arg))
1409 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1410
1411 _status=0;
1412 abort:
1413 return(_status);
1414 }
1415
1416void nr_ice_component_consent_calc_consent_timer(nr_ice_component *comp)
1417 {
1418 uint16_t trange, trand, tval;
1419
1420 trange = NR_ICE_CONSENT_TIMER_DEFAULT5000 * 20 / 100;
1421 tval = NR_ICE_CONSENT_TIMER_DEFAULT5000 - trange;
1422 if (!nr_crypto_random_bytes((UCHAR*)&trand, sizeof(trand))nr_crypto_vtbl->random_bytes((UCHAR*)&trand,sizeof(trand
))
)
1423 tval += (trand % (trange * 2));
1424
1425 if (comp->ctx->test_timer_divider)
1426 tval = tval / comp->ctx->test_timer_divider;
1427
1428 /* The timeout of the transaction is the maximum time until we send the
1429 * next consent request. */
1430 comp->consent_ctx->maximum_transmits_timeout_ms = tval;
1431 }
1432
1433static void nr_ice_component_consent_timer_cb(NR_SOCKET s, int how, void *cb_arg)
1434 {
1435 nr_ice_component *comp=cb_arg;
1436 int r;
1437
1438 if (!comp->consent_ctx) {
1439 return;
1440 }
1441
1442 if (comp->consent_timer) {
1443 NR_async_timer_cancel(comp->consent_timer);
1444 }
1445 comp->consent_timer = 0;
1446
1447 comp->consent_ctx->params.ice_binding_request.username =
1448 comp->stream->l2r_user;
1449 comp->consent_ctx->params.ice_binding_request.password =
1450 comp->stream->l2r_pass;
1451 comp->consent_ctx->params.ice_binding_request.control =
1452 comp->stream->pctx->controlling?
1453 NR_ICE_CONTROLLING1:NR_ICE_CONTROLLED2;
1454 comp->consent_ctx->params.ice_binding_request.tiebreaker =
1455 comp->stream->pctx->tiebreaker;
1456 comp->consent_ctx->params.ice_binding_request.priority =
1457 comp->active->local->priority;
1458
1459 nr_ice_component_consent_calc_consent_timer(comp);
1460
1461 if (r=nr_ice_component_refresh_consent(comp->consent_ctx,
1462 nr_ice_component_refresh_consent_cb,
1463 comp->active)) {
1464 r_log(LOG_ICE,LOG_ERR3,"ICE(%s)/STREAM(%s)/COMP(%d): Refresh consent failed with %d",
1465 comp->ctx->label, comp->stream->label, comp->component_id, r);
1466 }
1467
1468 nr_ice_component_consent_schedule_consent_timer(comp);
1469
1470 }
1471
1472void nr_ice_component_consent_schedule_consent_timer(nr_ice_component *comp)
1473 {
1474 if (!comp->can_send) {
1475 return;
1476 }
1477
1478 NR_ASYNC_TIMER_SET(comp->consent_ctx->maximum_transmits_timeout_ms,NR_async_timer_set(comp->consent_ctx->maximum_transmits_timeout_ms
,nr_ice_component_consent_timer_cb,comp,(char *)__FUNCTION__,
1480,&comp->consent_timer)
1479 nr_ice_component_consent_timer_cb, comp,NR_async_timer_set(comp->consent_ctx->maximum_transmits_timeout_ms
,nr_ice_component_consent_timer_cb,comp,(char *)__FUNCTION__,
1480,&comp->consent_timer)
1480 &comp->consent_timer)NR_async_timer_set(comp->consent_ctx->maximum_transmits_timeout_ms
,nr_ice_component_consent_timer_cb,comp,(char *)__FUNCTION__,
1480,&comp->consent_timer)
;
1481 }
1482
1483void nr_ice_component_refresh_consent_now(nr_ice_component *comp)
1484 {
1485 nr_ice_component_consent_timer_cb(0, 0, comp);
1486 }
1487
1488void nr_ice_component_consent_destroy(nr_ice_component *comp)
1489 {
1490 if (comp->consent_timer) {
1491 NR_async_timer_cancel(comp->consent_timer);
1492 comp->consent_timer = 0;
1493 }
1494 if (comp->consent_timeout) {
1495 NR_async_timer_cancel(comp->consent_timeout);
1496 comp->consent_timeout = 0;
1497 }
1498 if (comp->consent_handle) {
1499 nr_ice_socket_deregister(comp->active->local->isock,
1500 comp->consent_handle);
1501 comp->consent_handle = 0;
1502 }
1503 if (comp->consent_ctx) {
1504 nr_stun_client_ctx_destroy(&comp->consent_ctx);
1505 comp->consent_ctx = 0;
1506 }
1507 }
1508
1509int nr_ice_component_setup_consent(nr_ice_component *comp)
1510 {
1511 int r,_status;
1512
1513 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s)/STREAM(%s)/COMP(%d): Setting up refresh consent",
1514 comp->ctx->label, comp->stream->label, comp->component_id);
1515
1516 nr_ice_component_consent_destroy(comp);
1517
1518 if (r=nr_stun_client_ctx_create("consent", comp->active->local->osock,
1519 &comp->active->remote->addr, 0,
1520 &comp->consent_ctx))
1521 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1522 /* Consent request get send only once. */
1523 comp->consent_ctx->maximum_transmits = 1;
1524
1525 if (r=nr_ice_socket_register_stun_client(comp->active->local->isock,
1526 comp->consent_ctx, &comp->consent_handle))
1527 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1528
1529 comp->can_send = 1;
1530 comp->disconnected = 0;
1531 nr_ice_component_consent_refreshed(comp);
1532
1533 nr_ice_component_consent_calc_consent_timer(comp);
1534 nr_ice_component_consent_schedule_consent_timer(comp);
1535
1536 _status=0;
1537 abort:
1538 return(_status);
1539 }
1540
1541int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
1542 {
1543 int r,_status;
1544 nr_ice_cand_pair *p2;
1545
1546 /* Are we changing what the nominated pair is? */
1547 if(comp->nominated){
1548 if(comp->nominated->priority >= pair->priority)
1549 return(0);
1550 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): replacing pair %s with CAND-PAIR(%s)",comp->stream->pctx->label,comp->stream->label,comp->component_id,comp->nominated->codeword,comp->nominated->as_string,pair->codeword);
1551 /* As consent doesn't hold a reference to its isock this needs to happen
1552 * before making the new pair the active one. */
1553 nr_ice_component_consent_destroy(comp);
1554 }
1555
1556 /* Set the new nominated pair */
1557 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): nominated pair is %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->codeword,pair->as_string);
1558 comp->state=NR_ICE_COMPONENT_NOMINATED2;
1559 comp->nominated=pair;
1560 comp->active=pair;
1561
1562 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling all pairs but %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->codeword,pair->as_string);
1563
1564 /* Cancel checks in WAITING and FROZEN per ICE S 8.1.2 */
1565 /* DO NOT CANCEL HIGHER PRIORITY PEER NOMINATED PAIRS!!! If a pair has been
1566 * peer nominated, we _must_ pursue it to completion, because if this is
1567 * the highest priority working pair from the peer's perspective, this is
1568 * the one it will use! This is a spec bug. */
1569 p2=TAILQ_FIRST(&comp->stream->trigger_check_queue)((&comp->stream->trigger_check_queue)->tqh_first
)
;
1570 while(p2){
1571 if((p2 != pair) &&
1572 (p2->remote->component->component_id == comp->component_id) &&
1573 !(p2->peer_nominated && (p2->priority > pair->priority))) {
1574 assert(p2->state == NR_ICE_PAIR_STATE_WAITING ||((void) sizeof ((p2->state == 2 || p2->state == 6) ? 1 :
0), __extension__ ({ if (p2->state == 2 || p2->state ==
6) ; else __assert_fail ("p2->state == NR_ICE_PAIR_STATE_WAITING || p2->state == NR_ICE_PAIR_STATE_CANCELLED"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 1575, __extension__ __PRETTY_FUNCTION__); }))
1575 p2->state == NR_ICE_PAIR_STATE_CANCELLED)((void) sizeof ((p2->state == 2 || p2->state == 6) ? 1 :
0), __extension__ ({ if (p2->state == 2 || p2->state ==
6) ; else __assert_fail ("p2->state == NR_ICE_PAIR_STATE_WAITING || p2->state == NR_ICE_PAIR_STATE_CANCELLED"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 1575, __extension__ __PRETTY_FUNCTION__); }))
;
1576 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s in trigger check queue because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword);
1577
1578 nr_ice_candidate_pair_cancel(pair->pctx,p2,0);
1579 }
1580
1581 p2=TAILQ_NEXT(p2,triggered_check_queue_entry)((p2)->triggered_check_queue_entry.tqe_next);
1582 }
1583 p2=TAILQ_FIRST(&comp->stream->check_list)((&comp->stream->check_list)->tqh_first);
1584 while(p2){
1585 if((p2 != pair) &&
1586 (p2->remote->component->component_id == comp->component_id) &&
1587 ((p2->state == NR_ICE_PAIR_STATE_FROZEN1) ||
1588 (p2->state == NR_ICE_PAIR_STATE_WAITING2)) &&
1589 !(p2->peer_nominated && (p2->priority > pair->priority))) {
1590 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword);
1591
1592 nr_ice_candidate_pair_cancel(pair->pctx,p2,0);
1593 }
1594
1595 p2=TAILQ_NEXT(p2,check_queue_entry)((p2)->check_queue_entry.tqe_next);
1596 }
1597 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): cancelling done",comp->stream->pctx->label,comp->stream->label,comp->component_id);
1598
1599 if(r=nr_ice_component_setup_consent(comp))
1600 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1601
1602 nr_ice_media_stream_component_nominated(comp->stream,comp);
1603
1604 _status=0;
1605 abort:
1606 return(_status);
1607 }
1608
1609static int nr_ice_component_have_all_pairs_failed(nr_ice_component *comp)
1610 {
1611 nr_ice_cand_pair *p2;
1612
1613 p2=TAILQ_FIRST(&comp->stream->check_list)((&comp->stream->check_list)->tqh_first);
1614 while(p2){
1615 if(comp->component_id==p2->local->component_id){
1616 switch(p2->state){
1617 case NR_ICE_PAIR_STATE_FROZEN1:
1618 case NR_ICE_PAIR_STATE_WAITING2:
1619 case NR_ICE_PAIR_STATE_IN_PROGRESS3:
1620 case NR_ICE_PAIR_STATE_SUCCEEDED5:
1621 return(0);
1622 case NR_ICE_PAIR_STATE_FAILED4:
1623 case NR_ICE_PAIR_STATE_CANCELLED6:
1624 /* states that will never be recovered from */
1625 break;
1626 default:
1627 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_component.c"
, 1627, __extension__ __PRETTY_FUNCTION__); }))
;
1628 break;
1629 }
1630 }
1631
1632 p2=TAILQ_NEXT(p2,check_queue_entry)((p2)->check_queue_entry.tqe_next);
1633 }
1634
1635 return(1);
1636 }
1637
1638void nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
1639 {
1640 nr_ice_component_check_if_failed(comp);
1641 }
1642
1643void nr_ice_component_check_if_failed(nr_ice_component *comp)
1644 {
1645 if (comp->state == NR_ICE_COMPONENT_RUNNING1) {
1646 /* Don't do anything to streams that aren't currently running */
1647 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): Checking whether component needs to be marked failed.",comp->stream->pctx->label,comp->stream->label,comp->component_id);
1648
1649 if (!comp->stream->pctx->trickle_grace_period_timer &&
1650 nr_ice_component_have_all_pairs_failed(comp)) {
1651 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): All pairs are failed, and grace period has elapsed. Marking component as failed.",comp->stream->pctx->label,comp->stream->label,comp->component_id);
1652 nr_ice_media_stream_component_failed(comp->stream,comp);
1653 }
1654 }
1655 }
1656
1657int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp)
1658 {
1659 nr_ice_cand_pair **pairs=0;
1660 int ct=0;
1661 nr_ice_cand_pair *pair;
1662 int r,_status;
1663
1664 /* Size the array */
1665 pair=TAILQ_FIRST(&comp->stream->check_list)((&comp->stream->check_list)->tqh_first);
1666 while(pair){
1667 if (comp->component_id == pair->local->component_id)
1668 ct++;
1669
1670 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
1671 }
1672
1673 /* Make and fill the array */
1674 if(!(pairs=RCALLOC(sizeof(nr_ice_cand_pair *)*ct)r_calloc(0,1,sizeof(nr_ice_cand_pair *)*ct)))
1675 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1676
1677 ct=0;
1678 pair=TAILQ_FIRST(&comp->stream->check_list)((&comp->stream->check_list)->tqh_first);
1679 while(pair){
1680 if (comp->component_id == pair->local->component_id)
1681 pairs[ct++]=pair;
1682
1683 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
1684 }
1685
1686 if (pctx->handler) {
1687 if(r=pctx->handler->vtbl->select_pair(pctx->handler->obj,
1688 comp->stream,comp->component_id,pairs,ct))
1689 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1690 }
1691
1692 _status=0;
1693 abort:
1694 RFREE(pairs)if(pairs) r_free(pairs);
1695 return(_status);
1696 }
1697
1698
1699/* Close the underlying sockets for everything but the nominated candidate */
1700int nr_ice_component_finalize(nr_ice_component *lcomp, nr_ice_component *rcomp)
1701 {
1702 nr_ice_socket *isock=0;
1703 nr_ice_socket *s1,*s2;
1704
1705 if(rcomp->state==NR_ICE_COMPONENT_NOMINATED2){
1706 assert(rcomp->active == rcomp->nominated)((void) sizeof ((rcomp->active == rcomp->nominated) ? 1
: 0), __extension__ ({ if (rcomp->active == rcomp->nominated
) ; else __assert_fail ("rcomp->active == rcomp->nominated"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_component.c"
, 1706, __extension__ __PRETTY_FUNCTION__); }))
;
1707 isock=rcomp->nominated->local->isock;
1708 }
1709
1710 STAILQ_FOREACH_SAFE(s1, &lcomp->sockets, entry, s2)for ((s1) = (((&lcomp->sockets))->stqh_first); (s1)
&& ((s2) = (((s1))->entry.stqe_next), 1); (s1) = (
s2))
{
1711 if(s1!=isock){
1712 STAILQ_REMOVE(&lcomp->sockets,s1,nr_ice_socket_,entry)do { if ((((&lcomp->sockets))->stqh_first) == (s1))
{ do { if ((((((&lcomp->sockets)))->stqh_first) = (
(((((&lcomp->sockets)))->stqh_first))->entry.stqe_next
)) == ((void*)0)) ((&lcomp->sockets))->stqh_last = &
((((&lcomp->sockets)))->stqh_first); } while (0); }
else { struct nr_ice_socket_ *curelm = (((&lcomp->sockets
))->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)) (&lcomp->sockets)->stqh_last
= &(((curelm))->entry.stqe_next); } } while (0)
;
1713 nr_ice_socket_destroy(&s1);
1714 }
1715 }
1716
1717 return(0);
1718 }
1719
1720
1721int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair)
1722 {
1723 int _status;
1724
1725 /* Pairs for peer reflexive are marked SUCCEEDED immediately */
1726 if (pair->state != NR_ICE_PAIR_STATE_FROZEN1 &&
1727 pair->state != NR_ICE_PAIR_STATE_SUCCEEDED5){
1728 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_component.c"
, 1728, __extension__ __PRETTY_FUNCTION__); }))
;
1729 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1730 }
1731
1732 /* We do not throw an error after this, because we've inserted the pair. */
1733 nr_ice_candidate_pair_insert(&pair->remote->stream->check_list,pair);
1734
1735 /* Make sure the check timer is running, if the stream was previously
1736 * started. We will not start streams just because a pair was created,
1737 * unless it is the first pair to be created across all streams. */
1738 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND-PAIR(%s): Ensure that check timer is running for new pair %s.",pair->remote->stream->pctx->label, pair->codeword, pair->as_string);
1739
1740 if(pair->remote->stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE3 ||
1741 (pair->remote->stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN2 &&
1742 !pair->remote->stream->pctx->checks_started)){
1743 if(nr_ice_media_stream_start_checks(pair->remote->stream->pctx, pair->remote->stream)) {
1744 r_log(LOG_ICE,LOG_WARNING4,"ICE-PEER(%s)/CAND-PAIR(%s): Could not restart checks for new pair %s.",pair->remote->stream->pctx->label, pair->codeword, pair->as_string);
1745 }
1746 }
1747
1748 _status=0;
1749 abort:
1750 if (_status) {
1751 nr_ice_candidate_pair_destroy(&pair);
1752 }
1753 return(_status);
1754 }
1755
1756int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candidate **candp, int ip_version)
1757 {
1758 int _status;
1759 nr_ice_candidate *cand;
1760 nr_ice_candidate *best_cand = NULL((void*)0);
1761
1762 /* We have the component. Now find the "best" candidate, making
1763 use of the fact that more "reliable" candidate types have
1764 higher numbers. So, we sort by type and then priority within
1765 type
1766 */
1767 cand=TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
1768 while(cand){
1769 if (!nr_ice_ctx_hide_candidate(comp->ctx, cand) &&
1770 cand->addr.ip_version == ip_version) {
1771 if (!best_cand) {
1772 best_cand = cand;
1773 }
1774 else if (best_cand->type < cand->type) {
1775 best_cand = cand;
1776 } else if (best_cand->type == cand->type &&
1777 best_cand->priority < cand->priority) {
1778 best_cand = cand;
1779 }
1780 }
1781
1782 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
1783 }
1784
1785 /* No candidates */
1786 if (!best_cand)
1787 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1788
1789 *candp = best_cand;
1790
1791 _status=0;
1792 abort:
1793 return(_status);
1794
1795 }
1796
1797
1798void nr_ice_component_dump_state(nr_ice_component *comp, int log_level)
1799 {
1800 nr_ice_candidate *cand;
1801
1802 if (comp->local_component) {
1803 r_log(LOG_ICE,log_level,"ICE(%s)/ICE-STREAM(%s): Remote component %d in state %d - dumping candidates",comp->ctx->label,comp->stream->label,comp->component_id,comp->state);
1804 } else {
1805 r_log(LOG_ICE,log_level,"ICE(%s)/ICE-STREAM(%s): Local component %d - dumping candidates",comp->ctx->label,comp->stream->label,comp->component_id);
1806 }
1807
1808 cand=TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
1809 while(cand){
1810 r_log(LOG_ICE,log_level,"ICE(%s)/ICE-STREAM(%s)/CAND(%s): %s",comp->ctx->label,comp->stream->label,cand->codeword,cand->label);
1811 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
1812 }
1813 }
1814