Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c
Warning:line 163, column 12
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 <registry.h>
36#include <nr_api.h>
37#include "ice_ctx.h"
38#include "ice_peer_ctx.h"
39#include "ice_media_stream.h"
40#include "ice_util.h"
41#include "nr_crypto.h"
42#include "async_timer.h"
43#include "ice_reg.h"
44
45static void nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct);
46static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate, int trickled, const char *mdns_addr);
47static void nr_ice_peer_ctx_start_trickle_timer(nr_ice_peer_ctx *pctx);
48
49int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
50 {
51 int r,_status;
52 nr_ice_peer_ctx *pctx=0;
53
54 if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))r_calloc(0,1,sizeof(nr_ice_peer_ctx))))
55 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
56
57 pctx->state = NR_ICE_PEER_STATE_UNPAIRED1;
58
59 if(!(pctx->label=r_strdup(label)))
60 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
61
62 pctx->ctx=ctx;
63 pctx->handler=handler;
64
65 /* Decide controlling vs. controlled */
66 if(ctx->flags & NR_ICE_CTX_FLAGS_LITE(1<<1)){
67 pctx->controlling=0;
68 } else {
69 pctx->controlling=1;
70 }
71 if(r=nr_crypto_random_bytes((UCHAR *)&pctx->tiebreaker,8)nr_crypto_vtbl->random_bytes((UCHAR *)&pctx->tiebreaker
,8)
)
72 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
73
74 STAILQ_INIT(&pctx->peer_streams)do { (((&pctx->peer_streams))->stqh_first) = ((void
*)0); (&pctx->peer_streams)->stqh_last = &(((&
pctx->peer_streams))->stqh_first); } while (0)
;
75
76 STAILQ_INSERT_TAIL(&ctx->peers,pctx,entry)do { (((pctx))->entry.stqe_next) = ((void*)0); *(&ctx->
peers)->stqh_last = (pctx); (&ctx->peers)->stqh_last
= &(((pctx))->entry.stqe_next); } while (0)
;
77
78 *pctxp=pctx;
79
80 _status = 0;
81 abort:
82 if(_status){
83 nr_ice_peer_ctx_destroy(&pctx);
84 }
85 return(_status);
86 }
87
88
89
90int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
91 {
92 nr_ice_media_stream *pstream=0;
93 nr_ice_component *comp,*comp2;
94 char *lufrag,*rufrag;
95 char *lpwd,*rpwd;
96 int r,_status;
97
98 /*
99 Note: use component_ct from our own stream since components other
100 than this offered by the other side are unusable */
101 if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,"","",stream->component_ct,&pstream))
102 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
103
104 /* Match up the local and remote components */
105 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
106 comp2=STAILQ_FIRST(&pstream->components)((&pstream->components)->stqh_first);
107 while(comp){
108 comp2->local_component=comp;
109
110 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
111 comp2=STAILQ_NEXT(comp2,entry)((comp2)->entry.stqe_next);
112 }
113
114 pstream->local_stream=stream;
115 pstream->pctx=pctx;
116
117 nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct);
118
119 /* Now that we have the ufrag and password, compute all the username/password
120 pairs */
121 lufrag=stream->ufrag;
122 lpwd=stream->pwd;
123 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_peer_ctx.c"
, 123, __extension__ __PRETTY_FUNCTION__); }))
;
124 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_peer_ctx.c"
, 124, __extension__ __PRETTY_FUNCTION__); }))
;
125 rufrag=pstream->ufrag;
126 rpwd=pstream->pwd;
127 if (!rufrag || !rpwd)
128 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
129
130 if(r=nr_concat_strings(&pstream->r2l_user,lufrag,":",rufrag,NULL((void*)0)))
131 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
132 if(r=nr_concat_strings(&pstream->l2r_user,rufrag,":",lufrag,NULL((void*)0)))
133 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
134 if(r=r_data_make(&pstream->r2l_pass, (UCHAR *)lpwd, strlen(lpwd)))
135 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
136 if(r=r_data_make(&pstream->l2r_pass, (UCHAR *)rpwd, strlen(rpwd)))
137 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
138
139 STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry)do { (((pstream))->entry.stqe_next) = ((void*)0); *(&pctx
->peer_streams)->stqh_last = (pstream); (&pctx->
peer_streams)->stqh_last = &(((pstream))->entry.stqe_next
); } while (0)
;
140 pstream=0;
141
142 _status=0;
143 abort:
144 if (_status) {
145 nr_ice_media_stream_destroy(&pstream);
146 }
147 return(_status);
148 }
149
150static void nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct)
151 {
152 int r;
153 int i;
154
155 for(i=0;i<attr_ct;i++){
156 if(!strncmp(attrs[i],"ice-",4)){
157 if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i])) {
158 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): peer (%s) specified bogus ICE attribute",pctx->ctx->label,pctx->label);
159 continue;
160 }
161 }
162 else if (!strncmp(attrs[i],"candidate",9)){
163 if(r=nr_ice_ctx_parse_candidate(pctx,pstream,attrs[i],0,0)) {
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
164 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): peer (%s) specified bogus candidate",pctx->ctx->label,pctx->label);
165 continue;
166 }
167 }
168 else {
169 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): peer (%s) specified bogus attribute: %s",pctx->ctx->label,pctx->label,attrs[i]);
170 }
171 }
172
173 /* Doesn't fail because we just skip errors */
174 }
175
176static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate, int trickled, const char *mdns_addr)
177 {
178 nr_ice_candidate *cand=0;
179 nr_ice_component *comp;
180 int j;
181 int r, _status;
182
183 if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,candidate,pstream,&cand))
184 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
185
186 /* set the trickled flag on the candidate */
187 cand->trickled = trickled;
188
189 if (mdns_addr) {
190 cand->mdns_addr = r_strdup(mdns_addr);
191 if (!cand->mdns_addr) {
192 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
193 }
194 }
195
196 /* Not the fastest way to find a component, but it's what we got */
197 j=1;
198 for(comp=STAILQ_FIRST(&pstream->components)((&pstream->components)->stqh_first);comp;comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next)){
199 if(j==cand->component_id)
200 break;
201
202 j++;
203 }
204
205 if(!comp){
206 /* Very common for the answerer when it uses rtcp-mux */
207 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): peer (%s) no such component for candidate %s",pctx->ctx->label,pctx->label, candidate);
208 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
209 }
210
211 if (comp->state == NR_ICE_COMPONENT_DISABLED4) {
212 r_log(LOG_ICE,LOG_WARNING4,"Peer offered candidate for disabled remote component: %s", candidate);
213 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
214 }
215 if (comp->local_component->state == NR_ICE_COMPONENT_DISABLED4) {
216 r_log(LOG_ICE,LOG_WARNING4,"Peer offered candidate for disabled local component: %s", candidate);
217 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
218 }
219
220 cand->component=comp;
221
222 TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp)do { (((cand))->entry_comp.tqe_next) = ((void*)0); (cand)->
entry_comp.tqe_prev = (&comp->candidates)->tqh_last
; *(&comp->candidates)->tqh_last = (cand); (&comp
->candidates)->tqh_last = &(((cand))->entry_comp
.tqe_next); ; ; } while (0)
;
223
224 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s)/CAND(%s): creating peer candidate",
225 pctx->label,cand->label);
226
227 _status=0;
228 abort:
229 if (_status) {
230 nr_ice_candidate_destroy(&cand);
231 }
232 return(_status);
233 }
234
235int nr_ice_peer_ctx_find_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream **pstreamp)
236 {
237 int _status;
238 nr_ice_media_stream *pstream;
239
240 /* Because we don't have forward pointers, iterate through all the
241 peer streams to find one that matches us */
242 pstream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
243
244 if(!pstream) {
245 /* No peer streams at all, presumably because they do not exist yet.
246 * Don't log a warning here. */
247 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
248 }
249
250 while(pstream) {
251 if (pstream->local_stream == stream)
252 break;
253
254 pstream = STAILQ_NEXT(pstream, entry)((pstream)->entry.stqe_next);
255 }
256
257 if (!pstream) {
258 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
259 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
260 }
261
262 *pstreamp = pstream;
263
264 _status=0;
265 abort:
266 return(_status);
267 }
268
269int nr_ice_peer_ctx_remove_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream **pstreamp)
270 {
271 int r,_status;
272
273 STAILQ_REMOVE(&pctx->peer_streams,*pstreamp,nr_ice_media_stream_,entry)do { if ((((&pctx->peer_streams))->stqh_first) == (
*pstreamp)) { do { if ((((((&pctx->peer_streams)))->
stqh_first) = ((((((&pctx->peer_streams)))->stqh_first
))->entry.stqe_next)) == ((void*)0)) ((&pctx->peer_streams
))->stqh_last = &((((&pctx->peer_streams)))->
stqh_first); } while (0); } else { struct nr_ice_media_stream_
*curelm = (((&pctx->peer_streams))->stqh_first); while
(((curelm)->entry.stqe_next) != (*pstreamp)) curelm = ((curelm
)->entry.stqe_next); if ((((curelm)->entry.stqe_next) =
((((curelm)->entry.stqe_next))->entry.stqe_next)) == (
(void*)0)) (&pctx->peer_streams)->stqh_last = &
(((curelm))->entry.stqe_next); } } while (0)
;
274
275 if(r=nr_ice_media_stream_destroy(pstreamp)) {
276 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
277 }
278
279 _status=0;
280 abort:
281 return(_status);
282 }
283
284int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate, const char *mdns_addr)
285 {
286 nr_ice_media_stream *pstream;
287 int r,_status;
288 int needs_pairing = 0;
289
290 if (stream->obsolete) {
291 return 0;
292 }
293
294 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): peer (%s) parsing trickle ICE candidate %s",pctx->ctx->label,pctx->label,candidate);
295 r = nr_ice_peer_ctx_find_pstream(pctx, stream, &pstream);
296 if (r)
297 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
298
299 switch(pstream->ice_state) {
300 case NR_ICE_MEDIA_STREAM_UNPAIRED1:
301 break;
302 case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN2:
303 case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE3:
304 needs_pairing = 1;
305 break;
306 default:
307 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s), stream(%s) tried to trickle ICE in inappropriate state %d",pctx->ctx->label,pctx->label,stream->label,pstream->ice_state);
308 ABORT(R_ALREADY)do { int _r=4; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
309 break;
310 }
311
312 if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate,1,mdns_addr)){
313 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
314 }
315
316 /* If ICE is running (i.e., we are in FROZEN or ACTIVE states)
317 then we need to pair this new candidate. For now we
318 just re-pair the stream which is inefficient but still
319 fine because we suppress duplicate pairing */
320 if (needs_pairing) {
321 /* Start the remote trickle grace timeout if it hasn't been started by
322 another trickled candidate or from the SDP. */
323 if (!pctx->trickle_grace_period_timer) {
324 nr_ice_peer_ctx_start_trickle_timer(pctx);
325 }
326
327 if(r=nr_ice_media_stream_pair_candidates(pctx, stream, pstream)) {
328 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s), stream(%s) failed to pair trickle ICE candidates",pctx->ctx->label,pctx->label,stream->label);
329 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
330 }
331
332 /* Start checks if this stream is not checking yet or if it has checked
333 all the available candidates but not had a completed check for all
334 components.
335
336 Note that this is not compliant with RFC 5245, but consistent with
337 the libjingle trickle ICE behavior. Note that we will not restart
338 checks if either (a) the stream has failed or (b) all components
339 have a successful pair because the switch statement above jumps
340 will in both states.
341
342 TODO(ekr@rtfm.com): restart checks.
343 TODO(ekr@rtfm.com): update when the trickle ICE RFC is published
344 */
345 if (!pstream->timer) {
346 if(r=nr_ice_media_stream_start_checks(pctx, pstream)) {
347 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s), stream(%s) failed to start checks",pctx->ctx->label,pctx->label,stream->label);
348 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
349 }
350 }
351 }
352
353 _status=0;
354 abort:
355 return(_status);
356
357 }
358
359
360static void nr_ice_peer_ctx_trickle_wait_cb(NR_SOCKET s, int how, void *cb_arg)
361 {
362 nr_ice_peer_ctx *pctx=cb_arg;
363 nr_ice_media_stream *stream;
364 nr_ice_component *comp;
365
366 pctx->trickle_grace_period_timer=0;
367
368 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): peer (%s) Trickle grace period is over; marking every component with only failed pairs as failed.",pctx->ctx->label,pctx->label);
369
370 stream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
371 while(stream){
372 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
373 while(comp){
374 nr_ice_component_check_if_failed(comp);
375 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
376 }
377 stream=STAILQ_NEXT(stream,entry)((stream)->entry.stqe_next);
378 }
379 }
380
381static void nr_ice_peer_ctx_start_trickle_timer(nr_ice_peer_ctx *pctx)
382 {
383 UINT4 grace_period_timeout=0;
384
385 if(pctx->trickle_grace_period_timer) {
386 NR_async_timer_cancel(pctx->trickle_grace_period_timer);
387 pctx->trickle_grace_period_timer=0;
388 }
389
390 NR_reg_get_uint4(NR_ICE_REG_TRICKLE_GRACE_PERIOD"ice.trickle_grace_period",&grace_period_timeout);
391
392 if (grace_period_timeout) {
393 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): peer (%s) starting grace period timer for %u ms",pctx->ctx->label,pctx->label, grace_period_timeout);
394 /* If we're doing trickle, we need to allow a grace period for new
395 * trickle candidates to arrive in case the pairs we have fail quickly. */
396 NR_ASYNC_TIMER_SET(grace_period_timeout,nr_ice_peer_ctx_trickle_wait_cb,pctx,&pctx->trickle_grace_period_timer)NR_async_timer_set(grace_period_timeout,nr_ice_peer_ctx_trickle_wait_cb
,pctx,(char *)__FUNCTION__,396,&pctx->trickle_grace_period_timer
)
;
397 }
398 }
399
400int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
401 {
402 nr_ice_media_stream *stream;
403 int r,_status;
404
405 if(pctx->peer_lite && !pctx->controlling) {
406 if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_LITE(1<<1)){
407 r_log(LOG_ICE,LOG_ERR3,"Both sides are ICE-Lite");
408 ABORT(R_BAD_DATA)do { int _r=7; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
409 }
410 nr_ice_peer_ctx_switch_controlling_role(pctx);
411 }
412
413 r_log(LOG_ICE,LOG_DEBUG7,"ICE(%s): peer (%s) pairing candidates",pctx->ctx->label,pctx->label);
414
415 if(STAILQ_EMPTY(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first == ((void*)0))) {
416 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s) received no media stream attributes",pctx->ctx->label,pctx->label);
417 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
418 }
419
420 /* Set this first; if we fail partway through, we do not want to end
421 * up in UNPAIRED after creating some pairs. */
422 pctx->state = NR_ICE_PEER_STATE_PAIRED2;
423
424 stream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
425 while(stream){
426 if(!stream->local_stream->obsolete) {
427 if(r=nr_ice_media_stream_pair_candidates(pctx, stream->local_stream,
428 stream))
429 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
430 }
431
432 stream=STAILQ_NEXT(stream,entry)((stream)->entry.stqe_next);
433 }
434
435
436 _status=0;
437 abort:
438 return(_status);
439 }
440
441
442int nr_ice_peer_ctx_pair_new_trickle_candidate(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx, nr_ice_candidate *cand)
443 {
444 int r, _status;
445 nr_ice_media_stream *pstream;
446
447 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s) pairing local trickle ICE candidate %s",pctx->ctx->label,pctx->label,cand->label);
448 if ((r = nr_ice_peer_ctx_find_pstream(pctx, cand->stream, &pstream)))
449 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
450
451 /* Start the remote trickle grace timeout if it hasn't been started
452 already. */
453 if (!pctx->trickle_grace_period_timer) {
454 nr_ice_peer_ctx_start_trickle_timer(pctx);
455 }
456
457 if ((r = nr_ice_media_stream_pair_new_trickle_candidate(pctx, pstream, cand)))
458 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
459
460 _status=0;
461 abort:
462 return _status;
463 }
464
465int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id)
466 {
467 int r, _status;
468 nr_ice_media_stream *pstream;
469 nr_ice_component *component;
470
471 if ((r=nr_ice_peer_ctx_find_pstream(pctx, lstream, &pstream)))
472 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
473
474 /* We shouldn't be calling this after we have started pairing */
475 if (pstream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED1)
476 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
477
478 if ((r=nr_ice_media_stream_find_component(pstream, component_id,
479 &component)))
480 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
481
482 component->state = NR_ICE_COMPONENT_DISABLED4;
483
484 _status=0;
485 abort:
486 return(_status);
487 }
488
489 void nr_ice_peer_ctx_destroy(nr_ice_peer_ctx** pctxp) {
490 if (!pctxp || !*pctxp) return;
491
492 nr_ice_peer_ctx* pctx = *pctxp;
493 nr_ice_media_stream *str1,*str2;
494
495 /* Stop calling the handler */
496 pctx->handler = 0;
497
498 NR_async_timer_cancel(pctx->connected_cb_timer);
499 RFREE(pctx->label)if(pctx->label) r_free(pctx->label);
500
501 STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2)for ((str1) = (((&pctx->peer_streams))->stqh_first)
; (str1) && ((str2) = (((str1))->entry.stqe_next),
1); (str1) = (str2))
{
502 STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry)do { if ((((&pctx->peer_streams))->stqh_first) == (
str1)) { do { if ((((((&pctx->peer_streams)))->stqh_first
) = ((((((&pctx->peer_streams)))->stqh_first))->
entry.stqe_next)) == ((void*)0)) ((&pctx->peer_streams
))->stqh_last = &((((&pctx->peer_streams)))->
stqh_first); } while (0); } else { struct nr_ice_media_stream_
*curelm = (((&pctx->peer_streams))->stqh_first); while
(((curelm)->entry.stqe_next) != (str1)) curelm = ((curelm
)->entry.stqe_next); if ((((curelm)->entry.stqe_next) =
((((curelm)->entry.stqe_next))->entry.stqe_next)) == (
(void*)0)) (&pctx->peer_streams)->stqh_last = &
(((curelm))->entry.stqe_next); } } while (0)
;
503 nr_ice_media_stream_destroy(&str1);
504 }
505 assert(pctx->ctx)((void) sizeof ((pctx->ctx) ? 1 : 0), __extension__ ({ if (
pctx->ctx) ; else __assert_fail ("pctx->ctx", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c"
, 505, __extension__ __PRETTY_FUNCTION__); }))
;
506 if (pctx->ctx)
507 STAILQ_REMOVE(&pctx->ctx->peers, pctx, nr_ice_peer_ctx_, entry)do { if ((((&pctx->ctx->peers))->stqh_first) == (
pctx)) { do { if ((((((&pctx->ctx->peers)))->stqh_first
) = ((((((&pctx->ctx->peers)))->stqh_first))->
entry.stqe_next)) == ((void*)0)) ((&pctx->ctx->peers
))->stqh_last = &((((&pctx->ctx->peers)))->
stqh_first); } while (0); } else { struct nr_ice_peer_ctx_ *curelm
= (((&pctx->ctx->peers))->stqh_first); while ((
(curelm)->entry.stqe_next) != (pctx)) curelm = ((curelm)->
entry.stqe_next); if ((((curelm)->entry.stqe_next) = ((((curelm
)->entry.stqe_next))->entry.stqe_next)) == ((void*)0)) (
&pctx->ctx->peers)->stqh_last = &(((curelm))
->entry.stqe_next); } } while (0)
;
508
509 if(pctx->trickle_grace_period_timer) {
510 NR_async_timer_cancel(pctx->trickle_grace_period_timer);
511 pctx->trickle_grace_period_timer=0;
512 }
513
514 RFREE(pctx)if(pctx) r_free(pctx);
515
516 *pctxp=0;
517 }
518
519/* Start the checks for the first media stream (S 5.7)
520 The rest remain FROZEN */
521int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx)
522 {
523 return nr_ice_peer_ctx_start_checks2(pctx, 0);
524 }
525
526/* Start checks for some media stream.
527
528 If allow_non_first == 0, then we only look at the first stream,
529 which is 5245-complaint.
530
531 If allow_non_first == 1 then we find the first non-empty stream
532 This is not compliant with RFC 5245 but is necessary to make trickle ICE
533 work plausibly
534*/
535int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
536 {
537 int r,_status;
538 nr_ice_media_stream *stream;
539 int started = 0;
540
541 /* Ensure that grace period timer is running. We might cancel this if we
542 * didn't actually start any pairs. */
543 nr_ice_peer_ctx_start_trickle_timer(pctx);
544
545 /* Might have added some streams */
546 pctx->reported_connected = 0;
547 NR_async_timer_cancel(pctx->connected_cb_timer);
548 pctx->connected_cb_timer = 0;
549 pctx->checks_started = 0;
550
551 nr_ice_peer_ctx_check_if_connected(pctx);
552
553 if (pctx->reported_connected) {
554 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s) in %s all streams were done",pctx->ctx->label,pctx->label,__FUNCTION__);
555 return (0);
556 }
557
558 stream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
559 if(!stream)
560 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
561
562 while (stream) {
563 if(!stream->local_stream->obsolete) {
564 assert(stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED)((void) sizeof ((stream->ice_state != 1) ? 1 : 0), __extension__
({ if (stream->ice_state != 1) ; else __assert_fail ("stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c"
, 564, __extension__ __PRETTY_FUNCTION__); }))
;
565
566 if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN2) {
567 if(!TAILQ_EMPTY(&stream->check_list)((&stream->check_list)->tqh_first == ((void*)0)))
568 break;
569
570 if(!allow_non_first){
571 /* This test applies if:
572
573 1. allow_non_first is 0 (i.e., non-trickle ICE)
574 2. the first stream has an empty check list.
575
576 But in the non-trickle ICE case, the other side should have provided
577 some candidates or ICE is pretty much not going to work and we're
578 just going to fail. Hence R_FAILED as opposed to R_NOT_FOUND and
579 immediate termination here.
580 */
581 r_log(LOG_ICE,LOG_ERR3,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
582 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
583 }
584 }
585 }
586
587 stream=STAILQ_NEXT(stream, entry)((stream)->entry.stqe_next);
588 }
589
590 if (!stream) {
591 /*
592 We fail above if we aren't doing trickle, and this is not all that
593 unusual in the trickle case.
594 */
595 r_log(LOG_ICE,LOG_NOTICE5,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
596 }
597 else if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN2) {
598 if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
599 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
600 if(r=nr_ice_media_stream_start_checks(pctx,stream))
601 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
602 ++started;
603 }
604
605 stream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
606 while (stream) {
607 int serviced = 0;
608 if (r=nr_ice_media_stream_service_pre_answer_requests(pctx, stream->local_stream, stream, &serviced))
609 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
610
611 if (serviced) {
612 ++started;
613 }
614 else {
615 r_log(LOG_ICE,LOG_NOTICE5,"ICE(%s): peer (%s) no streams with pre-answer requests",pctx->ctx->label,pctx->label);
616 }
617
618
619 stream=STAILQ_NEXT(stream, entry)((stream)->entry.stqe_next);
620 }
621
622 if (!started && pctx->ctx->uninitialized_candidates) {
623 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): peer (%s) no checks to start, but gathering is not done yet, cancelling grace period timer",pctx->ctx->label,pctx->label);
624 /* Never mind on the grace period timer */
625 NR_async_timer_cancel(pctx->trickle_grace_period_timer);
626 pctx->trickle_grace_period_timer=0;
627 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
628 }
629
630 _status=0;
631 abort:
632 return(_status);
633 }
634
635void nr_ice_peer_ctx_stream_started_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
636 {
637 if (!pctx->checks_started) {
638 r_log(LOG_ICE,LOG_NOTICE5,"ICE(%s): peer (%s) is now checking",pctx->ctx->label,pctx->label);
639 pctx->checks_started = 1;
640 if (pctx->handler && pctx->handler->vtbl->ice_checking) {
641 pctx->handler->vtbl->ice_checking(pctx->handler->obj, pctx);
642 }
643 }
644 }
645
646void nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx, int log_level)
647 {
648 nr_ice_media_stream *stream;
649
650 r_log(LOG_ICE,log_level,"PEER %s STATE DUMP",pctx->label);
651 r_log(LOG_ICE,log_level,"==========================================");
652 stream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
653 while(stream){
654 nr_ice_media_stream_dump_state(pctx,stream,log_level);
655 }
656 r_log(LOG_ICE,log_level,"==========================================");
657 }
658
659void nr_ice_peer_ctx_refresh_consent_all_streams(nr_ice_peer_ctx *pctx)
660 {
661 nr_ice_media_stream *str;
662
663 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): refreshing consent on all streams",pctx->label);
664
665 str=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
666 while(str) {
667 nr_ice_media_stream_refresh_consent_all(str);
668 str=STAILQ_NEXT(str,entry)((str)->entry.stqe_next);
669 }
670 }
671
672void nr_ice_peer_ctx_disconnected(nr_ice_peer_ctx *pctx)
673 {
674 if (pctx->connected_cb_timer) {
675 /* Whoops, never mind */
676 NR_async_timer_cancel(pctx->connected_cb_timer);
677 pctx->connected_cb_timer = 0;
678 }
679
680 if (pctx->reported_connected &&
681 pctx->handler &&
682 pctx->handler->vtbl->ice_disconnected) {
683 pctx->handler->vtbl->ice_disconnected(pctx->handler->obj, pctx);
684
685 pctx->reported_connected = 0;
686 }
687 }
688
689void nr_ice_peer_ctx_disconnect_all_streams(nr_ice_peer_ctx *pctx)
690 {
691 nr_ice_media_stream *str;
692
693 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): disconnecting all streams",pctx->label);
694
695 str=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
696 while(str) {
697 nr_ice_media_stream_disconnect_all_components(str);
698
699 /* The first stream to be disconnected will cause the peer ctx to signal
700 the disconnect up. */
701 nr_ice_media_stream_set_disconnected(str, NR_ICE_MEDIA_STREAM_DISCONNECTED1);
702
703 str=STAILQ_NEXT(str,entry)((str)->entry.stqe_next);
704 }
705 }
706
707void nr_ice_peer_ctx_connected(nr_ice_peer_ctx *pctx)
708 {
709 /* Fire the handler callback to say we're done */
710 if (pctx->reported_connected &&
711 pctx->handler &&
712 pctx->handler->vtbl->ice_connected) {
713 pctx->handler->vtbl->ice_connected(pctx->handler->obj, pctx);
714 }
715 }
716
717static void nr_ice_peer_ctx_fire_connected(NR_SOCKET s, int how, void *cb_arg)
718 {
719 nr_ice_peer_ctx *pctx=cb_arg;
720
721 pctx->connected_cb_timer=0;
722
723 nr_ice_peer_ctx_connected(pctx);
724 }
725
726/* Examine all the streams to see if we're
727 maybe miraculously connected */
728void nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx)
729 {
730 nr_ice_media_stream *str;
731 int failed=0;
732 int succeeded=0;
733
734 str=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
735 while(str){
736 if (!str->local_stream->obsolete){
737 if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED4){
738 succeeded++;
739 }
740 else if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FAILED5){
741 failed++;
742 }
743 else{
744 break;
745 }
746 }
747 str=STAILQ_NEXT(str,entry)((str)->entry.stqe_next);
748 }
749
750 if(str)
751 return; /* Something isn't done */
752
753 /* OK, we're finished, one way or another */
754 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): all checks completed success=%d fail=%d",pctx->label,succeeded,failed);
755
756 /* Make sure grace period timer is cancelled */
757 if(pctx->trickle_grace_period_timer) {
758 r_log(LOG_ICE,LOG_INFO6,"ICE(%s): peer (%s) cancelling grace period timer",pctx->ctx->label,pctx->label);
759 NR_async_timer_cancel(pctx->trickle_grace_period_timer);
760 pctx->trickle_grace_period_timer=0;
761 }
762
763 /* Schedule a connected notification for the first connected event.
764 IMPORTANT: This is done in a callback because we expect destructors
765 of various kinds to be fired from here */
766 if (!pctx->reported_connected) {
767 pctx->reported_connected = 1;
768 assert(!pctx->connected_cb_timer)((void) sizeof ((!pctx->connected_cb_timer) ? 1 : 0), __extension__
({ if (!pctx->connected_cb_timer) ; else __assert_fail ("!pctx->connected_cb_timer"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c"
, 768, __extension__ __PRETTY_FUNCTION__); }))
;
769 NR_ASYNC_TIMER_SET(0,nr_ice_peer_ctx_fire_connected,pctx,&pctx->connected_cb_timer)NR_async_timer_set(0,nr_ice_peer_ctx_fire_connected,pctx,(char
*)__FUNCTION__,769,&pctx->connected_cb_timer)
;
770 }
771 }
772
773
774/* Given a component in the main ICE ctx, find the relevant component in
775 the peer_ctx */
776int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp)
777 {
778 nr_ice_media_stream *pstr;
779 int r,_status;
780
781 pstr=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
782 while(pstr){
783 if(pstr->local_stream==str)
784 break;
785
786 pstr=STAILQ_NEXT(pstr,entry)((pstr)->entry.stqe_next);
787 }
788 if(!pstr)
789 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
790
791 if(r=nr_ice_media_stream_find_component(pstr,component_id,compp))
792 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
793
794 _status=0;
795 abort:
796 return(_status);
797 }
798
799/*
800 This packet may be for us.
801
802 1. Find the matching peer component
803 2. Examine the packet source address to see if it matches
804 one of the peer candidates.
805 3. Fire the relevant callback handler if there is a match
806
807 Return 0 if match, R_REJECTED if no match, other errors
808 if we can't even find the component or something like that.
809*/
810
811int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
812 {
813 nr_ice_component *peer_comp;
814 nr_ice_candidate *cand;
815 int r,_status;
816
817 if(r=nr_ice_peer_ctx_find_component(pctx, comp->stream, comp->component_id,
818 &peer_comp))
819 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
820
821 /* OK, we've found the component, now look for matches */
822 cand=TAILQ_FIRST(&peer_comp->candidates)((&peer_comp->candidates)->tqh_first);
823 while(cand){
824 if(!nr_transport_addr_cmp(source_addr,&cand->addr,
825 NR_TRANSPORT_ADDR_CMP_MODE_ALL4))
826 break;
827
828 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
829 }
830
831 if(!cand)
832 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
833
834 // accumulate the received bytes for the active candidate pair
835 if (peer_comp->active) {
836 peer_comp->active->bytes_recvd += len;
837 gettimeofday(&peer_comp->active->last_recvd, 0);
838 }
839
840 /* OK, there's a match. Call the handler */
841
842 if (pctx->handler) {
843 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): Delivering data", pctx->label);
844
845 pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
846 pctx,comp->stream,comp->component_id,data,len);
847 }
848
849 _status=0;
850 abort:
851 return(_status);
852 }
853
854void nr_ice_peer_ctx_switch_controlling_role(nr_ice_peer_ctx *pctx)
855 {
856 int controlling = !(pctx->controlling);
857 if(pctx->controlling_conflict_resolved) {
858 r_log(LOG_ICE,LOG_WARNING4,"ICE(%s): peer (%s) %s called more than once; "
859 "this probably means the peer is confused. Not switching roles.",
860 pctx->ctx->label,pctx->label,__FUNCTION__);
861 return;
862 }
863
864 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): detected "
865 "role conflict. Switching to %s",
866 pctx->label,
867 controlling ? "controlling" : "controlled");
868
869 pctx->controlling = controlling;
870 pctx->controlling_conflict_resolved = 1;
871
872 if(pctx->state == NR_ICE_PEER_STATE_PAIRED2) {
873 /* We have formed candidate pairs. We need to inform them. */
874 nr_ice_media_stream *pstream=STAILQ_FIRST(&pctx->peer_streams)((&pctx->peer_streams)->stqh_first);
875 while(pstream) {
876 nr_ice_media_stream_role_change(pstream);
877 pstream = STAILQ_NEXT(pstream, entry)((pstream)->entry.stqe_next);
878 }
879 }
880 }
881