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