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