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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | Copyright (c) 2007, Adobe Systems, Incorporated |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are |
7 | met: |
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 | |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 | OF 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 | |
45 | static 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); |
46 | static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate, int trickled, const char *mdns_addr); |
47 | static void nr_ice_peer_ctx_start_trickle_timer(nr_ice_peer_ctx *pctx); |
48 | |
49 | int 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 | |
90 | int 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 | |
150 | static 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 | |
176 | static 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 | |
235 | int 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 | |
269 | int 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 | |
284 | int 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 | |
360 | static 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 | |
381 | static 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 | |
400 | int 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 | |
442 | int 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 | |
465 | int 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 */ |
521 | int 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 | */ |
535 | int 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 | |
635 | void 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 | |
646 | void 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 | |
659 | void 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 | |
672 | void 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 | |
689 | void 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 | |
707 | void 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 | |
717 | static 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 */ |
728 | void 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 */ |
776 | int 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 | |
811 | int 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 | |
854 | void 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 |