Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /*
2 Copyright (c) 2007, Adobe Systems, Incorporated
3 All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
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 */
35 static char *RCSSTRING __UNUSED__="$Id: ice_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
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"
59 int LOG_ICE = 0;
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);
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;
79 if(!(servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
80 ABORT(R_NO_MEMORY);
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 }
107 *out = servers;
109 _status=0;
110 abort:
111 RFREE(addr);
112 if (_status) RFREE(servers);
113 return(_status);
114 }
116 int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
117 {
118 int _status;
120 if(ctx->stun_servers){
121 RFREE(ctx->stun_servers);
122 ctx->stun_server_ct=0;
123 }
125 if (ct) {
126 if(!(ctx->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
127 ABORT(R_NO_MEMORY);
129 memcpy(ctx->stun_servers,servers,sizeof(nr_ice_stun_server)*ct);
130 ctx->stun_server_ct = ct;
131 }
133 _status=0;
134 abort:
135 return(_status);
136 }
138 int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
139 {
140 int _status;
142 if(ctx->turn_servers){
143 RFREE(ctx->turn_servers);
144 ctx->turn_server_ct=0;
145 }
147 if(ct) {
148 if(!(ctx->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
149 ABORT(R_NO_MEMORY);
151 memcpy(ctx->turn_servers,servers,sizeof(nr_ice_turn_server)*ct);
152 ctx->turn_server_ct = ct;
153 }
155 _status=0;
156 abort:
157 return(_status);
158 }
160 int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
161 {
162 int _status,i,r;
164 if(ctx->local_addrs) {
165 RFREE(ctx->local_addrs);
166 ctx->local_addr_ct=0;
167 ctx->local_addrs=0;
168 }
170 if (ct) {
171 if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct)))
172 ABORT(R_NO_MEMORY);
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 }
182 _status=0;
183 abort:
184 return(_status);
185 }
187 int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
188 {
189 int _status;
191 if (ctx->resolver) {
192 ABORT(R_ALREADY);
193 }
195 ctx->resolver = resolver;
197 _status=0;
198 abort:
199 return(_status);
200 }
202 int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
203 {
204 int _status;
206 if (ctx->interface_prioritizer) {
207 ABORT(R_ALREADY);
208 }
210 ctx->interface_prioritizer = ip;
212 _status=0;
213 abort:
214 return(_status);
215 }
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};
229 if(!(servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
230 ABORT(R_NO_MEMORY);
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);
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 }
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 }
271 servers[i].turn_server.index=i;
273 RFREE(addr);
274 addr=0;
275 }
277 *out = servers;
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 */
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];
294 if(r=r_log_register("ice", &LOG_ICE))
295 ABORT(r);
297 if(!(ctx=RCALLOC(sizeof(nr_ice_ctx))))
298 ABORT(R_NO_MEMORY);
300 ctx->flags=flags;
302 if(!(ctx->label=r_strdup(label)))
303 ABORT(R_NO_MEMORY);
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);
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 }
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 }
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 }
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 */
346 ctx->local_addrs=0;
347 ctx->local_addr_ct=0;
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 }
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 */
366 ctx->Ta = 20;
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);
374 *ctxp=ctx;
376 _status=0;
377 abort:
378 if(_status)
379 nr_ice_ctx_destroy_cb(0,0,ctx);
381 return(_status);
382 }
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;
392 RFREE(ctx->label);
394 RFREE(ctx->stun_servers);
396 RFREE(ctx->local_addrs);
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);
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);
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 }
418 STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2){
419 STAILQ_REMOVE(&ctx->ids,id1,nr_ice_stun_id_,entry);
420 RFREE(id1);
421 }
423 nr_resolver_destroy(&ctx->resolver);
424 nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
426 RFREE(ctx);
427 }
429 int nr_ice_ctx_destroy(nr_ice_ctx **ctxp)
430 {
431 if(!ctxp || !*ctxp)
432 return(0);
434 (*ctxp)->done_cb=0;
435 (*ctxp)->trickle_cb=0;
437 NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
439 *ctxp=0;
441 return(0);
442 }
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;
451 assert(cb_arg);
452 if (!cb_arg)
453 return;
454 ctx = cand->ctx;
456 ctx->uninitialized_candidates--;
458 if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
459 int was_pruned = 0;
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 }
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);
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 }
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 }
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;
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 }
506 pctx=STAILQ_NEXT(pctx,entry);
507 }
509 _status=0;
510 abort:
511 return(_status);
512 }
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;
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;
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 }
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 }
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 }
553 if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
554 ABORT(r);
555 }
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);
563 stream=STAILQ_NEXT(stream,entry);
564 }
566 if(ctx->uninitialized_candidates)
567 ABORT(R_WOULDBLOCK);
570 _status=0;
571 abort:
572 return(_status);
573 }
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;
579 if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
580 ABORT(r);
582 STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry);
584 _status=0;
585 abort:
586 return(_status);
587 }
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;
595 if(!(attrs=RCALLOC(sizeof(char *)*2)))
596 ABORT(R_NO_MEMORY);
598 if(!(tmp=RMALLOC(100)))
599 ABORT(R_NO_MEMORY);
600 snprintf(tmp,100,"ice-ufrag:%s",ctx->ufrag);
601 attrs[0]=tmp;
603 if(!(tmp=RMALLOC(100)))
604 ABORT(R_NO_MEMORY);
605 snprintf(tmp,100,"ice-pwd:%s",ctx->pwd);
606 attrs[1]=tmp;
608 *attrctp=2;
609 *attrsp=attrs;
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 }
623 static int nr_ice_random_string(char *str, int len)
624 {
625 unsigned char bytes[100];
626 int needed;
627 int r,_status;
629 if(len%2) ABORT(R_BAD_ARGS);
630 needed=len/2;
632 if(needed>sizeof(bytes)) ABORT(R_BAD_ARGS);
634 //memset(bytes,0,needed);
636 if(r=nr_crypto_random_bytes(bytes,needed))
637 ABORT(r);
639 if(r=nr_bin2hex(bytes,needed,(unsigned char *)str))
640 ABORT(r);
642 _status=0;
643 abort:
644 return(_status);
645 }
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;
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;
663 pctx=STAILQ_NEXT(pctx,entry);
664 }
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);
669 return(0);
670 }
672 int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
673 {
674 nr_ice_stun_id *xid;
676 xid=STAILQ_FIRST(&ctx->ids);
677 while(xid){
678 if (!memcmp(xid->id, id, 12))
679 return 1;
681 xid=STAILQ_NEXT(xid,entry);
682 }
684 return 0;
685 }
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;
692 xid = RCALLOC(sizeof(*xid));
693 if (!xid)
694 ABORT(R_NO_MEMORY);
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));
702 STAILQ_INSERT_TAIL(&ctx->ids,xid,entry);
704 _status=0;
705 abort:
706 return(_status);
707 }
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;
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);
726 while(rstr){
727 if(rstr->local_stream==lstr)
728 break;
730 rstr=STAILQ_NEXT(rstr,entry);
731 }
733 nr_ice_media_stream_finalize(lstr,rstr);
735 lstr=STAILQ_NEXT(lstr,entry);
736 }
738 return(0);
739 }
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;
747 return 0;
748 }