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