| File: | root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c |
| Warning: | line 157, 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])) { |
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r' | |
| 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)) { |
| 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 |