Line data Source code
1 :
2 : /*
3 : Copyright (c) 2007, Adobe Systems, Incorporated
4 : All rights reserved.
5 :
6 : Redistribution and use in source and binary forms, with or without
7 : modification, are permitted provided that the following conditions are
8 : met:
9 :
10 : * Redistributions of source code must retain the above copyright
11 : notice, this list of conditions and the following disclaimer.
12 :
13 : * Redistributions in binary form must reproduce the above copyright
14 : notice, this list of conditions and the following disclaimer in the
15 : documentation and/or other materials provided with the distribution.
16 :
17 : * Neither the name of Adobe Systems, Network Resonance nor the names of its
18 : contributors may be used to endorse or promote products derived from
19 : this software without specific prior written permission.
20 :
21 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 : */
33 :
34 :
35 :
36 : static char *RCSSTRING __UNUSED__="$Id: ice_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
37 :
38 : #include <csi_platform.h>
39 : #include <assert.h>
40 : #include <sys/types.h>
41 : #ifdef WIN32
42 : #include <winsock2.h>
43 : #else
44 : #include <sys/socket.h>
45 : #include <netinet/in.h>
46 : #include <arpa/inet.h>
47 : #endif
48 : #include <sys/queue.h>
49 : #include <string.h>
50 : #include <nr_api.h>
51 : #include <registry.h>
52 : #include "stun.h"
53 : #include "ice_ctx.h"
54 : #include "ice_reg.h"
55 : #include "nr_crypto.h"
56 : #include "async_timer.h"
57 : #include "util.h"
58 : #include "nr_socket_local.h"
59 :
60 : #define ICE_UFRAG_LEN 8
61 : #define ICE_PWD_LEN 32
62 :
63 : int LOG_ICE = 0;
64 :
65 : static int nr_ice_random_string(char *str, int len);
66 : static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
67 : #ifdef USE_TURN
68 : static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
69 : #endif /* USE_TURN */
70 : static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
71 : static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand);
72 0 : static int no_op(void **obj) {
73 0 : return 0;
74 : }
75 :
76 : static nr_socket_factory_vtbl default_socket_factory_vtbl = {
77 : nr_socket_local_create,
78 : no_op
79 : };
80 :
81 0 : int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
82 : {
83 : int r,_status;
84 0 : nr_ice_stun_server *servers = 0;
85 : int i;
86 : NR_registry child;
87 0 : char *addr=0;
88 : UINT2 port;
89 : in_addr_t addr_int;
90 :
91 0 : if(!(servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
92 0 : ABORT(R_NO_MEMORY);
93 :
94 0 : for(i=0;i<ct;i++){
95 0 : if(r=NR_reg_get_child_registry(NR_ICE_REG_STUN_SRV_PRFX,i,child))
96 0 : ABORT(r);
97 : /* Assume we have a v4 addr for now */
98 0 : if(r=NR_reg_alloc2_string(child,"addr",&addr))
99 0 : ABORT(r);
100 0 : addr_int=inet_addr(addr);
101 0 : if(addr_int==INADDR_NONE){
102 0 : r_log(LOG_ICE,LOG_ERR,"Invalid address %s;",addr);
103 0 : ABORT(R_BAD_ARGS);
104 : }
105 0 : if(r=NR_reg_get2_uint2(child,"port",&port)) {
106 0 : if (r != R_NOT_FOUND)
107 0 : ABORT(r);
108 0 : port = 3478;
109 : }
110 0 : if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP,
111 0 : &servers[i].u.addr))
112 0 : ABORT(r);
113 0 : servers[i].type = NR_ICE_STUN_SERVER_TYPE_ADDR;
114 0 : RFREE(addr);
115 0 : addr=0;
116 : }
117 :
118 0 : *out = servers;
119 :
120 0 : _status=0;
121 : abort:
122 0 : RFREE(addr);
123 0 : if (_status) RFREE(servers);
124 0 : return(_status);
125 : }
126 :
127 0 : int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
128 : {
129 : int _status;
130 :
131 0 : if(ctx->stun_servers){
132 0 : RFREE(ctx->stun_servers);
133 0 : ctx->stun_server_ct=0;
134 : }
135 :
136 0 : if (ct) {
137 0 : if(!(ctx->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
138 0 : ABORT(R_NO_MEMORY);
139 :
140 0 : memcpy(ctx->stun_servers,servers,sizeof(nr_ice_stun_server)*ct);
141 0 : ctx->stun_server_ct = ct;
142 : }
143 :
144 0 : _status=0;
145 : abort:
146 0 : return(_status);
147 : }
148 :
149 0 : int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
150 : {
151 : int _status;
152 :
153 0 : if(ctx->turn_servers){
154 0 : RFREE(ctx->turn_servers);
155 0 : ctx->turn_server_ct=0;
156 : }
157 :
158 0 : if(ct) {
159 0 : if(!(ctx->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
160 0 : ABORT(R_NO_MEMORY);
161 :
162 0 : memcpy(ctx->turn_servers,servers,sizeof(nr_ice_turn_server)*ct);
163 0 : ctx->turn_server_ct = ct;
164 : }
165 :
166 0 : _status=0;
167 : abort:
168 0 : return(_status);
169 : }
170 :
171 0 : int nr_ice_ctx_copy_turn_servers(nr_ice_ctx *ctx, nr_ice_turn_server *servers, int ct)
172 : {
173 : int _status, i, r;
174 :
175 0 : if (r = nr_ice_ctx_set_turn_servers(ctx, servers, ct)) {
176 0 : ABORT(r);
177 : }
178 :
179 : // make copies of the username and password so they aren't freed twice
180 0 : for (i = 0; i < ct; ++i) {
181 0 : if (!(ctx->turn_servers[i].username = r_strdup(servers[i].username))) {
182 0 : ABORT(R_NO_MEMORY);
183 : }
184 0 : if (r = r_data_create(&ctx->turn_servers[i].password,
185 0 : servers[i].password->data,
186 0 : servers[i].password->len)) {
187 0 : ABORT(r);
188 : }
189 : }
190 :
191 0 : _status=0;
192 : abort:
193 0 : return(_status);
194 : }
195 :
196 0 : static int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
197 : {
198 : int _status,i,r;
199 :
200 0 : if(ctx->local_addrs) {
201 0 : RFREE(ctx->local_addrs);
202 0 : ctx->local_addr_ct=0;
203 0 : ctx->local_addrs=0;
204 : }
205 :
206 0 : if (ct) {
207 0 : if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct)))
208 0 : ABORT(R_NO_MEMORY);
209 :
210 0 : for (i=0;i<ct;++i) {
211 0 : if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
212 0 : ABORT(r);
213 : }
214 : }
215 0 : ctx->local_addr_ct = ct;
216 : }
217 :
218 0 : _status=0;
219 : abort:
220 0 : return(_status);
221 : }
222 :
223 0 : int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
224 : {
225 : int _status;
226 :
227 0 : if (ctx->resolver) {
228 0 : ABORT(R_ALREADY);
229 : }
230 :
231 0 : ctx->resolver = resolver;
232 :
233 0 : _status=0;
234 : abort:
235 0 : return(_status);
236 : }
237 :
238 0 : int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
239 : {
240 : int _status;
241 :
242 0 : if (ctx->interface_prioritizer) {
243 0 : ABORT(R_ALREADY);
244 : }
245 :
246 0 : ctx->interface_prioritizer = ip;
247 :
248 0 : _status=0;
249 : abort:
250 0 : return(_status);
251 : }
252 :
253 0 : int nr_ice_ctx_set_turn_tcp_socket_wrapper(nr_ice_ctx *ctx, nr_socket_wrapper_factory *wrapper)
254 : {
255 : int _status;
256 :
257 0 : if (ctx->turn_tcp_socket_wrapper) {
258 0 : ABORT(R_ALREADY);
259 : }
260 :
261 0 : ctx->turn_tcp_socket_wrapper = wrapper;
262 :
263 0 : _status=0;
264 : abort:
265 0 : return(_status);
266 : }
267 :
268 0 : void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory)
269 : {
270 0 : nr_socket_factory_destroy(&ctx->socket_factory);
271 0 : ctx->socket_factory = factory;
272 0 : }
273 :
274 : #ifdef USE_TURN
275 0 : int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
276 : {
277 : int r,_status;
278 0 : nr_ice_turn_server *servers = 0;
279 : int i;
280 : NR_registry child;
281 0 : char *addr=0;
282 : UINT2 port;
283 : in_addr_t addr_int;
284 0 : Data data={0};
285 :
286 0 : if(!(servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
287 0 : ABORT(R_NO_MEMORY);
288 :
289 0 : for(i=0;i<ct;i++){
290 0 : if(r=NR_reg_get_child_registry(NR_ICE_REG_TURN_SRV_PRFX,i,child))
291 0 : ABORT(r);
292 : /* Assume we have a v4 addr for now */
293 0 : if(r=NR_reg_alloc2_string(child,"addr",&addr))
294 0 : ABORT(r);
295 0 : addr_int=inet_addr(addr);
296 0 : if(addr_int==INADDR_NONE){
297 0 : r_log(LOG_ICE,LOG_ERR,"Invalid address %s",addr);
298 0 : ABORT(R_BAD_ARGS);
299 : }
300 0 : if(r=NR_reg_get2_uint2(child,"port",&port)) {
301 0 : if (r != R_NOT_FOUND)
302 0 : ABORT(r);
303 0 : port = 3478;
304 : }
305 0 : if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP,
306 0 : &servers[i].turn_server.u.addr))
307 0 : ABORT(r);
308 :
309 :
310 0 : if(r=NR_reg_alloc2_string(child,NR_ICE_REG_TURN_SRV_USERNAME,&servers[i].username)){
311 0 : if(r!=R_NOT_FOUND)
312 0 : ABORT(r);
313 : }
314 :
315 0 : if(r=NR_reg_alloc2_data(child,NR_ICE_REG_TURN_SRV_PASSWORD,&data)){
316 0 : if(r!=R_NOT_FOUND)
317 0 : ABORT(r);
318 : }
319 : else {
320 0 : servers[i].password=RCALLOC(sizeof(*servers[i].password));
321 0 : if(!servers[i].password)
322 0 : ABORT(R_NO_MEMORY);
323 0 : servers[i].password->data = data.data;
324 0 : servers[i].password->len = data.len;
325 0 : data.data=0;
326 : }
327 :
328 0 : RFREE(addr);
329 0 : addr=0;
330 : }
331 :
332 0 : *out = servers;
333 :
334 0 : _status=0;
335 : abort:
336 0 : RFREE(data.data);
337 0 : RFREE(addr);
338 0 : if (_status) RFREE(servers);
339 0 : return(_status);
340 : }
341 : #endif /* USE_TURN */
342 :
343 : #define MAXADDRS 100 /* Ridiculously high */
344 0 : int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
345 : {
346 : int r,_status;
347 0 : char *ufrag = 0;
348 0 : char *pwd = 0;
349 :
350 0 : if (r=nr_ice_get_new_ice_ufrag(&ufrag))
351 0 : ABORT(r);
352 0 : if (r=nr_ice_get_new_ice_pwd(&pwd))
353 0 : ABORT(r);
354 :
355 0 : if (r=nr_ice_ctx_create_with_credentials(label, flags, ufrag, pwd, ctxp))
356 0 : ABORT(r);
357 :
358 0 : _status=0;
359 : abort:
360 0 : RFREE(ufrag);
361 0 : RFREE(pwd);
362 :
363 0 : return(_status);
364 : }
365 :
366 0 : int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char *ufrag, char *pwd, nr_ice_ctx **ctxp)
367 : {
368 0 : nr_ice_ctx *ctx=0;
369 : int r,_status;
370 :
371 0 : if(r=r_log_register("ice", &LOG_ICE))
372 0 : ABORT(r);
373 :
374 0 : if(!(ctx=RCALLOC(sizeof(nr_ice_ctx))))
375 0 : ABORT(R_NO_MEMORY);
376 :
377 0 : ctx->flags=flags;
378 :
379 0 : if(!(ctx->label=r_strdup(label)))
380 0 : ABORT(R_NO_MEMORY);
381 :
382 0 : if(!(ctx->ufrag=r_strdup(ufrag)))
383 0 : ABORT(r);
384 0 : if(!(ctx->pwd=r_strdup(pwd)))
385 0 : ABORT(r);
386 :
387 : /* Get the STUN servers */
388 0 : if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX,
389 0 : (unsigned int *)&ctx->stun_server_ct)||ctx->stun_server_ct==0) {
390 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No STUN servers specified in nICEr registry", ctx->label);
391 0 : ctx->stun_server_ct=0;
392 : }
393 :
394 : /* 31 is the max for our priority algorithm */
395 0 : if(ctx->stun_server_ct>31){
396 0 : r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Too many STUN servers specified: max=31", ctx->label);
397 0 : ctx->stun_server_ct=31;
398 : }
399 :
400 0 : if(ctx->stun_server_ct>0){
401 0 : if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct,&ctx->stun_servers)){
402 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): Couldn't load STUN servers from registry", ctx->label);
403 0 : ctx->stun_server_ct=0;
404 0 : ABORT(r);
405 : }
406 : }
407 :
408 : #ifdef USE_TURN
409 : /* Get the TURN servers */
410 0 : if(r=NR_reg_get_child_count(NR_ICE_REG_TURN_SRV_PRFX,
411 0 : (unsigned int *)&ctx->turn_server_ct)||ctx->turn_server_ct==0) {
412 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No TURN servers specified in nICEr registry", ctx->label);
413 0 : ctx->turn_server_ct=0;
414 : }
415 : #else
416 : ctx->turn_server_ct=0;
417 : #endif /* USE_TURN */
418 :
419 0 : ctx->local_addrs=0;
420 0 : ctx->local_addr_ct=0;
421 :
422 : /* 31 is the max for our priority algorithm */
423 0 : if((ctx->stun_server_ct+ctx->turn_server_ct)>31){
424 0 : r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Too many STUN/TURN servers specified: max=31", ctx->label);
425 0 : ctx->turn_server_ct=31-ctx->stun_server_ct;
426 : }
427 :
428 : #ifdef USE_TURN
429 0 : if(ctx->turn_server_ct>0){
430 0 : if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct,&ctx->turn_servers)){
431 0 : ctx->turn_server_ct=0;
432 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): Couldn't load TURN servers from registry", ctx->label);
433 0 : ABORT(r);
434 : }
435 : }
436 : #endif /* USE_TURN */
437 :
438 :
439 0 : ctx->Ta = 20;
440 :
441 0 : ctx->test_timer_divider = 0;
442 :
443 0 : if (r=nr_socket_factory_create_int(NULL, &default_socket_factory_vtbl, &ctx->socket_factory))
444 0 : ABORT(r);
445 :
446 0 : if ((r=NR_reg_get_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, ctx->force_net_interface, sizeof(ctx->force_net_interface)))) {
447 0 : if (r == R_NOT_FOUND) {
448 0 : ctx->force_net_interface[0] = 0;
449 : } else {
450 0 : ABORT(r);
451 : }
452 : }
453 :
454 0 : STAILQ_INIT(&ctx->streams);
455 0 : STAILQ_INIT(&ctx->sockets);
456 0 : STAILQ_INIT(&ctx->foundations);
457 0 : STAILQ_INIT(&ctx->peers);
458 0 : STAILQ_INIT(&ctx->ids);
459 :
460 0 : *ctxp=ctx;
461 :
462 0 : _status=0;
463 : abort:
464 0 : if(_status && ctx)
465 0 : nr_ice_ctx_destroy_cb(0,0,ctx);
466 :
467 0 : return(_status);
468 : }
469 :
470 0 : static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
471 : {
472 0 : nr_ice_ctx *ctx=cb_arg;
473 : nr_ice_foundation *f1,*f2;
474 : nr_ice_media_stream *s1,*s2;
475 : int i;
476 : nr_ice_stun_id *id1,*id2;
477 :
478 0 : STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2){
479 0 : STAILQ_REMOVE(&ctx->streams,s1,nr_ice_media_stream_,entry);
480 0 : nr_ice_media_stream_destroy(&s1);
481 : }
482 :
483 0 : RFREE(ctx->label);
484 :
485 0 : RFREE(ctx->stun_servers);
486 :
487 0 : RFREE(ctx->local_addrs);
488 :
489 0 : for (i = 0; i < ctx->turn_server_ct; i++) {
490 0 : RFREE(ctx->turn_servers[i].username);
491 0 : r_data_destroy(&ctx->turn_servers[i].password);
492 : }
493 0 : RFREE(ctx->turn_servers);
494 :
495 0 : f1=STAILQ_FIRST(&ctx->foundations);
496 0 : while(f1){
497 0 : f2=STAILQ_NEXT(f1,entry);
498 0 : RFREE(f1);
499 0 : f1=f2;
500 : }
501 0 : RFREE(ctx->pwd);
502 0 : RFREE(ctx->ufrag);
503 :
504 0 : STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2){
505 0 : STAILQ_REMOVE(&ctx->ids,id1,nr_ice_stun_id_,entry);
506 0 : RFREE(id1);
507 : }
508 :
509 0 : nr_resolver_destroy(&ctx->resolver);
510 0 : nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
511 0 : nr_socket_wrapper_factory_destroy(&ctx->turn_tcp_socket_wrapper);
512 0 : nr_socket_factory_destroy(&ctx->socket_factory);
513 :
514 0 : RFREE(ctx);
515 0 : }
516 :
517 0 : void nr_ice_ctx_add_flags(nr_ice_ctx *ctx, UINT4 flags)
518 : {
519 0 : ctx->flags |= flags;
520 0 : }
521 :
522 0 : void nr_ice_ctx_remove_flags(nr_ice_ctx *ctx, UINT4 flags)
523 : {
524 0 : ctx->flags &= ~flags;
525 0 : }
526 :
527 0 : int nr_ice_ctx_destroy(nr_ice_ctx **ctxp)
528 : {
529 0 : if(!ctxp || !*ctxp)
530 0 : return(0);
531 :
532 0 : (*ctxp)->done_cb=0;
533 0 : (*ctxp)->trickle_cb=0;
534 :
535 0 : NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
536 :
537 0 : *ctxp=0;
538 :
539 0 : return(0);
540 : }
541 :
542 0 : void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
543 : {
544 : int r;
545 0 : nr_ice_candidate *cand=cb_arg;
546 : nr_ice_ctx *ctx;
547 :
548 :
549 0 : assert(cb_arg);
550 0 : if (!cb_arg)
551 0 : return;
552 0 : ctx = cand->ctx;
553 :
554 0 : ctx->uninitialized_candidates--;
555 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): initialized, %d remaining",ctx->label,cand->codeword,ctx->uninitialized_candidates);
556 :
557 : /* Avoid the need for yet another initialization function */
558 0 : if (cand->state == NR_ICE_CAND_STATE_INITIALIZING && cand->type == HOST)
559 0 : cand->state = NR_ICE_CAND_STATE_INITIALIZED;
560 :
561 0 : if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
562 0 : int was_pruned = 0;
563 :
564 0 : if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
565 : cand, &was_pruned)) {
566 0 : r_log(LOG_ICE, LOG_NOTICE, "ICE(%s): Problem pruning candidates",ctx->label);
567 : }
568 :
569 : /* If we are initialized, the candidate wasn't pruned,
570 : and we have a trickle ICE callback fire the callback */
571 0 : if (ctx->trickle_cb && !was_pruned &&
572 0 : !nr_ice_ctx_hide_candidate(ctx, cand)) {
573 0 : ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
574 :
575 0 : if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
576 0 : r_log(LOG_ICE,LOG_ERR, "ICE(%s): All could not pair new trickle candidate",ctx->label);
577 : /* But continue */
578 : }
579 : }
580 : }
581 :
582 0 : if(ctx->uninitialized_candidates==0){
583 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
584 0 : if (ctx->done_cb) {
585 0 : ctx->done_cb(0,0,ctx->cb_arg);
586 : }
587 : else {
588 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No done_cb. We were probably destroyed.",ctx->label);
589 : }
590 : }
591 : else {
592 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Waiting for %d candidates to be initialized",ctx->label, ctx->uninitialized_candidates);
593 : }
594 : }
595 :
596 0 : static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
597 : {
598 : int r,_status;
599 : nr_ice_peer_ctx *pctx;
600 :
601 0 : pctx=STAILQ_FIRST(&ctx->peers);
602 0 : while(pctx){
603 0 : if (pctx->state == NR_ICE_PEER_STATE_PAIRED) {
604 0 : r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
605 0 : if (r)
606 0 : ABORT(r);
607 : }
608 :
609 0 : pctx=STAILQ_NEXT(pctx,entry);
610 : }
611 :
612 0 : _status=0;
613 : abort:
614 0 : return(_status);
615 : }
616 :
617 : /* Get the default address by doing a connect to a known public IP address,
618 : in this case Google public DNS:
619 :
620 : IPv4: 8.8.8.8
621 : IPv6: 2001:4860:4860::8888
622 :
623 : Then we can do getsockname to get the address. No packets get sent
624 : since this is UDP. It's just a way to get the address.
625 : */
626 0 : static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transport_addr* addrp)
627 : {
628 : int r,_status;
629 : nr_transport_addr addr;
630 : nr_transport_addr remote_addr;
631 0 : nr_socket *sock=0;
632 :
633 0 : switch(ip_version) {
634 : case NR_IPV4:
635 0 : if ((r=nr_str_port_to_transport_addr("0.0.0.0", 0, IPPROTO_UDP, &addr)))
636 0 : ABORT(r);
637 0 : if ((r=nr_str_port_to_transport_addr("8.8.8.8", 53, IPPROTO_UDP, &remote_addr)))
638 0 : ABORT(r);
639 0 : break;
640 : case NR_IPV6:
641 0 : if ((r=nr_str_port_to_transport_addr("::0", 0, IPPROTO_UDP, &addr)))
642 0 : ABORT(r);
643 0 : if ((r=nr_str_port_to_transport_addr("2001:4860:4860::8888", 53, IPPROTO_UDP, &remote_addr)))
644 0 : ABORT(r);
645 0 : break;
646 : default:
647 0 : assert(0);
648 : ABORT(R_INTERNAL);
649 : }
650 :
651 0 : if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
652 0 : ABORT(r);
653 0 : if ((r=nr_socket_connect(sock, &remote_addr)))
654 0 : ABORT(r);
655 0 : if ((r=nr_socket_getaddr(sock, addrp)))
656 0 : ABORT(r);
657 :
658 0 : r_log(LOG_GENERIC, LOG_DEBUG, "Default address: %s", addrp->as_string);
659 :
660 0 : _status=0;
661 : abort:
662 0 : nr_socket_destroy(&sock);
663 0 : return(_status);
664 : }
665 :
666 0 : static int nr_ice_get_default_local_address(nr_ice_ctx *ctx, int ip_version, nr_local_addr* addrs, int addr_ct, nr_local_addr *addrp)
667 : {
668 : int r,_status;
669 : nr_transport_addr default_addr;
670 : int i;
671 :
672 0 : if ((r=nr_ice_get_default_address(ctx, ip_version, &default_addr)))
673 0 : ABORT(r);
674 :
675 0 : for (i=0; i < addr_ct; ++i) {
676 : // if default addr is found in local addrs, copy the more fully
677 : // complete local addr to the output arg. Don't need to worry
678 : // about comparing ports here.
679 0 : if (!nr_transport_addr_cmp(&default_addr, &addrs[i].addr,
680 : NR_TRANSPORT_ADDR_CMP_MODE_ADDR)) {
681 0 : if ((r=nr_local_addr_copy(addrp, &addrs[i])))
682 0 : ABORT(r);
683 0 : break;
684 : }
685 : }
686 :
687 : // if default addr is not in local addrs, just copy the transport addr
688 : // to output arg.
689 0 : if (i == addr_ct) {
690 0 : if ((r=nr_transport_addr_copy(&addrp->addr, &default_addr)))
691 0 : ABORT(r);
692 0 : strlcpy(addrp->addr.ifname, "default route", sizeof(addrp->addr.ifname));
693 : }
694 :
695 0 : _status=0;
696 : abort:
697 0 : return(_status);
698 : }
699 :
700 0 : int nr_ice_set_local_addresses(nr_ice_ctx *ctx,
701 : nr_local_addr* stun_addrs, int stun_addr_ct)
702 : {
703 : int r,_status;
704 : nr_local_addr local_addrs[MAXADDRS];
705 0 : nr_local_addr *addrs = 0;
706 : int i,addr_ct;
707 : nr_local_addr default_addrs[2];
708 0 : int default_addr_ct = 0;
709 :
710 0 : if (ctx->local_addrs) {
711 0 : r_log(LOG_ICE,LOG_WARNING,"ICE(%s): local addresses already set, no work to do",ctx->label);
712 0 : ABORT(R_ALREADY);
713 : }
714 0 : if (!stun_addrs || !stun_addr_ct) {
715 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): no stun addrs provided",ctx->label);
716 0 : ABORT(R_BAD_ARGS);
717 : }
718 :
719 0 : addr_ct = MIN(stun_addr_ct, MAXADDRS);
720 0 : r_log(LOG_ICE, LOG_DEBUG, "ICE(%s): copy %d pre-fetched stun addrs", ctx->label, addr_ct);
721 0 : for (i=0; i<addr_ct; ++i) {
722 0 : if (r=nr_local_addr_copy(&local_addrs[i], &stun_addrs[i])) {
723 0 : ABORT(r);
724 : }
725 : }
726 :
727 : // removes duplicates and, based on prefs, loopback and link_local addrs
728 0 : if (r=nr_stun_filter_local_addresses(local_addrs, &addr_ct)) {
729 0 : ABORT(r);
730 : }
731 :
732 0 : if (ctx->force_net_interface[0] && addr_ct) {
733 : /* Limit us to only addresses on a single interface */
734 0 : int force_addr_ct = 0;
735 0 : for(i=0;i<addr_ct;i++){
736 0 : if (!strcmp(local_addrs[i].addr.ifname, ctx->force_net_interface)) {
737 : // copy it down in the array, if needed
738 0 : if (i != force_addr_ct) {
739 0 : if (r=nr_local_addr_copy(&local_addrs[force_addr_ct], &local_addrs[i])) {
740 0 : ABORT(r);
741 : }
742 : }
743 0 : force_addr_ct++;
744 : }
745 : }
746 0 : addr_ct = force_addr_ct;
747 : }
748 :
749 0 : if ((!addr_ct) || (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS)) {
750 : /* Get just the default IPv4 and IPv6 addrs */
751 0 : if(!nr_ice_get_default_local_address(ctx, NR_IPV4, local_addrs, addr_ct,
752 : &default_addrs[default_addr_ct])) {
753 0 : ++default_addr_ct;
754 : }
755 0 : if(!nr_ice_get_default_local_address(ctx, NR_IPV6, local_addrs, addr_ct,
756 : &default_addrs[default_addr_ct])) {
757 0 : ++default_addr_ct;
758 : }
759 0 : if (!default_addr_ct) {
760 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): failed to find default addresses",ctx->label);
761 0 : ABORT(R_FAILED);
762 : }
763 0 : addrs = default_addrs;
764 0 : addr_ct = default_addr_ct;
765 : }
766 : else {
767 0 : addrs = local_addrs;
768 : }
769 :
770 : /* Sort interfaces by preference */
771 0 : if(ctx->interface_prioritizer) {
772 0 : for(i=0;i<addr_ct;i++){
773 0 : if(r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) {
774 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to add interface ",ctx->label);
775 0 : ABORT(r);
776 : }
777 : }
778 0 : if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
779 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to sort interface by preference",ctx->label);
780 0 : ABORT(r);
781 : }
782 : }
783 :
784 0 : if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
785 0 : ABORT(r);
786 : }
787 :
788 0 : _status=0;
789 : abort:
790 0 : return(_status);
791 : }
792 :
793 0 : int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
794 : {
795 : int r,_status;
796 : nr_ice_media_stream *stream;
797 : nr_local_addr stun_addrs[MAXADDRS];
798 : int stun_addr_ct;
799 :
800 0 : if (!ctx->local_addrs) {
801 0 : if((r=nr_stun_find_local_addresses(stun_addrs,MAXADDRS,&stun_addr_ct))) {
802 0 : ABORT(r);
803 : }
804 0 : if((r=nr_ice_set_local_addresses(ctx,stun_addrs,stun_addr_ct))) {
805 0 : ABORT(r);
806 : }
807 : }
808 :
809 0 : if(STAILQ_EMPTY(&ctx->streams)) {
810 0 : r_log(LOG_ICE,LOG_ERR,"ICE(%s): Missing streams to initialize",ctx->label);
811 0 : ABORT(R_BAD_ARGS);
812 : }
813 :
814 0 : r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Initializing candidates",ctx->label);
815 0 : ctx->done_cb=done_cb;
816 0 : ctx->cb_arg=cb_arg;
817 :
818 : /* Initialize all the media stream/component pairs */
819 0 : stream=STAILQ_FIRST(&ctx->streams);
820 0 : while(stream){
821 0 : if(r=nr_ice_media_stream_initialize(ctx,stream))
822 0 : ABORT(r);
823 :
824 0 : stream=STAILQ_NEXT(stream,entry);
825 : }
826 :
827 0 : if(ctx->uninitialized_candidates)
828 0 : ABORT(R_WOULDBLOCK);
829 :
830 0 : _status=0;
831 : abort:
832 0 : return(_status);
833 : }
834 :
835 0 : int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
836 : {
837 : int r,_status;
838 :
839 0 : if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
840 0 : ABORT(r);
841 :
842 0 : STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry);
843 :
844 0 : _status=0;
845 : abort:
846 0 : return(_status);
847 : }
848 :
849 0 : int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp)
850 : {
851 : int r,_status;
852 : nr_ice_peer_ctx *pctx;
853 : nr_ice_media_stream *peer_stream;
854 :
855 0 : pctx=STAILQ_FIRST(&ctx->peers);
856 0 : while(pctx){
857 0 : if(!nr_ice_peer_ctx_find_pstream(pctx, *streamp, &peer_stream)) {
858 0 : if(r=nr_ice_peer_ctx_remove_pstream(pctx, &peer_stream)) {
859 0 : ABORT(r);
860 : }
861 : }
862 :
863 0 : pctx=STAILQ_NEXT(pctx,entry);
864 : }
865 :
866 0 : STAILQ_REMOVE(&ctx->streams,*streamp,nr_ice_media_stream_,entry);
867 0 : if(r=nr_ice_media_stream_destroy(streamp)) {
868 0 : ABORT(r);
869 : }
870 :
871 0 : _status=0;
872 : abort:
873 0 : return(_status);
874 : }
875 :
876 0 : int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp)
877 : {
878 0 : char **attrs=0;
879 : int _status;
880 0 : char *tmp=0;
881 :
882 0 : if(!(attrs=RCALLOC(sizeof(char *)*2)))
883 0 : ABORT(R_NO_MEMORY);
884 :
885 0 : if(!(tmp=RMALLOC(100)))
886 0 : ABORT(R_NO_MEMORY);
887 0 : snprintf(tmp,100,"ice-ufrag:%s",ctx->ufrag);
888 0 : attrs[0]=tmp;
889 :
890 0 : if(!(tmp=RMALLOC(100)))
891 0 : ABORT(R_NO_MEMORY);
892 0 : snprintf(tmp,100,"ice-pwd:%s",ctx->pwd);
893 0 : attrs[1]=tmp;
894 :
895 0 : *attrctp=2;
896 0 : *attrsp=attrs;
897 :
898 0 : _status=0;
899 : abort:
900 0 : if (_status){
901 0 : if (attrs){
902 0 : RFREE(attrs[0]);
903 0 : RFREE(attrs[1]);
904 : }
905 0 : RFREE(attrs);
906 : }
907 0 : return(_status);
908 : }
909 :
910 0 : static int nr_ice_random_string(char *str, int len)
911 : {
912 : unsigned char bytes[100];
913 : int needed;
914 : int r,_status;
915 :
916 0 : if(len%2) ABORT(R_BAD_ARGS);
917 0 : needed=len/2;
918 :
919 0 : if(needed>sizeof(bytes)) ABORT(R_BAD_ARGS);
920 :
921 0 : if(r=nr_crypto_random_bytes(bytes,needed))
922 0 : ABORT(r);
923 :
924 0 : if(r=nr_bin2hex(bytes,needed,(unsigned char *)str))
925 0 : ABORT(r);
926 :
927 0 : _status=0;
928 : abort:
929 0 : return(_status);
930 : }
931 :
932 : /* This is incredibly annoying: we now have a datagram but we don't
933 : know which peer it's from, and we need to be able to tell the
934 : API user. So, offer it to each peer and if one bites, assume
935 : the others don't want it
936 : */
937 0 : int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
938 : {
939 : nr_ice_peer_ctx *pctx;
940 : int r;
941 :
942 0 : pctx=STAILQ_FIRST(&ctx->peers);
943 0 : while(pctx){
944 0 : r=nr_ice_peer_ctx_deliver_packet_maybe(pctx, comp, source_addr, data, len);
945 0 : if(!r)
946 0 : break;
947 :
948 0 : pctx=STAILQ_NEXT(pctx,entry);
949 : }
950 :
951 0 : if(!pctx)
952 0 : r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Packet received from %s which doesn't match any known peer",ctx->label,source_addr->as_string);
953 :
954 0 : return(0);
955 : }
956 :
957 0 : int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
958 : {
959 : nr_ice_stun_id *xid;
960 :
961 0 : xid=STAILQ_FIRST(&ctx->ids);
962 0 : while(xid){
963 0 : if (!memcmp(xid->id, id, 12))
964 0 : return 1;
965 :
966 0 : xid=STAILQ_NEXT(xid,entry);
967 : }
968 :
969 0 : return 0;
970 : }
971 :
972 0 : int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg)
973 : {
974 : int _status;
975 : nr_ice_stun_id *xid;
976 :
977 0 : xid = RCALLOC(sizeof(*xid));
978 0 : if (!xid)
979 0 : ABORT(R_NO_MEMORY);
980 :
981 : assert(sizeof(xid->id) == sizeof(msg->header.id));
982 : #if __STDC_VERSION__ >= 201112L
983 : _Static_assert(sizeof(xid->id) == sizeof(msg->header.id),"Message ID Size Mismatch");
984 : #endif
985 0 : memcpy(xid->id, &msg->header.id, sizeof(xid->id));
986 :
987 0 : STAILQ_INSERT_TAIL(&ctx->ids,xid,entry);
988 :
989 0 : _status=0;
990 : abort:
991 0 : return(_status);
992 : }
993 :
994 :
995 : /* Clean up some of the resources (mostly file descriptors) used
996 : by candidates we didn't choose. Note that this still leaves
997 : a fair amount of non-system stuff floating around. This gets
998 : cleaned up when you destroy the ICE ctx */
999 0 : int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx)
1000 : {
1001 : nr_ice_media_stream *lstr,*rstr;
1002 :
1003 0 : r_log(LOG_ICE,LOG_DEBUG,"Finalizing ICE ctx %s, peer=%s",ctx->label,pctx->label);
1004 : /*
1005 : First find the peer stream, if any
1006 : */
1007 0 : lstr=STAILQ_FIRST(&ctx->streams);
1008 0 : while(lstr){
1009 0 : rstr=STAILQ_FIRST(&pctx->peer_streams);
1010 :
1011 0 : while(rstr){
1012 0 : if(rstr->local_stream==lstr)
1013 0 : break;
1014 :
1015 0 : rstr=STAILQ_NEXT(rstr,entry);
1016 : }
1017 :
1018 0 : nr_ice_media_stream_finalize(lstr,rstr);
1019 :
1020 0 : lstr=STAILQ_NEXT(lstr,entry);
1021 : }
1022 :
1023 0 : return(0);
1024 : }
1025 :
1026 :
1027 0 : int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
1028 : {
1029 0 : ctx->trickle_cb = cb;
1030 0 : ctx->trickle_cb_arg = cb_arg;
1031 :
1032 0 : return 0;
1033 : }
1034 :
1035 0 : int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
1036 : {
1037 0 : if (cand->state != NR_ICE_CAND_STATE_INITIALIZED) {
1038 0 : return 1;
1039 : }
1040 :
1041 0 : if (ctx->flags & NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES) {
1042 0 : if (cand->type == HOST)
1043 0 : return 1;
1044 : }
1045 :
1046 0 : return 0;
1047 : }
1048 :
1049 0 : int nr_ice_get_new_ice_ufrag(char** ufrag)
1050 : {
1051 : int r,_status;
1052 : char buf[ICE_UFRAG_LEN+1];
1053 :
1054 0 : if(r=nr_ice_random_string(buf,ICE_UFRAG_LEN))
1055 0 : ABORT(r);
1056 0 : if(!(*ufrag=r_strdup(buf)))
1057 0 : ABORT(r);
1058 :
1059 0 : _status=0;
1060 : abort:
1061 0 : if(_status) {
1062 0 : RFREE(*ufrag);
1063 0 : *ufrag = 0;
1064 : }
1065 0 : return(_status);
1066 : }
1067 :
1068 0 : int nr_ice_get_new_ice_pwd(char** pwd)
1069 : {
1070 : int r,_status;
1071 : char buf[ICE_PWD_LEN+1];
1072 :
1073 0 : if(r=nr_ice_random_string(buf,ICE_PWD_LEN))
1074 0 : ABORT(r);
1075 0 : if(!(*pwd=r_strdup(buf)))
1076 0 : ABORT(r);
1077 :
1078 0 : _status=0;
1079 : abort:
1080 0 : if(_status) {
1081 0 : RFREE(*pwd);
1082 0 : *pwd = 0;
1083 : }
1084 0 : return(_status);
1085 : }
1086 :
1087 : #ifndef UINT2_MAX
1088 : #define UINT2_MAX ((UINT2)(65535U))
1089 : #endif
1090 :
1091 0 : void nr_ice_accumulate_count(UINT2* orig_count, UINT2 new_count)
1092 : {
1093 0 : if (UINT2_MAX - new_count < *orig_count) {
1094 : // don't rollover, just stop accumulating at MAX value
1095 0 : *orig_count = UINT2_MAX;
1096 : } else {
1097 0 : *orig_count += new_count;
1098 : }
1099 0 : }
|