LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/ice - ice_ctx.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 520 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          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 :   }

Generated by: LCOV version 1.13