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

          Line data    Source code
       1             : /*
       2             :   Copyright (c) 2007, Adobe Systems, Incorporated
       3             :   Copyright (c) 2013, Mozilla
       4             : 
       5             :   All rights reserved.
       6             : 
       7             :   Redistribution and use in source and binary forms, with or without
       8             :   modification, are permitted provided that the following conditions are
       9             :   met:
      10             : 
      11             :   * Redistributions of source code must retain the above copyright
      12             :   notice, this list of conditions and the following disclaimer.
      13             : 
      14             :   * Redistributions in binary form must reproduce the above copyright
      15             :   notice, this list of conditions and the following disclaimer in the
      16             :   documentation and/or other materials provided with the distribution.
      17             : 
      18             :   * Neither the name of Adobe Systems, Network Resonance, Mozilla nor
      19             :   the names of its contributors may be used to endorse or promote
      20             :   products derived from this software without specific prior written
      21             :   permission.
      22             : 
      23             :   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      24             :   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      25             :   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      26             :   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      27             :   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      28             :   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      29             :   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      30             :   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      31             :   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      32             :   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      33             :   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      34             : */
      35             : 
      36             : 
      37             : 
      38             : static char *RCSSTRING __UNUSED__="$Id: turn_client_ctx.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
      39             : 
      40             : #ifdef USE_TURN
      41             : 
      42             : #include <assert.h>
      43             : #include <string.h>
      44             : 
      45             : #include "nr_api.h"
      46             : #include "r_time.h"
      47             : #include "async_timer.h"
      48             : #include "nr_socket_buffered_stun.h"
      49             : #include "stun.h"
      50             : #include "turn_client_ctx.h"
      51             : 
      52             : int NR_LOG_TURN = 0;
      53             : 
      54             : #define TURN_MAX_PENDING_BYTES 32000
      55             : 
      56             : #define TURN_RTO 100  /* Hardcoded RTO estimate */
      57             : #define TURN_LIFETIME_REQUEST_SECONDS    3600  /* One hour */
      58             : #define TURN_USECS_PER_S                 1000000
      59             : #define TURN_REFRESH_SLACK_SECONDS       10    /* How long before expiry to refresh
      60             :                                                   allocations/permissions. The RFC 5766
      61             :                                                   Section 7 recommendation if 60 seconds,
      62             :                                                   but this is silly since the transaction
      63             :                                                   times out after about 5. */
      64             : #define TURN_PERMISSION_LIFETIME_SECONDS 300   /* 5 minutes. From RFC 5766 2.3 */
      65             : 
      66             : // Set to enable a temporary fix that will run the TURN reservation keep-alive
      67             : // logic when data is received via a TURN relayed path: a DATA_INDICATION packet is received.
      68             : // TODO(pkerr@mozilla.com) This should be replace/removed when bug 935806 is implemented.
      69             : #define REFRESH_RESERVATION_ON_RECV 1
      70             : 
      71             : static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int type,
      72             :                                    NR_async_cb success_cb,
      73             :                                    NR_async_cb failure_cb,
      74             :                                    nr_turn_stun_ctx **ctxp);
      75             : static int nr_turn_stun_ctx_destroy(nr_turn_stun_ctx **ctxp);
      76             : static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg);
      77             : static int nr_turn_stun_set_auth_params(nr_turn_stun_ctx *ctx,
      78             :                                         char *realm, char *nonce);
      79             : static void nr_turn_client_refresh_timer_cb(NR_SOCKET s, int how, void *arg);
      80             : static int nr_turn_client_refresh_setup(nr_turn_client_ctx *ctx,
      81             :                                         nr_turn_stun_ctx **sctx);
      82             : static int nr_turn_client_start_refresh_timer(nr_turn_client_ctx *ctx,
      83             :                                               nr_turn_stun_ctx *sctx,
      84             :                                               UINT4 lifetime);
      85             : static int nr_turn_permission_create(nr_turn_client_ctx *ctx,
      86             :                                      nr_transport_addr *addr,
      87             :                                      nr_turn_permission **permp);
      88             : static int nr_turn_permission_find(nr_turn_client_ctx *ctx,
      89             :                                    nr_transport_addr *addr,
      90             :                                    nr_turn_permission **permp);
      91             : static int nr_turn_permission_destroy(nr_turn_permission **permp);
      92             : static void nr_turn_client_refresh_cb(NR_SOCKET s, int how, void *arg);
      93             : static void nr_turn_client_permissions_cb(NR_SOCKET s, int how, void *cb);
      94             : static int nr_turn_client_send_stun_request(nr_turn_client_ctx *ctx,
      95             :                                             nr_stun_message *req,
      96             :                                             int flags);
      97             : 
      98             : 
      99             : /* nr_turn_stun_ctx functions */
     100           0 : static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int mode,
     101             :                                    NR_async_cb success_cb,
     102             :                                    NR_async_cb error_cb,
     103             :                                    nr_turn_stun_ctx **ctxp)
     104             : {
     105           0 :   nr_turn_stun_ctx *sctx = 0;
     106             :   int r,_status;
     107             :   char label[256];
     108             : 
     109           0 :   if (!(sctx=RCALLOC(sizeof(nr_turn_stun_ctx))))
     110           0 :     ABORT(R_NO_MEMORY);
     111             : 
     112             :   /* TODO(ekr@rtfm.com): label by phase */
     113           0 :   snprintf(label, sizeof(label), "%s:%s", tctx->label, ":TURN");
     114             : 
     115           0 :   if ((r=nr_stun_client_ctx_create(label, tctx->sock, &tctx->turn_server_addr,
     116           0 :                                    TURN_RTO, &sctx->stun))) {
     117           0 :     ABORT(r);
     118             :   }
     119             : 
     120             :   /* Set the STUN auth parameters, but don't set authentication on.
     121             :      For that we need the nonce, set in nr_turn_stun_set_auth_params.
     122             :   */
     123           0 :   sctx->stun->auth_params.username=tctx->username;
     124           0 :   INIT_DATA(sctx->stun->auth_params.password,
     125             :             tctx->password->data, tctx->password->len);
     126             : 
     127           0 :   sctx->tctx=tctx;
     128           0 :   sctx->success_cb=success_cb;
     129           0 :   sctx->error_cb=error_cb;
     130           0 :   sctx->mode=mode;
     131           0 :   sctx->last_error_code=0;
     132             : 
     133             :   /* Add ourselves to the tctx's list */
     134           0 :   STAILQ_INSERT_TAIL(&tctx->stun_ctxs, sctx, entry);
     135           0 :   *ctxp=sctx;
     136             : 
     137           0 :   _status=0;
     138             : abort:
     139           0 :   if (_status) {
     140           0 :     nr_turn_stun_ctx_destroy(&sctx);
     141             :   }
     142           0 :   return(_status);
     143             : }
     144             : 
     145             : /* Note: this function does not pull us off the tctx's list. */
     146           0 : static int nr_turn_stun_ctx_destroy(nr_turn_stun_ctx **ctxp)
     147             : {
     148             :   nr_turn_stun_ctx *ctx;
     149             : 
     150           0 :   if (!ctxp || !*ctxp)
     151           0 :     return 0;
     152             : 
     153           0 :   ctx = *ctxp;
     154           0 :   *ctxp = 0;
     155             : 
     156           0 :   nr_stun_client_ctx_destroy(&ctx->stun);
     157           0 :   RFREE(ctx->realm);
     158           0 :   RFREE(ctx->nonce);
     159             : 
     160           0 :   RFREE(ctx);
     161             : 
     162           0 :   return 0;
     163             : }
     164             : 
     165           0 : static int nr_turn_stun_set_auth_params(nr_turn_stun_ctx *ctx,
     166             :                                         char *realm, char *nonce)
     167             : {
     168             :   int _status;
     169             : 
     170           0 :   RFREE(ctx->realm);
     171           0 :   RFREE(ctx->nonce);
     172             : 
     173           0 :   assert(realm);
     174           0 :   if (!realm)
     175           0 :     ABORT(R_BAD_ARGS);
     176           0 :   ctx->realm=r_strdup(realm);
     177           0 :   if (!ctx->realm)
     178           0 :     ABORT(R_NO_MEMORY);
     179             : 
     180           0 :   assert(nonce);
     181           0 :   if (!nonce)
     182           0 :     ABORT(R_BAD_ARGS);
     183           0 :   ctx->nonce=r_strdup(nonce);
     184           0 :   if (!ctx->nonce)
     185           0 :     ABORT(R_NO_MEMORY);
     186             : 
     187           0 :   RFREE(ctx->stun->realm);
     188           0 :   ctx->stun->realm = r_strdup(ctx->realm);
     189           0 :   if (!ctx->stun->realm)
     190           0 :     ABORT(R_NO_MEMORY);
     191             : 
     192           0 :   ctx->stun->auth_params.realm = ctx->realm;
     193           0 :   ctx->stun->auth_params.nonce = ctx->nonce;
     194           0 :   ctx->stun->auth_params.authenticate = 1;  /* May already be 1 */
     195             : 
     196           0 :   _status=0;
     197             : abort:
     198           0 :   return(_status);
     199             : }
     200             : 
     201           0 : static int nr_turn_stun_ctx_start(nr_turn_stun_ctx *ctx)
     202             : {
     203             :   int r, _status;
     204           0 :   nr_turn_client_ctx *tctx = ctx->tctx;
     205             : 
     206           0 :   if ((r=nr_stun_client_reset(ctx->stun))) {
     207           0 :     r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't reset STUN",
     208             :           tctx->label);
     209           0 :     ABORT(r);
     210             :   }
     211             : 
     212           0 :   if ((r=nr_stun_client_start(ctx->stun, ctx->mode, nr_turn_stun_ctx_cb, ctx))) {
     213           0 :     r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't start STUN",
     214             :           tctx->label);
     215           0 :     ABORT(r);
     216             :   }
     217             : 
     218           0 :   _status=0;
     219             : abort:
     220           0 :   return _status;
     221             : }
     222             : 
     223           0 : static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg)
     224             : {
     225             :   int r, _status;
     226           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
     227             : 
     228           0 :   ctx->last_error_code = ctx->stun->error_code;
     229             : 
     230           0 :   switch (ctx->stun->state) {
     231             :     case NR_STUN_CLIENT_STATE_DONE:
     232             :       /* Save the realm and nonce */
     233           0 :       if (ctx->stun->realm && (!ctx->tctx->realm || strcmp(ctx->stun->realm,
     234           0 :                                                            ctx->tctx->realm))) {
     235           0 :         RFREE(ctx->tctx->realm);
     236           0 :         ctx->tctx->realm = r_strdup(ctx->stun->realm);
     237           0 :         if (!ctx->tctx->realm)
     238           0 :           ABORT(R_NO_MEMORY);
     239             :       }
     240           0 :       if (ctx->stun->nonce && (!ctx->tctx->nonce || strcmp(ctx->stun->nonce,
     241           0 :                                                            ctx->tctx->nonce))) {
     242           0 :         RFREE(ctx->tctx->nonce);
     243           0 :         ctx->tctx->nonce = r_strdup(ctx->stun->nonce);
     244           0 :         if (!ctx->tctx->nonce)
     245           0 :           ABORT(R_NO_MEMORY);
     246             :       }
     247             : 
     248           0 :       ctx->retry_ct=0;
     249           0 :       ctx->success_cb(0, 0, ctx);
     250           0 :       break;
     251             : 
     252             :     case NR_STUN_CLIENT_STATE_FAILED:
     253             :       /* Special case: if this is an authentication error,
     254             :          we retry once. This allows the 401/438 nonce retry
     255             :          paradigm. After that, we fail */
     256             :       /* TODO(ekr@rtfm.com): 401 needs a #define */
     257             :       /* TODO(ekr@rtfm.com): Add alternate-server (Mozilla bug 857688) */
     258           0 :       if (ctx->stun->error_code == 438) {
     259             :         // track 438s for ice telemetry
     260           0 :         nr_ice_accumulate_count(&(ctx->tctx->cnt_438s), 1);
     261             :       }
     262           0 :       if (ctx->stun->error_code == 401 || ctx->stun->error_code == 438) {
     263           0 :         if (ctx->retry_ct > 0) {
     264           0 :           if (ctx->stun->error_code == 401) {
     265             :             // track 401s for ice telemetry
     266           0 :             nr_ice_accumulate_count(&(ctx->tctx->cnt_401s), 1);
     267             :           }
     268           0 :           r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): Exceeded the number of retries", ctx->tctx->label);
     269           0 :           ABORT(R_FAILED);
     270             :         }
     271             : 
     272           0 :         if (!ctx->stun->nonce) {
     273           0 :           r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): 401 but no nonce", ctx->tctx->label);
     274           0 :           ABORT(R_FAILED);
     275             :         }
     276           0 :         if (!ctx->stun->realm) {
     277           0 :           r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): 401 but no realm", ctx->tctx->label);
     278           0 :           ABORT(R_FAILED);
     279             :         }
     280             : 
     281             :         /* Try to retry */
     282           0 :         if ((r=nr_turn_stun_set_auth_params(ctx, ctx->stun->realm,
     283           0 :                                             ctx->stun->nonce)))
     284           0 :           ABORT(r);
     285             : 
     286           0 :         ctx->stun->error_code = 0;  /* Reset to avoid inf-looping */
     287             : 
     288           0 :         if ((r=nr_turn_stun_ctx_start(ctx))) {
     289           0 :           r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't start STUN", ctx->tctx->label);
     290           0 :           ABORT(r);
     291             :         }
     292             : 
     293           0 :         ctx->retry_ct++;
     294             :       }
     295             :       else {
     296           0 :         ABORT(R_FAILED);
     297             :       }
     298           0 :       break;
     299             : 
     300             :     case NR_STUN_CLIENT_STATE_TIMED_OUT:
     301           0 :       ABORT(R_FAILED);
     302             :       break;
     303             : 
     304             :     case NR_STUN_CLIENT_STATE_CANCELLED:
     305           0 :       assert(0);  /* Shouldn't happen */
     306             :       return;
     307             :       break;
     308             : 
     309             :     default:
     310           0 :       assert(0);  /* Shouldn't happen */
     311             :       return;
     312             :   }
     313             : 
     314           0 :   _status=0;
     315             : abort:
     316           0 :   if (_status) {
     317           0 :     ctx->error_cb(0, 0, ctx);
     318             :   }
     319           0 : }
     320             : 
     321             : /* nr_turn_client_ctx functions */
     322           0 : int nr_turn_client_ctx_create(const char *label, nr_socket *sock,
     323             :                               const char *username, Data *password,
     324             :                               nr_transport_addr *addr,
     325             :                               nr_turn_client_ctx **ctxp)
     326             : {
     327           0 :   nr_turn_client_ctx *ctx=0;
     328             :   int r,_status;
     329             : 
     330           0 :   if ((r=r_log_register("turn", &NR_LOG_TURN)))
     331           0 :     ABORT(r);
     332             : 
     333           0 :   if(!(ctx=RCALLOC(sizeof(nr_turn_client_ctx))))
     334           0 :     ABORT(R_NO_MEMORY);
     335             : 
     336           0 :   STAILQ_INIT(&ctx->stun_ctxs);
     337           0 :   STAILQ_INIT(&ctx->permissions);
     338             : 
     339           0 :   if(!(ctx->label=r_strdup(label)))
     340           0 :     ABORT(R_NO_MEMORY);
     341             : 
     342           0 :   ctx->sock=sock;
     343           0 :   ctx->username = r_strdup(username);
     344           0 :   if (!ctx->username)
     345           0 :     ABORT(R_NO_MEMORY);
     346             : 
     347           0 :   if ((r=r_data_create(&ctx->password, password->data, password->len)))
     348           0 :     ABORT(r);
     349           0 :   if ((r=nr_transport_addr_copy(&ctx->turn_server_addr, addr)))
     350           0 :     ABORT(r);
     351             : 
     352           0 :   ctx->state = NR_TURN_CLIENT_STATE_INITTED;
     353           0 :   if (addr->protocol == IPPROTO_TCP) {
     354           0 :     if ((r=nr_socket_connect(ctx->sock, &ctx->turn_server_addr))) {
     355           0 :       if (r != R_WOULDBLOCK)
     356           0 :         ABORT(r);
     357             :     }
     358             :   }
     359             : 
     360           0 :   *ctxp=ctx;
     361             : 
     362           0 :   _status=0;
     363             : abort:
     364           0 :   if(_status){
     365           0 :     nr_turn_client_ctx_destroy(&ctx);
     366             :   }
     367           0 :   return(_status);
     368             : }
     369             : 
     370             : int
     371           0 : nr_turn_client_ctx_destroy(nr_turn_client_ctx **ctxp)
     372             : {
     373             :   nr_turn_client_ctx *ctx;
     374             : 
     375           0 :   if(!ctxp || !*ctxp)
     376           0 :     return(0);
     377             : 
     378           0 :   ctx=*ctxp;
     379           0 :   *ctxp = 0;
     380             : 
     381           0 :   if (ctx->label)
     382           0 :     r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): destroy", ctx->label);
     383             : 
     384           0 :   nr_turn_client_deallocate(ctx);
     385             : 
     386             :   /* Cancel frees the rest of our data */
     387           0 :   RFREE(ctx->label);
     388           0 :   ctx->label = 0;
     389             : 
     390           0 :   nr_turn_client_cancel(ctx);
     391             : 
     392           0 :   RFREE(ctx->username);
     393           0 :   ctx->username = 0;
     394           0 :   r_data_destroy(&ctx->password);
     395           0 :   RFREE(ctx->nonce);
     396           0 :   ctx->nonce = 0;
     397           0 :   RFREE(ctx->realm);
     398           0 :   ctx->realm = 0;
     399             : 
     400             :   /* Destroy the STUN client ctxs */
     401           0 :   while (!STAILQ_EMPTY(&ctx->stun_ctxs)) {
     402           0 :     nr_turn_stun_ctx *stun = STAILQ_FIRST(&ctx->stun_ctxs);
     403           0 :     STAILQ_REMOVE_HEAD(&ctx->stun_ctxs, entry);
     404           0 :     nr_turn_stun_ctx_destroy(&stun);
     405             :   }
     406             : 
     407             :   /* Destroy the permissions */
     408           0 :   while (!STAILQ_EMPTY(&ctx->permissions)) {
     409           0 :     nr_turn_permission *perm = STAILQ_FIRST(&ctx->permissions);
     410           0 :     STAILQ_REMOVE_HEAD(&ctx->permissions, entry);
     411           0 :     nr_turn_permission_destroy(&perm);
     412             :   }
     413             : 
     414           0 :   RFREE(ctx);
     415             : 
     416           0 :   return(0);
     417             : }
     418             : 
     419           0 : int nr_turn_client_cancel(nr_turn_client_ctx *ctx)
     420             : {
     421           0 :   nr_turn_stun_ctx *stun = 0;
     422             : 
     423           0 :   if (ctx->state == NR_TURN_CLIENT_STATE_CANCELLED ||
     424           0 :       ctx->state == NR_TURN_CLIENT_STATE_FAILED)
     425           0 :     return(0);
     426             : 
     427           0 :   if (ctx->label)
     428           0 :     r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): cancelling", ctx->label);
     429             : 
     430             :   /* Cancel the STUN client ctxs */
     431           0 :   stun = STAILQ_FIRST(&ctx->stun_ctxs);
     432           0 :   while (stun) {
     433           0 :     nr_stun_client_cancel(stun->stun);
     434           0 :     stun = STAILQ_NEXT(stun, entry);
     435             :   }
     436             : 
     437             :   /* Cancel the timers, if not already cancelled */
     438           0 :   NR_async_timer_cancel(ctx->connected_timer_handle);
     439           0 :   NR_async_timer_cancel(ctx->refresh_timer_handle);
     440             : 
     441           0 :   ctx->state = NR_TURN_CLIENT_STATE_CANCELLED;
     442             : 
     443           0 :   return(0);
     444             : }
     445             : 
     446           0 : int nr_turn_client_send_stun_request(nr_turn_client_ctx *ctx,
     447             :                                      nr_stun_message *req,
     448             :                                      int flags)
     449             : {
     450             :   int r,_status;
     451             : 
     452           0 :   if ((r=nr_stun_encode_message(req)))
     453           0 :     ABORT(r);
     454             : 
     455           0 :   if ((r=nr_socket_sendto(ctx->sock,
     456           0 :                           req->buffer, req->length, flags,
     457             :                           &ctx->turn_server_addr))) {
     458           0 :     r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): Failed sending request",
     459             :           ctx->label);
     460           0 :     ABORT(r);
     461             :   }
     462             : 
     463           0 :   _status=0;
     464             : abort:
     465           0 :   return(_status);
     466             : }
     467             : 
     468           0 : int nr_turn_client_deallocate(nr_turn_client_ctx *ctx)
     469             : {
     470             :   int r,_status;
     471           0 :   nr_stun_message *aloc = 0;
     472             :   nr_stun_client_auth_params auth;
     473             :   nr_stun_client_refresh_request_params refresh;
     474             : 
     475           0 :   if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
     476           0 :     return(0);
     477             : 
     478           0 :   r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): deallocating", ctx->label);
     479             : 
     480           0 :   refresh.lifetime_secs = 0;
     481             : 
     482           0 :   auth.username = ctx->username;
     483           0 :   INIT_DATA(auth.password, ctx->password->data, ctx->password->len);
     484             : 
     485           0 :   auth.realm = ctx->realm;
     486           0 :   auth.nonce = ctx->nonce;
     487             : 
     488           0 :   auth.authenticate = 1;
     489             : 
     490           0 :   if ((r=nr_stun_build_refresh_request(&auth, &refresh, &aloc)))
     491           0 :     ABORT(r);
     492             : 
     493             :   // We are only sending a single request here because we are in the process of
     494             :   // shutting everything down. Theoretically we should probably start a seperate
     495             :   // STUN transaction which outlives the TURN context.
     496           0 :   if ((r=nr_turn_client_send_stun_request(ctx, aloc, 0)))
     497           0 :     ABORT(r);
     498             : 
     499           0 :   ctx->state = NR_TURN_CLIENT_STATE_DEALLOCATING;
     500             : 
     501           0 :   _status=0;
     502             : abort:
     503           0 :   nr_stun_message_destroy(&aloc);
     504           0 :   return(_status);
     505             : }
     506             : 
     507           0 : static void nr_turn_client_fire_finished_cb(nr_turn_client_ctx *ctx)
     508             :   {
     509           0 :     if (ctx->finished_cb) {
     510           0 :       NR_async_cb finished_cb=ctx->finished_cb;
     511           0 :       ctx->finished_cb=0;
     512           0 :       finished_cb(0, 0, ctx->cb_arg);
     513             :     }
     514           0 :   }
     515             : 
     516           0 : int nr_turn_client_failed(nr_turn_client_ctx *ctx)
     517             : {
     518           0 :   if (ctx->state == NR_TURN_CLIENT_STATE_FAILED ||
     519           0 :       ctx->state == NR_TURN_CLIENT_STATE_CANCELLED)
     520           0 :     return(0);
     521             : 
     522           0 :   r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s) failed", ctx->label);
     523           0 :   nr_turn_client_cancel(ctx);
     524           0 :   ctx->state = NR_TURN_CLIENT_STATE_FAILED;
     525           0 :   nr_turn_client_fire_finished_cb(ctx);
     526             : 
     527           0 :   return(0);
     528             : }
     529             : 
     530           0 : int nr_turn_client_get_relayed_address(nr_turn_client_ctx *ctx,
     531             :                                        nr_transport_addr *relayed_address)
     532             : {
     533             :   int r, _status;
     534             : 
     535           0 :   if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
     536           0 :     ABORT(R_FAILED);
     537             : 
     538           0 :   if (r=nr_transport_addr_copy(relayed_address, &ctx->relay_addr))
     539           0 :     ABORT(r);
     540             : 
     541           0 :   _status=0;
     542             : abort:
     543           0 :   return(_status);
     544             : }
     545             : 
     546           0 : int nr_turn_client_get_mapped_address(nr_turn_client_ctx *ctx,
     547             :                                        nr_transport_addr *mapped_address)
     548             : {
     549             :   int r, _status;
     550             : 
     551           0 :   if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
     552           0 :     ABORT(R_FAILED);
     553             : 
     554           0 :   if (r=nr_transport_addr_copy(mapped_address, &ctx->mapped_addr))
     555           0 :     ABORT(r);
     556             : 
     557           0 :   _status=0;
     558             : abort:
     559           0 :   return(_status);
     560             : }
     561             : 
     562           0 : static void nr_turn_client_allocate_cb(NR_SOCKET s, int how, void *arg)
     563             : {
     564           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
     565             :   nr_turn_stun_ctx *refresh_ctx;
     566             :   int r,_status;
     567             : 
     568           0 :   ctx->tctx->state = NR_TURN_CLIENT_STATE_ALLOCATED;
     569             : 
     570           0 :   if ((r=nr_transport_addr_copy(
     571           0 :           &ctx->tctx->relay_addr,
     572           0 :           &ctx->stun->results.allocate_response.relay_addr)))
     573           0 :     ABORT(r);
     574             : 
     575           0 :   if ((r=nr_transport_addr_copy(
     576           0 :           &ctx->tctx->mapped_addr,
     577           0 :           &ctx->stun->results.allocate_response.mapped_addr)))
     578           0 :     ABORT(r);
     579             : 
     580           0 :   if ((r=nr_turn_client_refresh_setup(ctx->tctx, &refresh_ctx)))
     581           0 :     ABORT(r);
     582             : 
     583           0 :   if ((r=nr_turn_client_start_refresh_timer(
     584           0 :           ctx->tctx, refresh_ctx,
     585           0 :           ctx->stun->results.allocate_response.lifetime_secs)))
     586           0 :     ABORT(r);
     587             : 
     588           0 :   r_log(NR_LOG_TURN, LOG_INFO,
     589             :         "TURN(%s): Succesfully allocated addr %s lifetime=%u",
     590           0 :         ctx->tctx->label,
     591           0 :         ctx->tctx->relay_addr.as_string,
     592           0 :         ctx->stun->results.allocate_response.lifetime_secs);
     593             : 
     594           0 :   nr_turn_client_fire_finished_cb(ctx->tctx);
     595           0 :   _status=0;
     596             : abort:
     597           0 :   if (_status) {
     598           0 :     nr_turn_client_failed(ctx->tctx);
     599             :   }
     600           0 : }
     601             : 
     602           0 : static void nr_turn_client_error_cb(NR_SOCKET s, int how, void *arg)
     603             : {
     604           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
     605             : 
     606           0 :   r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, %s",
     607           0 :         ctx->tctx->label, ctx->mode, __FUNCTION__);
     608             : 
     609           0 :   nr_turn_client_failed(ctx->tctx);
     610           0 : }
     611             : 
     612           0 : static void nr_turn_client_permission_error_cb(NR_SOCKET s, int how, void *arg)
     613             : {
     614           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
     615             : 
     616           0 :   if (ctx->last_error_code == 403) {
     617             :     // track 403s for ice telemetry
     618           0 :     nr_ice_accumulate_count(&(ctx->tctx->cnt_403s), 1);
     619           0 :     r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, permission denied",
     620           0 :           ctx->tctx->label, ctx->mode);
     621             : 
     622             :   } else{
     623           0 :     nr_turn_client_error_cb(0, 0, ctx);
     624             :   }
     625           0 : }
     626             : 
     627           0 : int nr_turn_client_allocate(nr_turn_client_ctx *ctx,
     628             :                             NR_async_cb finished_cb, void *cb_arg)
     629             : {
     630           0 :   nr_turn_stun_ctx *stun = 0;
     631             :   int r,_status;
     632             : 
     633           0 :   if(ctx->state == NR_TURN_CLIENT_STATE_FAILED ||
     634           0 :      ctx->state == NR_TURN_CLIENT_STATE_CANCELLED){
     635             :     /* TURN TCP contexts can fail before we ever try to form an allocation,
     636             :      * since the TCP connection can fail. It is also conceivable that a TURN
     637             :      * TCP context could be cancelled before we are done forming all
     638             :      * allocations (although we do not do this at the time this code was
     639             :      * written) */
     640           0 :     assert(ctx->turn_server_addr.protocol == IPPROTO_TCP);
     641           0 :     ABORT(R_NOT_FOUND);
     642             :   }
     643             : 
     644           0 :   assert(ctx->state == NR_TURN_CLIENT_STATE_INITTED);
     645             : 
     646           0 :   ctx->finished_cb=finished_cb;
     647           0 :   ctx->cb_arg=cb_arg;
     648             : 
     649           0 :   if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST,
     650             :                                  nr_turn_client_allocate_cb,
     651             :                                  nr_turn_client_error_cb,
     652             :                                  &stun)))
     653           0 :     ABORT(r);
     654           0 :   stun->stun->params.allocate_request.lifetime_secs =
     655             :       TURN_LIFETIME_REQUEST_SECONDS;
     656             : 
     657           0 :   if (ctx->state == NR_TURN_CLIENT_STATE_INITTED) {
     658           0 :       if ((r=nr_turn_stun_ctx_start(stun)))
     659           0 :         ABORT(r);
     660           0 :       ctx->state = NR_TURN_CLIENT_STATE_ALLOCATING;
     661             :   } else {
     662           0 :       ABORT(R_ALREADY);
     663             :   }
     664             : 
     665           0 :   _status=0;
     666             : abort:
     667           0 :   if (_status) {
     668           0 :     nr_turn_client_failed(ctx);
     669             :   }
     670             : 
     671           0 :   return(_status);
     672             : }
     673             : 
     674           0 : int nr_turn_client_process_response(nr_turn_client_ctx *ctx,
     675             :                                     UCHAR *msg, int len,
     676             :                                     nr_transport_addr *turn_server_addr)
     677             : {
     678             :   int r, _status;
     679             :   nr_turn_stun_ctx *sc1;
     680             : 
     681           0 :   switch (ctx->state) {
     682             :     case NR_TURN_CLIENT_STATE_ALLOCATING:
     683             :     case NR_TURN_CLIENT_STATE_ALLOCATED:
     684           0 :       break;
     685             :     default:
     686           0 :       ABORT(R_FAILED);
     687             :   }
     688             : 
     689           0 :   sc1 = STAILQ_FIRST(&ctx->stun_ctxs);
     690           0 :   while (sc1) {
     691           0 :     r = nr_stun_client_process_response(sc1->stun, msg, len, turn_server_addr);
     692           0 :     if (!r)
     693           0 :       break;
     694           0 :     if (r==R_RETRY)  /* Likely a 401 and we will retry */
     695           0 :       break;
     696           0 :     if (r != R_REJECTED)
     697           0 :       ABORT(r);
     698           0 :     sc1 = STAILQ_NEXT(sc1, entry);
     699             :   }
     700           0 :   if (!sc1)
     701           0 :     ABORT(R_REJECTED);
     702             : 
     703           0 :   _status=0;
     704             : abort:
     705           0 :   return(_status);
     706             : }
     707             : 
     708           0 : static int nr_turn_client_refresh_setup(nr_turn_client_ctx *ctx,
     709             :                                         nr_turn_stun_ctx **sctx)
     710             : {
     711           0 :   nr_turn_stun_ctx *stun = 0;
     712             :   int r,_status;
     713             : 
     714           0 :   assert(ctx->state == NR_TURN_CLIENT_STATE_ALLOCATED);
     715           0 :   if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
     716           0 :     ABORT(R_NOT_PERMITTED);
     717             : 
     718           0 :   if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_REFRESH_REQUEST,
     719             :                                  nr_turn_client_refresh_cb,
     720             :                                  nr_turn_client_error_cb,
     721             :                                  &stun)))
     722           0 :     ABORT(r);
     723             : 
     724           0 :   if ((r=nr_turn_stun_set_auth_params(stun, ctx->realm, ctx->nonce)))
     725           0 :     ABORT(r);
     726             : 
     727           0 :   stun->stun->params.refresh_request.lifetime_secs =
     728             :       TURN_LIFETIME_REQUEST_SECONDS;
     729             : 
     730             : 
     731           0 :   *sctx=stun;
     732             : 
     733           0 :   _status=0;
     734             : abort:
     735           0 :   return(_status);
     736             : }
     737             : 
     738           0 : static int nr_turn_client_start_refresh_timer(nr_turn_client_ctx *tctx,
     739             :                                               nr_turn_stun_ctx *sctx,
     740             :                                               UINT4 lifetime)
     741             : {
     742             :   int _status;
     743             : 
     744           0 :   assert(!tctx->refresh_timer_handle);
     745             : 
     746           0 :   if (lifetime <= TURN_REFRESH_SLACK_SECONDS) {
     747           0 :     r_log(NR_LOG_TURN, LOG_ERR, "Too short lifetime specified for turn %u", lifetime);
     748           0 :     ABORT(R_BAD_DATA);
     749             :   }
     750             : 
     751           0 :   if (lifetime > 3600)
     752           0 :     lifetime = 3600;
     753             : 
     754           0 :   lifetime -= TURN_REFRESH_SLACK_SECONDS;
     755             : 
     756           0 :   r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Setting refresh timer for %u seconds",
     757             :         tctx->label, lifetime);
     758           0 :   NR_ASYNC_TIMER_SET(lifetime * 1000, nr_turn_client_refresh_timer_cb, sctx,
     759             :                      &tctx->refresh_timer_handle);
     760             : 
     761           0 :   _status=0;
     762             : abort:
     763           0 :   if (_status) {
     764           0 :     nr_turn_client_failed(tctx);
     765             :   }
     766           0 :   return _status;
     767             : }
     768             : 
     769           0 : static void nr_turn_client_refresh_timer_cb(NR_SOCKET s, int how, void *arg)
     770             : {
     771           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
     772             :   int r,_status;
     773             : 
     774           0 :   r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Refresh timer fired",
     775           0 :         ctx->tctx->label);
     776             : 
     777           0 :   ctx->tctx->refresh_timer_handle=0;
     778           0 :   if ((r=nr_turn_stun_ctx_start(ctx))) {
     779           0 :     ABORT(r);
     780             :   }
     781             : 
     782           0 :   _status=0;
     783             : abort:
     784           0 :   if (_status) {
     785           0 :     nr_turn_client_failed(ctx->tctx);
     786             :   }
     787           0 :   return;
     788             : }
     789             : 
     790           0 : static void nr_turn_client_refresh_cb(NR_SOCKET s, int how, void *arg)
     791             : {
     792             :   int r, _status;
     793           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
     794             :   /* Save lifetime from the reset */
     795           0 :   UINT4 lifetime = ctx->stun->results.refresh_response.lifetime_secs;
     796             : 
     797           0 :   r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Refresh succeeded. lifetime=%u",
     798           0 :         ctx->tctx->label, lifetime);
     799             : 
     800           0 :   if ((r=nr_turn_client_start_refresh_timer(
     801           0 :           ctx->tctx, ctx, lifetime)))
     802           0 :     ABORT(r);
     803             : 
     804           0 :   _status=0;
     805             : 
     806             : abort:
     807           0 :   if (_status) {
     808           0 :     nr_turn_client_failed(ctx->tctx);
     809             :   }
     810           0 : }
     811             : 
     812             : /* TODO(ekr@rtfm.com): We currently don't support channels.
     813             :    We might in the future. Mozilla bug 857736 */
     814           0 : int nr_turn_client_send_indication(nr_turn_client_ctx *ctx,
     815             :                                    const UCHAR *msg, size_t len,
     816             :                                    int flags, nr_transport_addr *remote_addr)
     817             : {
     818             :   int r,_status;
     819           0 :   nr_stun_client_send_indication_params params = { { 0 } };
     820           0 :   nr_stun_message *ind = 0;
     821             : 
     822           0 :   if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
     823           0 :     ABORT(R_FAILED);
     824             : 
     825           0 :   r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Send indication len=%zu",
     826             :         ctx->label, len);
     827             : 
     828           0 :   if ((r=nr_turn_client_ensure_perm(ctx, remote_addr)))
     829           0 :     ABORT(r);
     830             : 
     831           0 :   if ((r=nr_transport_addr_copy(&params.remote_addr, remote_addr)))
     832           0 :     ABORT(r);
     833             : 
     834           0 :   params.data.data = (UCHAR*)msg;
     835           0 :   params.data.len = len;
     836             : 
     837           0 :   if ((r=nr_stun_build_send_indication(&params, &ind)))
     838           0 :     ABORT(r);
     839             : 
     840           0 :   if ((r=nr_turn_client_send_stun_request(ctx, ind, flags)))
     841           0 :     ABORT(r);
     842             : 
     843           0 :   _status=0;
     844             : abort:
     845           0 :   nr_stun_message_destroy(&ind);
     846           0 :   return(_status);
     847             : }
     848             : 
     849           0 : int nr_turn_client_parse_data_indication(nr_turn_client_ctx *ctx,
     850             :                                          nr_transport_addr *source_addr,
     851             :                                          UCHAR *msg, size_t len,
     852             :                                          UCHAR *newmsg, size_t *newlen,
     853             :                                          size_t newsize,
     854             :                                          nr_transport_addr *remote_addr)
     855             : {
     856             :   int r,_status;
     857           0 :   nr_stun_message *ind=0;
     858             :   nr_stun_message_attribute *attr;
     859             :   nr_turn_permission *perm;
     860             : 
     861           0 :   if (nr_transport_addr_cmp(&ctx->turn_server_addr, source_addr,
     862             :                             NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
     863           0 :     r_log(NR_LOG_TURN, LOG_WARNING,
     864             :           "TURN(%s): Indication from unexpected source addr %s (expected %s)",
     865           0 :           ctx->label, source_addr->as_string, ctx->turn_server_addr.as_string);
     866           0 :     ABORT(R_REJECTED);
     867             :   }
     868             : 
     869           0 :   if ((r=nr_stun_message_create2(&ind, msg, len)))
     870           0 :     ABORT(r);
     871           0 :   if ((r=nr_stun_decode_message(ind, 0, 0)))
     872           0 :     ABORT(r);
     873             : 
     874           0 :   if (ind->header.type != NR_STUN_MSG_DATA_INDICATION)
     875           0 :     ABORT(R_BAD_ARGS);
     876             : 
     877           0 :   if (!nr_stun_message_has_attribute(ind, NR_STUN_ATTR_XOR_PEER_ADDRESS, &attr))
     878           0 :     ABORT(R_BAD_ARGS);
     879             : 
     880           0 :   if ((r=nr_turn_permission_find(ctx, &attr->u.xor_mapped_address.unmasked,
     881             :                                  &perm))) {
     882           0 :     if (r == R_NOT_FOUND) {
     883           0 :       r_log(NR_LOG_TURN, LOG_WARNING,
     884             :             "TURN(%s): Indication from peer addr %s with no permission",
     885           0 :             ctx->label, attr->u.xor_mapped_address.unmasked.as_string);
     886             :     }
     887           0 :     ABORT(r);
     888             :   }
     889             : 
     890           0 :   if ((r=nr_transport_addr_copy(remote_addr,
     891           0 :                                 &attr->u.xor_mapped_address.unmasked)))
     892           0 :     ABORT(r);
     893             : 
     894             : #if REFRESH_RESERVATION_ON_RECV
     895           0 :   if ((r=nr_turn_client_ensure_perm(ctx, remote_addr))) {
     896           0 :     ABORT(r);
     897             :   }
     898             : #endif
     899             : 
     900           0 :   if (!nr_stun_message_has_attribute(ind, NR_STUN_ATTR_DATA, &attr)) {
     901           0 :     ABORT(R_BAD_DATA);
     902             :   }
     903             : 
     904           0 :   assert(newsize >= attr->u.data.length);
     905           0 :   if (newsize < attr->u.data.length)
     906           0 :     ABORT(R_BAD_ARGS);
     907             : 
     908           0 :   memcpy(newmsg, attr->u.data.data, attr->u.data.length);
     909           0 :   *newlen = attr->u.data.length;
     910             : 
     911           0 :   _status=0;
     912             : abort:
     913           0 :   nr_stun_message_destroy(&ind);
     914           0 :   return(_status);
     915             : }
     916             : 
     917             : 
     918             : 
     919             : /* The permissions model is as follows:
     920             : 
     921             :    - We keep a list of all the permissions we have ever requested
     922             :      along with when they were last established.
     923             :    - Whenever someone sends a packet, we automatically create/
     924             :      refresh the permission.
     925             : 
     926             :    This means that permissions automatically time out if
     927             :    unused.
     928             : 
     929             : */
     930           0 : int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx, nr_transport_addr *addr)
     931             : {
     932             :   int r, _status;
     933           0 :   nr_turn_permission *perm = 0;
     934             :   UINT8 now;
     935           0 :   UINT8 turn_permission_refresh = (TURN_PERMISSION_LIFETIME_SECONDS -
     936             :                                    TURN_REFRESH_SLACK_SECONDS) * TURN_USECS_PER_S;
     937             : 
     938           0 :   if ((r=nr_turn_permission_find(ctx, addr, &perm))) {
     939           0 :     if (r == R_NOT_FOUND) {
     940           0 :       if ((r=nr_turn_permission_create(ctx, addr, &perm)))
     941           0 :         ABORT(r);
     942             :     }
     943             :     else {
     944           0 :       ABORT(r);
     945             :     }
     946             :   }
     947             : 
     948           0 :   assert(perm);
     949             : 
     950             :   /* Now check that the permission is up-to-date */
     951           0 :   now = r_gettimeint();
     952             : 
     953           0 :   if ((now - perm->last_used) > turn_permission_refresh) {
     954           0 :     r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Permission for %s requires refresh",
     955           0 :           ctx->label, perm->addr.as_string);
     956             : 
     957           0 :     if ((r=nr_turn_stun_ctx_start(perm->stun)))
     958           0 :       ABORT(r);
     959             : 
     960           0 :     perm->last_used = now;  /* Update the time now so we don't retry on
     961             :                                next packet */
     962             :   }
     963             : 
     964           0 :   _status=0;
     965             : abort:
     966           0 :   return(_status);
     967             : }
     968             : 
     969           0 : static int nr_turn_permission_create(nr_turn_client_ctx *ctx, nr_transport_addr *addr,
     970             :                                      nr_turn_permission **permp)
     971             : {
     972             :   int r, _status;
     973           0 :   nr_turn_permission *perm = 0;
     974             : 
     975           0 :   assert(ctx->state == NR_TURN_CLIENT_STATE_ALLOCATED);
     976             : 
     977           0 :   r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): Creating permission for %s",
     978           0 :         ctx->label, addr->as_string);
     979             : 
     980           0 :   if (!(perm = RCALLOC(sizeof(nr_turn_permission))))
     981           0 :     ABORT(R_NO_MEMORY);
     982             : 
     983           0 :   if ((r=nr_transport_addr_copy(&perm->addr, addr)))
     984           0 :     ABORT(r);
     985             : 
     986           0 :   perm->last_used = 0;
     987             : 
     988           0 :   if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_PERMISSION_REQUEST,
     989             :                                  nr_turn_client_permissions_cb,
     990             :                                  nr_turn_client_permission_error_cb,
     991           0 :                                  &perm->stun)))
     992           0 :     ABORT(r);
     993             : 
     994             :   /* We want to authenticate on the first packet */
     995           0 :   if ((r=nr_turn_stun_set_auth_params(perm->stun, ctx->realm, ctx->nonce)))
     996           0 :     ABORT(r);
     997             : 
     998           0 :   if ((r=nr_transport_addr_copy(
     999           0 :           &perm->stun->stun->params.permission_request.remote_addr, addr)))
    1000           0 :     ABORT(r);
    1001           0 :   STAILQ_INSERT_TAIL(&ctx->permissions, perm, entry);
    1002             : 
    1003           0 :   *permp = perm;
    1004             : 
    1005           0 :   _status=0;
    1006             : abort:
    1007           0 :   if (_status) {
    1008           0 :     nr_turn_permission_destroy(&perm);
    1009             :   }
    1010           0 :   return(_status);
    1011             : }
    1012             : 
    1013             : 
    1014           0 : static int nr_turn_permission_find(nr_turn_client_ctx *ctx, nr_transport_addr *addr,
    1015             :                                    nr_turn_permission **permp)
    1016             : {
    1017             :   nr_turn_permission *perm;
    1018             :   int _status;
    1019             : 
    1020           0 :   perm = STAILQ_FIRST(&ctx->permissions);
    1021           0 :   while (perm) {
    1022           0 :     if (!nr_transport_addr_cmp(&perm->addr, addr,
    1023             :                                NR_TRANSPORT_ADDR_CMP_MODE_ADDR))
    1024           0 :       break;
    1025             : 
    1026           0 :     perm = STAILQ_NEXT(perm, entry);
    1027             :   }
    1028             : 
    1029           0 :   if (!perm) {
    1030           0 :     ABORT(R_NOT_FOUND);
    1031             :   }
    1032           0 :   if (perm->stun->last_error_code == 403) {
    1033           0 :     ABORT(R_NOT_PERMITTED);
    1034             :   }
    1035           0 :   *permp = perm;
    1036             : 
    1037           0 :   _status=0;
    1038             : abort:
    1039           0 :   return(_status);
    1040             : }
    1041             : 
    1042           0 : static void nr_turn_client_permissions_cb(NR_SOCKET s, int how, void *arg)
    1043             : {
    1044           0 :   nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
    1045           0 :   r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Successfully refreshed permission",
    1046           0 :         ctx->tctx->label);
    1047           0 : }
    1048             : 
    1049             : /* Note that we don't destroy the nr_turn_stun_ctx. That is owned by the
    1050             :    nr_turn_client_ctx. */
    1051           0 : static int nr_turn_permission_destroy(nr_turn_permission **permp)
    1052             : {
    1053             :   nr_turn_permission *perm;
    1054             : 
    1055           0 :   if (!permp || !*permp)
    1056           0 :     return(0);
    1057             : 
    1058           0 :   perm = *permp;
    1059           0 :   *permp = 0;
    1060             : 
    1061           0 :   RFREE(perm);
    1062             : 
    1063           0 :   return(0);
    1064             : }
    1065             : 
    1066             : #endif /* USE_TURN */

Generated by: LCOV version 1.13