media/mtransport/third_party/nICEr/src/ice/ice_ctx.c

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:ffff5b810228
1 /*
2 Copyright (c) 2007, Adobe Systems, Incorporated
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 * Neither the name of Adobe Systems, Network Resonance nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34
35 static char *RCSSTRING __UNUSED__="$Id: ice_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
36
37 #include <csi_platform.h>
38 #include <assert.h>
39 #include <sys/types.h>
40 #ifdef WIN32
41 #include <winsock2.h>
42 #else
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #endif
47 #include <sys/queue.h>
48 #include <string.h>
49 #include <nr_api.h>
50 #include <registry.h>
51 #include "stun.h"
52 #include "ice_ctx.h"
53 #include "ice_reg.h"
54 #include "nr_crypto.h"
55 #include "async_timer.h"
56 #include "util.h"
57
58
59 int LOG_ICE = 0;
60
61 static int nr_ice_random_string(char *str, int len);
62 static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
63 #ifdef USE_TURN
64 static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
65 #endif /* USE_TURN */
66 static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
67 static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand);
68
69 int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
70 {
71 int r,_status;
72 nr_ice_stun_server *servers = 0;
73 int i;
74 NR_registry child;
75 char *addr=0;
76 UINT2 port;
77 in_addr_t addr_int;
78
79 if(!(servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
80 ABORT(R_NO_MEMORY);
81
82 for(i=0;i<ct;i++){
83 if(r=NR_reg_get_child_registry(NR_ICE_REG_STUN_SRV_PRFX,i,child))
84 ABORT(r);
85 /* Assume we have a v4 addr for now */
86 if(r=NR_reg_alloc2_string(child,"addr",&addr))
87 ABORT(r);
88 addr_int=inet_addr(addr);
89 if(addr_int==INADDR_NONE){
90 r_log(LOG_ICE,LOG_ERR,"Invalid address %s;",addr);
91 ABORT(R_BAD_ARGS);
92 }
93 if(r=NR_reg_get2_uint2(child,"port",&port)) {
94 if (r != R_NOT_FOUND)
95 ABORT(r);
96 port = 3478;
97 }
98 if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP,
99 &servers[i].u.addr))
100 ABORT(r);
101 servers[i].index=i;
102 servers[i].type = NR_ICE_STUN_SERVER_TYPE_ADDR;
103 RFREE(addr);
104 addr=0;
105 }
106
107 *out = servers;
108
109 _status=0;
110 abort:
111 RFREE(addr);
112 if (_status) RFREE(servers);
113 return(_status);
114 }
115
116 int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
117 {
118 int _status;
119
120 if(ctx->stun_servers){
121 RFREE(ctx->stun_servers);
122 ctx->stun_server_ct=0;
123 }
124
125 if (ct) {
126 if(!(ctx->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
127 ABORT(R_NO_MEMORY);
128
129 memcpy(ctx->stun_servers,servers,sizeof(nr_ice_stun_server)*ct);
130 ctx->stun_server_ct = ct;
131 }
132
133 _status=0;
134 abort:
135 return(_status);
136 }
137
138 int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
139 {
140 int _status;
141
142 if(ctx->turn_servers){
143 RFREE(ctx->turn_servers);
144 ctx->turn_server_ct=0;
145 }
146
147 if(ct) {
148 if(!(ctx->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
149 ABORT(R_NO_MEMORY);
150
151 memcpy(ctx->turn_servers,servers,sizeof(nr_ice_turn_server)*ct);
152 ctx->turn_server_ct = ct;
153 }
154
155 _status=0;
156 abort:
157 return(_status);
158 }
159
160 int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
161 {
162 int _status,i,r;
163
164 if(ctx->local_addrs) {
165 RFREE(ctx->local_addrs);
166 ctx->local_addr_ct=0;
167 ctx->local_addrs=0;
168 }
169
170 if (ct) {
171 if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct)))
172 ABORT(R_NO_MEMORY);
173
174 for (i=0;i<ct;++i) {
175 if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
176 ABORT(r);
177 }
178 }
179 ctx->local_addr_ct = ct;
180 }
181
182 _status=0;
183 abort:
184 return(_status);
185 }
186
187 int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
188 {
189 int _status;
190
191 if (ctx->resolver) {
192 ABORT(R_ALREADY);
193 }
194
195 ctx->resolver = resolver;
196
197 _status=0;
198 abort:
199 return(_status);
200 }
201
202 int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
203 {
204 int _status;
205
206 if (ctx->interface_prioritizer) {
207 ABORT(R_ALREADY);
208 }
209
210 ctx->interface_prioritizer = ip;
211
212 _status=0;
213 abort:
214 return(_status);
215 }
216
217 #ifdef USE_TURN
218 int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
219 {
220 int r,_status;
221 nr_ice_turn_server *servers = 0;
222 int i;
223 NR_registry child;
224 char *addr=0;
225 UINT2 port;
226 in_addr_t addr_int;
227 Data data={0};
228
229 if(!(servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
230 ABORT(R_NO_MEMORY);
231
232 for(i=0;i<ct;i++){
233 if(r=NR_reg_get_child_registry(NR_ICE_REG_TURN_SRV_PRFX,i,child))
234 ABORT(r);
235 /* Assume we have a v4 addr for now */
236 if(r=NR_reg_alloc2_string(child,"addr",&addr))
237 ABORT(r);
238 addr_int=inet_addr(addr);
239 if(addr_int==INADDR_NONE){
240 r_log(LOG_ICE,LOG_ERR,"Invalid address %s",addr);
241 ABORT(R_BAD_ARGS);
242 }
243 if(r=NR_reg_get2_uint2(child,"port",&port)) {
244 if (r != R_NOT_FOUND)
245 ABORT(r);
246 port = 3478;
247 }
248 if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP,
249 &servers[i].turn_server.u.addr))
250 ABORT(r);
251
252
253 if(r=NR_reg_alloc2_string(child,NR_ICE_REG_TURN_SRV_USERNAME,&servers[i].username)){
254 if(r!=R_NOT_FOUND)
255 ABORT(r);
256 }
257
258 if(r=NR_reg_alloc2_data(child,NR_ICE_REG_TURN_SRV_PASSWORD,&data)){
259 if(r!=R_NOT_FOUND)
260 ABORT(r);
261 }
262 else {
263 servers[i].password=RCALLOC(sizeof(*servers[i].password));
264 if(!servers[i].password)
265 ABORT(R_NO_MEMORY);
266 servers[i].password->data = data.data;
267 servers[i].password->len = data.len;
268 data.data=0;
269 }
270
271 servers[i].turn_server.index=i;
272
273 RFREE(addr);
274 addr=0;
275 }
276
277 *out = servers;
278
279 _status=0;
280 abort:
281 RFREE(data.data);
282 RFREE(addr);
283 if (_status) RFREE(servers);
284 return(_status);
285 }
286 #endif /* USE_TURN */
287
288 int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
289 {
290 nr_ice_ctx *ctx=0;
291 int r,_status;
292 char buf[100];
293
294 if(r=r_log_register("ice", &LOG_ICE))
295 ABORT(r);
296
297 if(!(ctx=RCALLOC(sizeof(nr_ice_ctx))))
298 ABORT(R_NO_MEMORY);
299
300 ctx->flags=flags;
301
302 if(!(ctx->label=r_strdup(label)))
303 ABORT(R_NO_MEMORY);
304
305 if(r=nr_ice_random_string(buf,8))
306 ABORT(r);
307 if(!(ctx->ufrag=r_strdup(buf)))
308 ABORT(r);
309 if(r=nr_ice_random_string(buf,32))
310 ABORT(r);
311 if(!(ctx->pwd=r_strdup(buf)))
312 ABORT(r);
313
314 /* Get the STUN servers */
315 if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX,
316 (unsigned int *)&ctx->stun_server_ct)||ctx->stun_server_ct==0) {
317 r_log(LOG_ICE,LOG_WARNING,"ICE(%s): No STUN servers specified", ctx->label);
318 ctx->stun_server_ct=0;
319 }
320
321 /* 255 is the max for our priority algorithm */
322 if(ctx->stun_server_ct>255){
323 r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Too many STUN servers specified: max=255", ctx->label);
324 ctx->stun_server_ct=255;
325 }
326
327 if(ctx->stun_server_ct>0){
328 if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct,&ctx->stun_servers)){
329 r_log(LOG_ICE,LOG_ERR,"ICE(%s): Couldn't load STUN servers from registry", ctx->label);
330 ctx->stun_server_ct=0;
331 ABORT(r);
332 }
333 }
334
335 #ifdef USE_TURN
336 /* Get the TURN servers */
337 if(r=NR_reg_get_child_count(NR_ICE_REG_TURN_SRV_PRFX,
338 (unsigned int *)&ctx->turn_server_ct)||ctx->turn_server_ct==0) {
339 r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): No TURN servers specified", ctx->label);
340 ctx->turn_server_ct=0;
341 }
342 #else
343 ctx->turn_server_ct=0;
344 #endif /* USE_TURN */
345
346 ctx->local_addrs=0;
347 ctx->local_addr_ct=0;
348
349 /* 255 is the max for our priority algorithm */
350 if((ctx->stun_server_ct+ctx->turn_server_ct)>255){
351 r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Too many STUN/TURN servers specified: max=255", ctx->label);
352 ctx->turn_server_ct=255-ctx->stun_server_ct;
353 }
354
355 #ifdef USE_TURN
356 if(ctx->turn_server_ct>0){
357 if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct,&ctx->turn_servers)){
358 ctx->turn_server_ct=0;
359 r_log(LOG_ICE,LOG_ERR,"ICE(%s): Couldn't load TURN servers from registry", ctx->label);
360 ABORT(r);
361 }
362 }
363 #endif /* USE_TURN */
364
365
366 ctx->Ta = 20;
367
368 STAILQ_INIT(&ctx->streams);
369 STAILQ_INIT(&ctx->sockets);
370 STAILQ_INIT(&ctx->foundations);
371 STAILQ_INIT(&ctx->peers);
372 STAILQ_INIT(&ctx->ids);
373
374 *ctxp=ctx;
375
376 _status=0;
377 abort:
378 if(_status)
379 nr_ice_ctx_destroy_cb(0,0,ctx);
380
381 return(_status);
382 }
383
384 static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
385 {
386 nr_ice_ctx *ctx=cb_arg;
387 nr_ice_foundation *f1,*f2;
388 nr_ice_media_stream *s1,*s2;
389 int i;
390 nr_ice_stun_id *id1,*id2;
391
392 RFREE(ctx->label);
393
394 RFREE(ctx->stun_servers);
395
396 RFREE(ctx->local_addrs);
397
398 for (i = 0; i < ctx->turn_server_ct; i++) {
399 RFREE(ctx->turn_servers[i].username);
400 r_data_destroy(&ctx->turn_servers[i].password);
401 }
402 RFREE(ctx->turn_servers);
403
404 f1=STAILQ_FIRST(&ctx->foundations);
405 while(f1){
406 f2=STAILQ_NEXT(f1,entry);
407 RFREE(f1);
408 f1=f2;
409 }
410 RFREE(ctx->pwd);
411 RFREE(ctx->ufrag);
412
413 STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2){
414 STAILQ_REMOVE(&ctx->streams,s1,nr_ice_media_stream_,entry);
415 nr_ice_media_stream_destroy(&s1);
416 }
417
418 STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2){
419 STAILQ_REMOVE(&ctx->ids,id1,nr_ice_stun_id_,entry);
420 RFREE(id1);
421 }
422
423 nr_resolver_destroy(&ctx->resolver);
424 nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
425
426 RFREE(ctx);
427 }
428
429 int nr_ice_ctx_destroy(nr_ice_ctx **ctxp)
430 {
431 if(!ctxp || !*ctxp)
432 return(0);
433
434 (*ctxp)->done_cb=0;
435 (*ctxp)->trickle_cb=0;
436
437 NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
438
439 *ctxp=0;
440
441 return(0);
442 }
443
444 void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
445 {
446 int r,_status;
447 nr_ice_candidate *cand=cb_arg;
448 nr_ice_ctx *ctx;
449
450
451 assert(cb_arg);
452 if (!cb_arg)
453 return;
454 ctx = cand->ctx;
455
456 ctx->uninitialized_candidates--;
457
458 if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
459 int was_pruned = 0;
460
461 if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
462 cand, &was_pruned)) {
463 r_log(LOG_ICE, LOG_NOTICE, "ICE(%s): Problem pruning candidates",ctx->label);
464 }
465
466 /* If we are initialized, the candidate wasn't pruned,
467 and we have a trickle ICE callback fire the callback */
468 if (ctx->trickle_cb && !was_pruned) {
469 ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
470
471 if (r=nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
472 r_log(LOG_ICE,LOG_ERR, "ICE(%s): All could not pair new trickle candidate",ctx->label);
473 /* But continue */
474 }
475 }
476 }
477
478 if(ctx->uninitialized_candidates==0){
479 r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
480 ctx->state=NR_ICE_STATE_INITIALIZED;
481 if (ctx->done_cb) {
482 ctx->done_cb(0,0,ctx->cb_arg);
483 }
484 else {
485 r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No done_cb. We were probably destroyed.",ctx->label);
486 }
487 }
488 else {
489 r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Waiting for %d candidates to be initialized",ctx->label, ctx->uninitialized_candidates);
490 }
491 }
492
493 static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
494 {
495 int r,_status;
496 nr_ice_peer_ctx *pctx;
497
498 pctx=STAILQ_FIRST(&ctx->peers);
499 while(pctx){
500 if (pctx->state == NR_ICE_PEER_STATE_PAIRED) {
501 r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
502 if (r)
503 ABORT(r);
504 }
505
506 pctx=STAILQ_NEXT(pctx,entry);
507 }
508
509 _status=0;
510 abort:
511 return(_status);
512 }
513
514
515 #define MAXADDRS 100 // Ridiculously high
516 int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
517 {
518 int r,_status;
519 nr_ice_media_stream *stream;
520 nr_local_addr addrs[MAXADDRS];
521 int i,addr_ct;
522
523 r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Initializing candidates",ctx->label);
524 ctx->state=NR_ICE_STATE_INITIALIZING;
525 ctx->done_cb=done_cb;
526 ctx->cb_arg=cb_arg;
527
528 if(STAILQ_EMPTY(&ctx->streams)) {
529 r_log(LOG_ICE,LOG_ERR,"ICE(%s): Missing streams to initialize",ctx->label);
530 ABORT(R_BAD_ARGS);
531 }
532
533 /* First, gather all the local addresses we have */
534 if(r=nr_stun_find_local_addresses(addrs,MAXADDRS,&addr_ct)) {
535 r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to find local addresses",ctx->label);
536 ABORT(r);
537 }
538
539 /* Sort interfaces by preference */
540 if(ctx->interface_prioritizer) {
541 for(i=0;i<addr_ct;i++){
542 if(r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) {
543 r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to add interface ",ctx->label);
544 ABORT(r);
545 }
546 }
547 if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
548 r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to sort interface by preference",ctx->label);
549 ABORT(r);
550 }
551 }
552
553 if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
554 ABORT(r);
555 }
556
557 /* Initialize all the media stream/component pairs */
558 stream=STAILQ_FIRST(&ctx->streams);
559 while(stream){
560 if(r=nr_ice_media_stream_initialize(ctx,stream))
561 ABORT(r);
562
563 stream=STAILQ_NEXT(stream,entry);
564 }
565
566 if(ctx->uninitialized_candidates)
567 ABORT(R_WOULDBLOCK);
568
569
570 _status=0;
571 abort:
572 return(_status);
573 }
574
575 int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
576 {
577 int r,_status;
578
579 if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
580 ABORT(r);
581
582 STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry);
583
584 _status=0;
585 abort:
586 return(_status);
587 }
588
589 int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp)
590 {
591 char **attrs=0;
592 int _status;
593 char *tmp=0;
594
595 if(!(attrs=RCALLOC(sizeof(char *)*2)))
596 ABORT(R_NO_MEMORY);
597
598 if(!(tmp=RMALLOC(100)))
599 ABORT(R_NO_MEMORY);
600 snprintf(tmp,100,"ice-ufrag:%s",ctx->ufrag);
601 attrs[0]=tmp;
602
603 if(!(tmp=RMALLOC(100)))
604 ABORT(R_NO_MEMORY);
605 snprintf(tmp,100,"ice-pwd:%s",ctx->pwd);
606 attrs[1]=tmp;
607
608 *attrctp=2;
609 *attrsp=attrs;
610
611 _status=0;
612 abort:
613 if (_status){
614 if (attrs){
615 RFREE(attrs[0]);
616 RFREE(attrs[1]);
617 }
618 RFREE(attrs);
619 }
620 return(_status);
621 }
622
623 static int nr_ice_random_string(char *str, int len)
624 {
625 unsigned char bytes[100];
626 int needed;
627 int r,_status;
628
629 if(len%2) ABORT(R_BAD_ARGS);
630 needed=len/2;
631
632 if(needed>sizeof(bytes)) ABORT(R_BAD_ARGS);
633
634 //memset(bytes,0,needed);
635
636 if(r=nr_crypto_random_bytes(bytes,needed))
637 ABORT(r);
638
639 if(r=nr_bin2hex(bytes,needed,(unsigned char *)str))
640 ABORT(r);
641
642 _status=0;
643 abort:
644 return(_status);
645 }
646
647 /* This is incredibly annoying: we now have a datagram but we don't
648 know which peer it's from, and we need to be able to tell the
649 API user. So, offer it to each peer and if one bites, assume
650 the others don't want it
651 */
652 int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
653 {
654 nr_ice_peer_ctx *pctx;
655 int r;
656
657 pctx=STAILQ_FIRST(&ctx->peers);
658 while(pctx){
659 r=nr_ice_peer_ctx_deliver_packet_maybe(pctx, comp, source_addr, data, len);
660 if(!r)
661 break;
662
663 pctx=STAILQ_NEXT(pctx,entry);
664 }
665
666 if(!pctx)
667 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);
668
669 return(0);
670 }
671
672 int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
673 {
674 nr_ice_stun_id *xid;
675
676 xid=STAILQ_FIRST(&ctx->ids);
677 while(xid){
678 if (!memcmp(xid->id, id, 12))
679 return 1;
680
681 xid=STAILQ_NEXT(xid,entry);
682 }
683
684 return 0;
685 }
686
687 int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg)
688 {
689 int _status;
690 nr_ice_stun_id *xid;
691
692 xid = RCALLOC(sizeof(*xid));
693 if (!xid)
694 ABORT(R_NO_MEMORY);
695
696 assert(sizeof(xid->id) == sizeof(msg->header.id));
697 #if __STDC_VERSION__ >= 201112L
698 _Static_assert(sizeof(xid->id) == sizeof(msg->header.id),"Message ID Size Mismatch");
699 #endif
700 memcpy(xid->id, &msg->header.id, sizeof(xid->id));
701
702 STAILQ_INSERT_TAIL(&ctx->ids,xid,entry);
703
704 _status=0;
705 abort:
706 return(_status);
707 }
708
709
710 /* Clean up some of the resources (mostly file descriptors) used
711 by candidates we didn't choose. Note that this still leaves
712 a fair amount of non-system stuff floating around. This gets
713 cleaned up when you destroy the ICE ctx */
714 int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx)
715 {
716 nr_ice_media_stream *lstr,*rstr;
717
718 r_log(LOG_ICE,LOG_DEBUG,"Finalizing ICE ctx %s, peer=%s",ctx->label,pctx->label);
719 /*
720 First find the peer stream, if any
721 */
722 lstr=STAILQ_FIRST(&ctx->streams);
723 while(lstr){
724 rstr=STAILQ_FIRST(&pctx->peer_streams);
725
726 while(rstr){
727 if(rstr->local_stream==lstr)
728 break;
729
730 rstr=STAILQ_NEXT(rstr,entry);
731 }
732
733 nr_ice_media_stream_finalize(lstr,rstr);
734
735 lstr=STAILQ_NEXT(lstr,entry);
736 }
737
738 return(0);
739 }
740
741
742 int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
743 {
744 ctx->trickle_cb = cb;
745 ctx->trickle_cb_arg = cb_arg;
746
747 return 0;
748 }

mercurial