Bug Summary

File:root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c
Warning:line 307, column 9
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 <r_assoc.h>
37#include <async_timer.h>
38#include "ice_util.h"
39#include "ice_ctx.h"
40
41static char *nr_ice_media_stream_states[]={"INVALID",
42 "UNPAIRED","FROZEN","ACTIVE","CONNECTED","FAILED"
43};
44
45int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
46
47int nr_ice_media_stream_create(nr_ice_ctx *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp)
48 {
49 int r,_status;
50 nr_ice_media_stream *stream=0;
51 nr_ice_component *comp=0;
52 int i;
53
54 if(!(stream=RCALLOC(sizeof(nr_ice_media_stream))r_calloc(0,1,sizeof(nr_ice_media_stream))))
55 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
56
57 if(!(stream->label=r_strdup(label)))
58 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
59
60 if(!(stream->ufrag=r_strdup(ufrag)))
61 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
62
63 if(!(stream->pwd=r_strdup(pwd)))
64 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
65
66 stream->ctx=ctx;
67
68 STAILQ_INIT(&stream->components)do { (((&stream->components))->stqh_first) = ((void
*)0); (&stream->components)->stqh_last = &(((&
stream->components))->stqh_first); } while (0)
;
69 for(i=0;i<components;i++){
70 /* component-id must be > 0, so increment by 1 */
71 if(r=nr_ice_component_create(stream, i+1, &comp))
72 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
73
74 }
75
76 TAILQ_INIT(&stream->check_list)do { (((&stream->check_list))->tqh_first) = ((void*
)0); (&stream->check_list)->tqh_last = &(((&
stream->check_list))->tqh_first); ; } while (0)
;
77 TAILQ_INIT(&stream->trigger_check_queue)do { (((&stream->trigger_check_queue))->tqh_first) =
((void*)0); (&stream->trigger_check_queue)->tqh_last
= &(((&stream->trigger_check_queue))->tqh_first
); ; } while (0)
;
78
79 stream->disconnected = 0;
80 stream->component_ct=components;
81 stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED1;
82 stream->obsolete = 0;
83 stream->actually_started_checking = 0;
84 stream->r2l_user = 0;
85 stream->l2r_user = 0;
86 stream->flags = ctx->flags;
87 if(ctx->stun_server_ct_cfg) {
88 if(!(stream->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*(ctx->stun_server_ct_cfg))r_calloc(0,1,sizeof(nr_ice_stun_server)*(ctx->stun_server_ct_cfg
))
))
89 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
90
91 memcpy(stream->stun_servers,ctx->stun_servers_cfg,sizeof(nr_ice_stun_server)*(ctx->stun_server_ct_cfg));
92 stream->stun_server_ct = ctx->stun_server_ct_cfg;
93 }
94
95 if(ctx->turn_server_ct_cfg) {
96 if(!(stream->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*(ctx->turn_server_ct_cfg))r_calloc(0,1,sizeof(nr_ice_turn_server)*(ctx->turn_server_ct_cfg
))
))
97 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
98
99 for(int i = 0; i < ctx->turn_server_ct_cfg; ++i) {
100 nr_ice_turn_server *dst = &stream->turn_servers[i];
101 nr_ice_turn_server *src = &ctx->turn_servers_cfg[i];
102 memcpy(&dst->turn_server, &src->turn_server, sizeof(nr_ice_stun_server));
103 dst->username = r_strdup(src->username);
104 r_data_create(&dst->password, src->password->data, src->password->len);
105 }
106 stream->turn_server_ct = ctx->turn_server_ct_cfg;
107 }
108
109 r_log(LOG_ICE,LOG_DEBUG7,"ICE-STREAM(%s): flags %d",stream->label,stream->flags);
110 *streamp=stream;
111
112 _status=0;
113 abort:
114 if(_status){
115 nr_ice_media_stream_destroy(&stream);
116 }
117 return(_status);
118 }
119
120int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
121 {
122 nr_ice_media_stream *stream;
123 nr_ice_component *c1,*c2;
124 nr_ice_cand_pair *p1,*p2;
125 if(!streamp || !*streamp)
126 return(0);
127
128 stream=*streamp;
129 *streamp=0;
130
131 STAILQ_FOREACH_SAFE(c1, &stream->components, entry, c2)for ((c1) = (((&stream->components))->stqh_first); (
c1) && ((c2) = (((c1))->entry.stqe_next), 1); (c1)
= (c2))
{
132 STAILQ_REMOVE(&stream->components,c1,nr_ice_component_,entry)do { if ((((&stream->components))->stqh_first) == (
c1)) { do { if ((((((&stream->components)))->stqh_first
) = ((((((&stream->components)))->stqh_first))->
entry.stqe_next)) == ((void*)0)) ((&stream->components
))->stqh_last = &((((&stream->components)))->
stqh_first); } while (0); } else { struct nr_ice_component_ *
curelm = (((&stream->components))->stqh_first); while
(((curelm)->entry.stqe_next) != (c1)) curelm = ((curelm)->
entry.stqe_next); if ((((curelm)->entry.stqe_next) = ((((curelm
)->entry.stqe_next))->entry.stqe_next)) == ((void*)0)) (
&stream->components)->stqh_last = &(((curelm))->
entry.stqe_next); } } while (0)
;
133 nr_ice_component_destroy(&c1);
134 }
135
136 /* Note: all the entries from the trigger check queue are held in here as
137 * well, so we only clean up the super set. */
138 TAILQ_FOREACH_SAFE(p1, &stream->check_list, check_queue_entry, p2)for ((p1) = (((&stream->check_list))->tqh_first); (
p1) && ((p2) = (((p1))->check_queue_entry.tqe_next
), 1); (p1) = (p2))
{
139 TAILQ_REMOVE(&stream->check_list,p1,check_queue_entry)do { if (((((p1))->check_queue_entry.tqe_next)) != ((void*
)0)) (((p1))->check_queue_entry.tqe_next)->check_queue_entry
.tqe_prev = (p1)->check_queue_entry.tqe_prev; else { (&
stream->check_list)->tqh_last = (p1)->check_queue_entry
.tqe_prev; ; } *(p1)->check_queue_entry.tqe_prev = (((p1))
->check_queue_entry.tqe_next); ; ; ; } while (0)
;
140 nr_ice_candidate_pair_destroy(&p1);
141 }
142
143 RFREE(stream->label)if(stream->label) r_free(stream->label);
144
145 RFREE(stream->ufrag)if(stream->ufrag) r_free(stream->ufrag);
146 RFREE(stream->pwd)if(stream->pwd) r_free(stream->pwd);
147 RFREE(stream->r2l_user)if(stream->r2l_user) r_free(stream->r2l_user);
148 RFREE(stream->l2r_user)if(stream->l2r_user) r_free(stream->l2r_user);
149 r_data_zfree(&stream->r2l_pass);
150 r_data_zfree(&stream->l2r_pass);
151
152 RFREE(stream->stun_servers)if(stream->stun_servers) r_free(stream->stun_servers);
153 for (int i = 0; i < stream->turn_server_ct; i++) {
154 RFREE(stream->turn_servers[i].username)if(stream->turn_servers[i].username) r_free(stream->turn_servers
[i].username)
;
155 r_data_destroy(&stream->turn_servers[i].password);
156 }
157 RFREE(stream->turn_servers)if(stream->turn_servers) r_free(stream->turn_servers);
158
159 if(stream->timer)
160 NR_async_timer_cancel(stream->timer);
161
162 RFREE(stream)if(stream) r_free(stream);
163
164 return(0);
165 }
166
167int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream)
168 {
169 int r,_status;
170 nr_ice_component *comp;
171
172 assert(!stream->obsolete)((void) sizeof ((!stream->obsolete) ? 1 : 0), __extension__
({ if (!stream->obsolete) ; else __assert_fail ("!stream->obsolete"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c"
, 172, __extension__ __PRETTY_FUNCTION__); }))
;
173
174 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
175 while(comp){
176 if(r=nr_ice_component_initialize(ctx,comp))
177 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
178 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
179 }
180
181 if (!nr_ice_media_stream_is_done_gathering(stream) && ctx->gather_handler &&
182 ctx->gather_handler->vtbl->stream_gathering) {
183 ctx->gather_handler->vtbl->stream_gathering(ctx->gather_handler->obj,
184 stream);
185 }
186
187 _status=0;
188 abort:
189 if (_status) {
190 if (ctx->gather_handler && ctx->gather_handler->vtbl->stream_gathered) {
191 ctx->gather_handler->vtbl->stream_gathered(ctx->gather_handler->obj,
192 stream);
193 }
194 }
195 return(_status);
196 }
197
198
199int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp)
200 {
201 int attrct=2;
202 nr_ice_component *comp;
203 char **attrs=0;
204 int index=0;
205 nr_ice_candidate *cand;
206 int r,_status;
207 char *tmp=0;
208
209 *attrctp=0;
210
211 /* First find out how many attributes we need */
212 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
213 while(comp){
214 if (comp->state != NR_ICE_COMPONENT_DISABLED4) {
215 cand = TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
216 while(cand){
217 if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
218 ++attrct;
219 }
220
221 cand = TAILQ_NEXT(cand, entry_comp)((cand)->entry_comp.tqe_next);
222 }
223 }
224 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
225 }
226
227 /* Make the array we'll need */
228 if(!(attrs=RCALLOC(sizeof(char *)*attrct)r_calloc(0,1,sizeof(char *)*attrct)))
229 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
230 for(index=0;index<attrct;index++){
231 if(!(attrs[index]=RMALLOC(NR_ICE_MAX_ATTRIBUTE_SIZE)r_malloc(0,256)))
232 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
233 }
234
235 index=0;
236 /* Now format the attributes */
237 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
238 while(comp){
239 if (comp->state != NR_ICE_COMPONENT_DISABLED4) {
240 nr_ice_candidate *cand;
241
242 cand=TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
243 while(cand){
244 if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
245 assert(index < attrct)((void) sizeof ((index < attrct) ? 1 : 0), __extension__ (
{ if (index < attrct) ; else __assert_fail ("index < attrct"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c"
, 245, __extension__ __PRETTY_FUNCTION__); }))
;
246
247 if (index >= attrct)
248 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
249
250 if(r=nr_ice_format_candidate_attribute(cand, attrs[index],NR_ICE_MAX_ATTRIBUTE_SIZE256, 0))
251 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
252
253 index++;
254 }
255
256 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
257 }
258 }
259 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
260 }
261
262 /* Now, ufrag and pwd */
263 if(!(tmp=RMALLOC(100)r_malloc(0,100)))
264 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
265 snprintf(tmp,100,"ice-ufrag:%s",stream->ufrag);
266 attrs[index++]=tmp;
267
268 if(!(tmp=RMALLOC(100)r_malloc(0,100)))
269 ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
270 snprintf(tmp,100,"ice-pwd:%s",stream->pwd);
271 attrs[index++]=tmp;
272
273 *attrsp=attrs;
274 *attrctp=attrct;
275
276 _status=0;
277 abort:
278 if(_status){
279 if(attrs){
280 for(index=0;index<attrct;index++){
281 RFREE(attrs[index])if(attrs[index]) r_free(attrs[index]);
282 }
283 RFREE(attrs)if(attrs) r_free(attrs);
284 }
285 }
286 return(_status);
287 }
288
289/* Get a default candidate per 4.1.4 */
290int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
291 {
292 int r,_status;
293 nr_ice_component *comp;
294
295 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
296 while(comp){
297 if (comp->component_id == component)
298 break;
299
300 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
301 }
302
303 if (!comp)
304 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
305
306 /* If there aren't any IPV4 candidates, try IPV6 */
307 if((r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV44)) &&
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
308 (r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV66))) {
309 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
310 }
311
312 _status=0;
313 abort:
314 return(_status);
315 }
316
317
318int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
319 {
320 int r,_status;
321 nr_ice_component *pcomp,*lcomp;
322
323 pcomp=STAILQ_FIRST(&pstream->components)((&pstream->components)->stqh_first);
324 lcomp=STAILQ_FIRST(&lstream->components)((&lstream->components)->stqh_first);
325 while(pcomp){
326 if ((lcomp->state != NR_ICE_COMPONENT_DISABLED4) &&
327 (pcomp->state != NR_ICE_COMPONENT_DISABLED4)) {
328 if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
329 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
330 }
331
332 lcomp=STAILQ_NEXT(lcomp,entry)((lcomp)->entry.stqe_next);
333 pcomp=STAILQ_NEXT(pcomp,entry)((pcomp)->entry.stqe_next);
334 };
335
336 if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED1) {
337 nr_ice_media_stream_set_state(pstream, NR_ICE_MEDIA_STREAM_CHECKS_FROZEN2);
338 }
339
340 _status=0;
341 abort:
342 return(_status);
343 }
344
345int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, nr_ice_media_stream *pstream, int *serviced)
346 {
347 nr_ice_component *pcomp;
348 int r,_status;
349 char *user = 0;
350
351 if (serviced)
352 *serviced = 0;
353
354 pcomp=STAILQ_FIRST(&pstream->components)((&pstream->components)->stqh_first);
355 while(pcomp){
356 int serviced_inner=0;
357
358 /* Flush all the pre-answer requests */
359 if(r=nr_ice_component_service_pre_answer_requests(pctx, pcomp, pstream->r2l_user, &serviced_inner))
360 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
361 if (serviced)
362 *serviced += serviced_inner;
363
364 pcomp=STAILQ_NEXT(pcomp,entry)((pcomp)->entry.stqe_next);
365 }
366
367 _status=0;
368 abort:
369 RFREE(user)if(user) r_free(user);
370 return(_status);
371 }
372
373/* S 5.8 -- run the first pair from the triggered check queue (even after
374 * checks have completed S 8.1.2) or run the highest priority WAITING pair or
375 * if not available FROZEN pair from the check queue */
376static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
377 {
378 int r,_status;
379 nr_ice_media_stream *stream=cb_arg;
380 nr_ice_cand_pair *pair = 0;
381 int timer_multiplier=stream->pctx->active_streams ? stream->pctx->active_streams : 1;
382 int timer_val=stream->pctx->ctx->Ta*timer_multiplier;
383
384 assert(timer_val>0)((void) sizeof ((timer_val>0) ? 1 : 0), __extension__ ({ if
(timer_val>0) ; else __assert_fail ("timer_val>0", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c"
, 384, __extension__ __PRETTY_FUNCTION__); }))
;
385
386 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
387 stream->timer=0;
388
389 /* The trigger check queue has the highest priority */
390 pair=TAILQ_FIRST(&stream->trigger_check_queue)((&stream->trigger_check_queue)->tqh_first);
391 while(pair){
392 if(pair->state==NR_ICE_PAIR_STATE_WAITING2){
393 /* Remove the pair from he trigger check queue */
394 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): Removing pair from trigger check queue %s",stream->pctx->label,pair->as_string);
395 TAILQ_REMOVE(&stream->trigger_check_queue,pair,triggered_check_queue_entry)do { if (((((pair))->triggered_check_queue_entry.tqe_next)
) != ((void*)0)) (((pair))->triggered_check_queue_entry.tqe_next
)->triggered_check_queue_entry.tqe_prev = (pair)->triggered_check_queue_entry
.tqe_prev; else { (&stream->trigger_check_queue)->tqh_last
= (pair)->triggered_check_queue_entry.tqe_prev; ; } *(pair
)->triggered_check_queue_entry.tqe_prev = (((pair))->triggered_check_queue_entry
.tqe_next); ; ; ; } while (0)
;
396 break;
397 }
398 pair=TAILQ_NEXT(pair,triggered_check_queue_entry)((pair)->triggered_check_queue_entry.tqe_next);
399 }
400
401 if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED4) {
402 if(!pair){
403 /* Find the highest priority WAITING check and move it to RUNNING */
404 pair=TAILQ_FIRST(&stream->check_list)((&stream->check_list)->tqh_first);
405 while(pair){
406 if(pair->state==NR_ICE_PAIR_STATE_WAITING2)
407 break;
408 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
409 }
410 }
411
412 /* Hmmm... No WAITING. Let's look for FROZEN */
413 if(!pair){
414 pair=TAILQ_FIRST(&stream->check_list)((&stream->check_list)->tqh_first);
415
416 while(pair){
417 if(pair->state==NR_ICE_PAIR_STATE_FROZEN1){
418 if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
419 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
420 break;
421 }
422 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
423 }
424 }
425 }
426
427 if(pair){
428 nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
429
430 /* stream->ice_state goes to checking when we decide that it is ok to
431 * start checking, which can happen before we get remote candidates. We
432 * want to fire this event when we _actually_ start sending checks. */
433 if (!stream->actually_started_checking) {
434 stream->actually_started_checking = 1;
435 if (stream->pctx->handler &&
436 stream->pctx->handler->vtbl->stream_checking) {
437 stream->pctx->handler->vtbl->stream_checking(
438 stream->pctx->handler->obj, stream->local_stream);
439 }
440 }
441
442 NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer)NR_async_timer_set(timer_val,nr_ice_media_stream_check_timer_cb
,cb_arg,(char *)__FUNCTION__,442,&stream->timer)
;
443 }
444 else {
445 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s): no FROZEN/WAITING pairs for %s",stream->pctx->label,stream->label);
446 }
447
448 _status=0;
449 abort:
450 if (_status) {
451 // cb doesn't return anything, but we should probably log that we aborted
452 // This also quiets the unused variable warnings.
453 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): check timer cb for media stream %s abort with status: %d",
454 stream->pctx->label,stream->label, _status);
455 }
456 return;
457 }
458
459/* Start checks for this media stream (aka check list) */
460int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
461 {
462 int r,_status;
463
464 /* Don't start the check timer if the stream is failed */
465 if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FAILED5) {
466 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_media_stream.c"
, 466, __extension__ __PRETTY_FUNCTION__); }))
;
467 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
468 }
469
470 if (stream->local_stream->obsolete) {
471 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_media_stream.c"
, 471, __extension__ __PRETTY_FUNCTION__); }))
;
472 ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
473 }
474
475 /* Even if the stream is completed already remote can still create a new
476 * triggered check request which needs to fire, but not change our stream
477 * state. */
478 if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED4) {
479 if(r=nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE3)) {
480 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
481 }
482 }
483
484 if (!stream->timer) {
485 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/ICE-STREAM(%s): Starting check timer for stream.",pctx->label,stream->label);
486 nr_ice_media_stream_check_timer_cb(0,0,stream);
487 }
488
489 nr_ice_peer_ctx_stream_started_checks(pctx, stream);
490
491 _status=0;
492 abort:
493 return(_status);
494 }
495
496/* Start checks for this media stream (aka check list) S 5.7 */
497int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
498 {
499 int r,_status;
500 r_assoc *assoc=0;
501 nr_ice_cand_pair *pair=0;
502
503 /* Already seen assoc */
504 if(r=r_assoc_create(&assoc,r_assoc_crc32_hash_compute,5))
505 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
506
507 /* S 5.7.4. Set the highest priority pairs in each foundation to WAITING */
508 pair=TAILQ_FIRST(&stream->check_list)((&stream->check_list)->tqh_first);
509 while(pair){
510 void *v;
511
512 if(r=r_assoc_fetch(assoc,pair->foundation,strlen(pair->foundation),&v)){
513 if(r!=R_NOT_FOUND2)
514 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
515 if(r=nr_ice_candidate_pair_unfreeze(pctx,pair))
516 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
517
518 if(r=r_assoc_insert(assoc,pair->foundation,strlen(pair->foundation),
519 0,0,0,R_ASSOC_NEW0x2))
520 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
521 }
522
523 /* Already exists... fall through */
524 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
525 }
526
527 _status=0;
528 abort:
529 r_assoc_destroy(&assoc);
530 return(_status);
531 }
532
533static int nr_ice_media_stream_unfreeze_pairs_match(nr_ice_media_stream *stream, char *foundation)
534 {
535 nr_ice_cand_pair *pair;
536 int r,_status;
537 int unfroze=0;
538
539 pair=TAILQ_FIRST(&stream->check_list)((&stream->check_list)->tqh_first);
540 while(pair){
541 if(pair->state==NR_ICE_PAIR_STATE_FROZEN1 &&
542 !strcmp(foundation,pair->foundation)){
543 if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
544 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
545 unfroze++;
546 }
547 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
548 }
549
550 if(!unfroze)
551 return(R_NOT_FOUND2);
552
553 _status=0;
554 abort:
555 return(_status);
556 }
557
558/* S 7.1.2.2 */
559int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation)
560 {
561 int r,_status;
562 nr_ice_media_stream *str;
563
564 /* 1. Unfreeze all frozen pairs with the same foundation
565 in this stream */
566 if(r=nr_ice_media_stream_unfreeze_pairs_match(stream,foundation)){
567 if(r!=R_NOT_FOUND2)
568 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
569 }
570
571 /* Now go through the check lists for the other streams */
572 str=STAILQ_FIRST(&stream->pctx->peer_streams)((&stream->pctx->peer_streams)->stqh_first);
573 while(str){
574 if(str!=stream && !str->local_stream->obsolete){
575 switch(str->ice_state){
576 case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE3:
577 /* Unfreeze matching pairs */
578 if(r=nr_ice_media_stream_unfreeze_pairs_match(str,foundation)){
579 if(r!=R_NOT_FOUND2)
580 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
581 }
582 break;
583 case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN2:
584 /* Unfreeze matching pairs if any */
585 r=nr_ice_media_stream_unfreeze_pairs_match(str,foundation);
586 if(r){
587 if(r!=R_NOT_FOUND2)
588 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
589
590 /* OK, no matching pairs: execute the algorithm from 5.7
591 for this stream */
592 if(r=nr_ice_media_stream_unfreeze_pairs(str->pctx,str))
593 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
594 }
595 if(r=nr_ice_media_stream_start_checks(str->pctx,str))
596 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
597
598 break;
599 default:
600 break;
601 }
602 }
603
604 str=STAILQ_NEXT(str,entry)((str)->entry.stqe_next);
605 }
606
607 _status=0;
608 abort:
609 return(_status);
610 }
611
612
613void nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, int log_level)
614 {
615 nr_ice_cand_pair *pair;
616 nr_ice_component *comp;
617
618 if(stream->local_stream){
619 /* stream has a corresponding local_stream */
620 nr_ice_media_stream_dump_state(stream->local_stream->pctx,stream->local_stream, log_level);
621 r_log(LOG_ICE,log_level,"ICE-PEER(%s)/STREAM(%s): state dump", stream->pctx->label, stream->label);
622 } else {
623 r_log(LOG_ICE,log_level,"ICE(%s)/STREAM(%s): state dump", stream->ctx->label, stream->label);
624 }
625
626 pair=TAILQ_FIRST(&stream->check_list)((&stream->check_list)->tqh_first);
627 while(pair){
628 nr_ice_candidate_pair_dump_state(pair, log_level);
629 pair=TAILQ_NEXT(pair,check_queue_entry)((pair)->check_queue_entry.tqe_next);
630 }
631
632 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
633 while(comp){
634 nr_ice_component_dump_state(comp, log_level);
635 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
636 }
637 }
638
639int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state)
640 {
641 /* Make no-change a no-op */
642 if (state == str->ice_state)
643 return 0;
644
645 assert((size_t)state < sizeof(nr_ice_media_stream_states)/sizeof(char *))((void) sizeof (((size_t)state < sizeof(nr_ice_media_stream_states
)/sizeof(char *)) ? 1 : 0), __extension__ ({ if ((size_t)state
< sizeof(nr_ice_media_stream_states)/sizeof(char *)) ; else
__assert_fail ("(size_t)state < sizeof(nr_ice_media_stream_states)/sizeof(char *)"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c"
, 645, __extension__ __PRETTY_FUNCTION__); }))
;
646 assert((size_t)str->ice_state < sizeof(nr_ice_media_stream_states)/sizeof(char *))((void) sizeof (((size_t)str->ice_state < sizeof(nr_ice_media_stream_states
)/sizeof(char *)) ? 1 : 0), __extension__ ({ if ((size_t)str->
ice_state < sizeof(nr_ice_media_stream_states)/sizeof(char
*)) ; else __assert_fail ("(size_t)str->ice_state < sizeof(nr_ice_media_stream_states)/sizeof(char *)"
, "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c"
, 646, __extension__ __PRETTY_FUNCTION__); }))
;
647
648 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): stream %s state %s->%s",
649 str->pctx->label,str->label,
650 nr_ice_media_stream_states[str->ice_state],
651 nr_ice_media_stream_states[state]);
652
653 if(state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE3)
654 str->pctx->active_streams++;
655 if(str->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE3)
656 str->pctx->active_streams--;
657
658 r_log(LOG_ICE,LOG_DEBUG7,"ICE-PEER(%s): %d active streams",
659 str->pctx->label, str->pctx->active_streams);
660
661 str->ice_state=state;
662 if (state == NR_ICE_MEDIA_STREAM_CHECKS_FAILED5) {
663 nr_ice_media_stream_dump_state(str->pctx,str,LOG_ERR3);
664 }
665
666 return(0);
667 }
668
669void nr_ice_media_stream_stop_checking(nr_ice_media_stream *str)
670 {
671 nr_ice_cand_pair *p;
672 nr_ice_component *comp;
673
674 /* Cancel candidate pairs */
675 p=TAILQ_FIRST(&str->check_list)((&str->check_list)->tqh_first);
676 while(p){
677 nr_ice_candidate_pair_cancel(p->pctx,p,0);
678 p=TAILQ_NEXT(p,check_queue_entry)((p)->check_queue_entry.tqe_next);
679 }
680
681 if(str->timer) {
682 NR_async_timer_cancel(str->timer);
683 str->timer = 0;
684 }
685
686 /* Cancel consent timers in case it is running already */
687 comp=STAILQ_FIRST(&str->components)((&str->components)->stqh_first);
688 while(comp){
689 nr_ice_component_consent_destroy(comp);
690 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
691 }
692 }
693
694void nr_ice_media_stream_set_obsolete(nr_ice_media_stream *str)
695 {
696 nr_ice_component *c1,*c2;
697 str->obsolete = 1;
698
699 STAILQ_FOREACH_SAFE(c1, &str->components, entry, c2)for ((c1) = (((&str->components))->stqh_first); (c1
) && ((c2) = (((c1))->entry.stqe_next), 1); (c1) =
(c2))
{
700 nr_ice_component_stop_gathering(c1);
701 }
702
703 nr_ice_media_stream_stop_checking(str);
704 }
705
706int nr_ice_media_stream_is_done_gathering(nr_ice_media_stream *str)
707 {
708 nr_ice_component *comp;
709 comp=STAILQ_FIRST(&str->components)((&str->components)->stqh_first);
710 while(comp){
711 if(!nr_ice_component_is_done_gathering(comp)) {
712 return 0;
713 }
714 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
715 }
716 return 1;
717 }
718
719void nr_ice_media_stream_refresh_consent_all(nr_ice_media_stream *stream)
720 {
721 nr_ice_component *comp;
722
723 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
724 while(comp){
725 if(comp->disconnected) {
726 nr_ice_component_refresh_consent_now(comp);
727 }
728
729 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
730 }
731 }
732
733void nr_ice_media_stream_disconnect_all_components(nr_ice_media_stream *stream)
734 {
735 nr_ice_component *comp;
736
737 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
738 while(comp){
739 comp->disconnected = 1;
740
741 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
742 }
743 }
744
745void nr_ice_media_stream_set_disconnected(nr_ice_media_stream *stream, int disconnected)
746 {
747 if (stream->disconnected == disconnected) {
748 return;
749 }
750
751 if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED4) {
752 return;
753 }
754 stream->disconnected = disconnected;
755
756 if (disconnected == NR_ICE_MEDIA_STREAM_DISCONNECTED1) {
757 if (!stream->local_stream->obsolete) {
758 if (stream->pctx->handler &&
759 stream->pctx->handler->vtbl->stream_disconnected) {
760 stream->pctx->handler->vtbl->stream_disconnected(
761 stream->pctx->handler->obj, stream->local_stream);
762 }
763 nr_ice_peer_ctx_disconnected(stream->pctx);
764 }
765 } else {
766 if (!stream->local_stream->obsolete) {
767 if (stream->pctx->handler &&
768 stream->pctx->handler->vtbl->stream_ready) {
769 stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,
770 stream->local_stream);
771 }
772 }
773 nr_ice_peer_ctx_check_if_connected(stream->pctx);
774 }
775 }
776
777int nr_ice_media_stream_check_if_connected(nr_ice_media_stream *stream)
778 {
779 nr_ice_component *comp;
780
781 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
782 while(comp){
783 if((comp->state != NR_ICE_COMPONENT_DISABLED4) &&
784 (comp->local_component->state != NR_ICE_COMPONENT_DISABLED4) &&
785 comp->disconnected)
786 break;
787
788 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
789 }
790
791 /* At least one disconnected component */
792 if(comp)
793 goto done;
794
795 nr_ice_media_stream_set_disconnected(stream, NR_ICE_MEDIA_STREAM_CONNECTED0);
796
797 done:
798 return(0);
799 }
800
801/* S OK, this component has a nominated. If every component has a nominated,
802 the stream is ready */
803void nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component)
804 {
805 nr_ice_component *comp;
806
807 comp=STAILQ_FIRST(&stream->components)((&stream->components)->stqh_first);
808 while(comp){
809 if((comp->state != NR_ICE_COMPONENT_DISABLED4) &&
810 (comp->local_component->state != NR_ICE_COMPONENT_DISABLED4) &&
811 !comp->nominated)
812 break;
813
814 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
815 }
816
817 /* At least one un-nominated component */
818 if(comp)
819 return;
820
821 /* All done... */
822 r_log(LOG_ICE,LOG_INFO6,"ICE-PEER(%s)/ICE-STREAM(%s): all active components have nominated candidate pairs",stream->pctx->label,stream->label);
823 nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED4);
824
825 /* Cancel our timer */
826 if(stream->timer){
827 NR_async_timer_cancel(stream->timer);
828 stream->timer=0;
829 }
830
831 if (stream->pctx->handler && !stream->local_stream->obsolete) {
832 stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
833 }
834
835 /* Now tell the peer_ctx that we're connected */
836 nr_ice_peer_ctx_check_if_connected(stream->pctx);
837 }
838
839void nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component)
840 {
841 component->state=NR_ICE_COMPONENT_FAILED3;
842
843 /* at least one component failed in this media stream, so the entire
844 * media stream is marked failed */
845
846 nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_FAILED5);
847
848 nr_ice_media_stream_stop_checking(stream);
849
850 if (stream->pctx->handler && !stream->local_stream->obsolete) {
851 stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
852 }
853
854 /* Now tell the peer_ctx that we've failed */
855 nr_ice_peer_ctx_check_if_connected(stream->pctx);
856 }
857
858int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp)
859 {
860 nr_ice_candidate *cand;
861 nr_ice_candidate *best_cand=0;
862 nr_ice_component *comp;
863 int r,_status;
864
865 if(r=nr_ice_media_stream_find_component(str,component,&comp))
866 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
867
868 cand=TAILQ_FIRST(&comp->candidates)((&comp->candidates)->tqh_first);
869 while(cand){
870 if(cand->state==NR_ICE_CAND_STATE_INITIALIZED3){
871 if(!best_cand || (cand->priority>best_cand->priority))
872 best_cand=cand;
873
874 }
875 cand=TAILQ_NEXT(cand,entry_comp)((cand)->entry_comp.tqe_next);
876 }
877
878 if(!best_cand)
879 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
880
881 *candp=best_cand;
882
883 _status=0;
884 abort:
885 return(_status);
886 }
887
888
889/* OK, we have the stream the user created, but that reflects the base
890 ICE ctx, not the peer_ctx. So, find the related stream in the pctx,
891 and then find the component */
892int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr_ice_component **compp)
893 {
894 int _status;
895 nr_ice_component *comp;
896
897 comp=STAILQ_FIRST(&str->components)((&str->components)->stqh_first);
898 while(comp){
899 if(comp->component_id==comp_id)
900 break;
901
902 comp=STAILQ_NEXT(comp,entry)((comp)->entry.stqe_next);
903 }
904 if(!comp)
905 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
906
907 *compp=comp;
908
909 _status=0;
910 abort:
911 return(_status);
912 }
913
914int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len)
915 {
916 int r,_status;
917 nr_ice_component *comp;
918
919 /* First find the peer component */
920 if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
921 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
922
923 /* Do we have an active pair yet? We should... */
924 if(!comp->active)
925 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
926
927 /* Does fresh ICE consent exist? */
928 if(!comp->can_send)
929 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
930
931 /* OK, write to that pair, which means:
932 1. Use the socket on our local side.
933 2. Use the address on the remote side
934 */
935 if(r=nr_socket_sendto(comp->active->local->osock,data,len,0,
936 &comp->active->remote->addr)) {
937 if ((r==R_IO_ERROR13) || (r==R_EOD5)) {
938 nr_ice_component_disconnected(comp);
939 }
940 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
941 }
942
943 // accumulate the sent bytes for the active candidate pair
944 comp->active->bytes_sent += len;
945 gettimeofday(&comp->active->last_sent, 0);
946
947 _status=0;
948 abort:
949 return(_status);
950 }
951
952/* Returns R_REJECTED if the component is unpaired or has been disabled. */
953int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote)
954 {
955 int r,_status;
956 nr_ice_component *comp;
957
958 /* First find the peer component */
959 if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
960 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
961
962 if (comp->state == NR_ICE_COMPONENT_UNPAIRED0 ||
963 comp->state == NR_ICE_COMPONENT_DISABLED4)
964 ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
965
966 if(!comp->active)
967 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
968
969 if (local) *local = comp->active->local;
970 if (remote) *remote = comp->active->remote;
971
972 _status=0;
973 abort:
974 return(_status);
975 }
976
977int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote)
978 {
979 int r,_status;
980 nr_ice_component *comp;
981
982 /* First find the peer component */
983 if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
984 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
985
986 /* Do we have an active pair yet? We should... */
987 if(!comp->active)
988 ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
989
990 /* Use the socket on our local side */
991 if(r=nr_socket_getaddr(comp->active->local->osock,local))
992 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
993
994 /* Use the address on the remote side */
995 if(r=nr_transport_addr_copy(remote,&comp->active->remote->addr))
996 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
997
998 _status=0;
999 abort:
1000 return(_status);
1001 }
1002
1003
1004
1005int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr)
1006 {
1007 nr_ice_component *lcomp,*rcomp;
1008
1009 r_log(LOG_ICE,LOG_DEBUG7,"Finalizing media stream %s, peer=%s",lstr->label,
1010 rstr?rstr->label:"NONE");
1011
1012 lcomp=STAILQ_FIRST(&lstr->components)((&lstr->components)->stqh_first);
1013 if(rstr)
1014 rcomp=STAILQ_FIRST(&rstr->components)((&rstr->components)->stqh_first);
1015 else
1016 rcomp=0;
1017
1018 while(lcomp){
1019 nr_ice_component_finalize(lcomp,rcomp);
1020
1021 lcomp=STAILQ_NEXT(lcomp,entry)((lcomp)->entry.stqe_next);
1022 if(rcomp){
1023 rcomp=STAILQ_NEXT(rcomp,entry)((rcomp)->entry.stqe_next);
1024 }
1025 }
1026
1027 return(0);
1028 }
1029
1030int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, nr_ice_candidate *cand)
1031 {
1032 int r,_status;
1033 nr_ice_component *comp;
1034
1035 if ((r=nr_ice_media_stream_find_component(pstream, cand->component_id, &comp)))
1036 ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1037
1038 if (r=nr_ice_component_pair_candidate(pctx, comp, cand, 1))
1039 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1040
1041 _status=0;
1042 abort:
1043 return(_status);
1044 }
1045
1046int nr_ice_media_stream_get_consent_status(nr_ice_media_stream *stream, int
1047component_id, int *can_send, struct timeval *ts)
1048 {
1049 int r,_status;
1050 nr_ice_component *comp;
1051
1052 if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
1053 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1054
1055 *can_send = comp->can_send;
1056 ts->tv_sec = comp->consent_last_seen.tv_sec;
1057 ts->tv_usec = comp->consent_last_seen.tv_usec;
1058 _status=0;
1059 abort:
1060 return(_status);
1061 }
1062
1063int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id)
1064 {
1065 int r,_status;
1066 nr_ice_component *comp;
1067
1068 if (stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED1)
1069 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1070
1071 if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
1072 ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1073
1074 /* Can only disable before pairing */
1075 if (comp->state != NR_ICE_COMPONENT_UNPAIRED0 &&
1076 comp->state != NR_ICE_COMPONENT_DISABLED4)
1077 ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while
(0)
;
1078
1079 comp->state = NR_ICE_COMPONENT_DISABLED4;
1080
1081 _status=0;
1082 abort:
1083 return(_status);
1084 }
1085
1086void nr_ice_media_stream_role_change(nr_ice_media_stream *stream)
1087 {
1088 nr_ice_cand_pair *pair,*temp_pair;
1089 /* Changing role causes candidate pair priority to change, which requires
1090 * re-sorting the check list. */
1091 nr_ice_cand_pair_head old_checklist;
1092
1093 /* Move check_list to old_checklist (not POD, have to do the hard way) */
1094 TAILQ_INIT(&old_checklist)do { (((&old_checklist))->tqh_first) = ((void*)0); (&
old_checklist)->tqh_last = &(((&old_checklist))->
tqh_first); ; } while (0)
;
1095 TAILQ_FOREACH_SAFE(pair,&stream->check_list,check_queue_entry,temp_pair)for ((pair) = (((&stream->check_list))->tqh_first);
(pair) && ((temp_pair) = (((pair))->check_queue_entry
.tqe_next), 1); (pair) = (temp_pair))
{
1096 TAILQ_REMOVE(&stream->check_list,pair,check_queue_entry)do { if (((((pair))->check_queue_entry.tqe_next)) != ((void
*)0)) (((pair))->check_queue_entry.tqe_next)->check_queue_entry
.tqe_prev = (pair)->check_queue_entry.tqe_prev; else { (&
stream->check_list)->tqh_last = (pair)->check_queue_entry
.tqe_prev; ; } *(pair)->check_queue_entry.tqe_prev = (((pair
))->check_queue_entry.tqe_next); ; ; ; } while (0)
;
1097 TAILQ_INSERT_TAIL(&old_checklist,pair,check_queue_entry)do { (((pair))->check_queue_entry.tqe_next) = ((void*)0); (
pair)->check_queue_entry.tqe_prev = (&old_checklist)->
tqh_last; *(&old_checklist)->tqh_last = (pair); (&
old_checklist)->tqh_last = &(((pair))->check_queue_entry
.tqe_next); ; ; } while (0)
;
1098 }
1099
1100 /* Re-insert into the check list */
1101 TAILQ_FOREACH_SAFE(pair,&old_checklist,check_queue_entry,temp_pair)for ((pair) = (((&old_checklist))->tqh_first); (pair) &&
((temp_pair) = (((pair))->check_queue_entry.tqe_next), 1)
; (pair) = (temp_pair))
{
1102 TAILQ_REMOVE(&old_checklist,pair,check_queue_entry)do { if (((((pair))->check_queue_entry.tqe_next)) != ((void
*)0)) (((pair))->check_queue_entry.tqe_next)->check_queue_entry
.tqe_prev = (pair)->check_queue_entry.tqe_prev; else { (&
old_checklist)->tqh_last = (pair)->check_queue_entry.tqe_prev
; ; } *(pair)->check_queue_entry.tqe_prev = (((pair))->
check_queue_entry.tqe_next); ; ; ; } while (0)
;
1103 nr_ice_candidate_pair_role_change(pair);
1104 nr_ice_candidate_pair_insert(&stream->check_list,pair);
1105 }
1106 }
1107
1108int nr_ice_media_stream_find_pair(nr_ice_media_stream *str, nr_ice_candidate *lcand, nr_ice_candidate *rcand, nr_ice_cand_pair **pair)
1109 {
1110 nr_ice_cand_pair_head *head = &str->check_list;
1111 nr_ice_cand_pair *c1;
1112
1113 c1=TAILQ_FIRST(head)((head)->tqh_first);
1114 while(c1){
1115 if(c1->local == lcand &&
1116 c1->remote == rcand) {
1117 *pair=c1;
1118 return(0);
1119 }
1120
1121 c1=TAILQ_NEXT(c1,check_queue_entry)((c1)->check_queue_entry.tqe_next);
1122 }
1123
1124 return(R_NOT_FOUND2);
1125 }