bool TestNrSocket::allow_ingress(const nr_transport_addr &from,
                                 PortMapping **port_mapping_used) const {
  // This is only called for traffic arriving at a port mapping
  MOZ_ASSERT(nat_->enabled_);
  MOZ_ASSERT(!nat_->is_an_internal_tuple(from));

  *port_mapping_used = get_port_mapping(from, nat_->filtering_type_);
  if (!(*port_mapping_used)) {
    r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
                                 "Filtered",
                                 internal_socket_->my_addr().as_string,
                                 from.as_string);
    return false;
  }

  if (is_port_mapping_stale(**port_mapping_used)) {
    r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
                                 "Stale port mapping",
                                 internal_socket_->my_addr().as_string,
                                 from.as_string);
    return false;
  }

  if (!nat_->allow_hairpinning_ && nat_->is_my_external_tuple(from)) {
    r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
                                 "Hairpinning disallowed",
                                 internal_socket_->my_addr().as_string,
                                 from.as_string);
    return false;
  }

  return true;
}
int TestNrSocket::PortMapping::sendto(const void *msg,
                                      size_t len,
                                      const nr_transport_addr &to) {
  MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP);
  r_log(LOG_GENERIC, LOG_DEBUG,
        "PortMapping %s -> %s sending to %s",
        external_socket_->my_addr().as_string,
        remote_address_.as_string,
        to.as_string);

  last_used_ = PR_IntervalNow();
  int r = external_socket_->sendto(msg, len, 0,
      // TODO(bug 1170299): Remove const_cast when no longer necessary
      const_cast<nr_transport_addr*>(&to));

  if (r == R_WOULDBLOCK) {
    r_log(LOG_GENERIC, LOG_DEBUG, "Enqueueing UDP packet to %s", to.as_string);
    send_queue_.push_back(RefPtr<UdpPacket>(new UdpPacket(msg, len, to)));
    return 0;
  }
  if (r) {
    r_log(LOG_GENERIC,LOG_ERR, "Error: %d", r);
  }

  return r;
}
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair)
  {
    int r,_status;

    if(!pair){
      r_log(LOG_ICE,LOG_ERR,"ICE-PAIR: No pair chosen");
      ABORT(R_BAD_ARGS);
    }

    if(pair->state!=NR_ICE_PAIR_STATE_SUCCEEDED){
      r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s)/CAND-PAIR(%s): tried to install non-succeeded pair, ignoring: %s",pair->pctx->label,pair->codeword,pair->as_string);
    }
    else{
      /* Ok, they chose one */
      /* 1. Send a new request with nominated. Do it as a scheduled
            event to avoid reentrancy issues. Only do this if it hasn't
            happened already (though this shouldn't happen.)
      */
      if(!pair->restart_nominated_cb_timer)
        NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_restart_stun_nominated_cb,pair,&pair->restart_nominated_cb_timer);

      /* 2. Tell ourselves this pair is ready */
      if(r=nr_ice_component_nominated_pair(pair->remote->component, pair))
        ABORT(r);
    }

    _status=0;
  abort:
    return(_status);
 }
RefPtr<NrSocketBase> TestNrSocket::create_external_socket(
    const nr_transport_addr &dest_addr) const {
  MOZ_ASSERT(nat_->enabled_);
  MOZ_ASSERT(!nat_->is_an_internal_tuple(dest_addr));

  int r;
  nr_transport_addr nat_external_addr;

  // Open the socket on an arbitrary port, on the same address.
  // TODO(bug 1170299): Remove const_cast when no longer necessary
  if ((r = nr_transport_addr_copy(
             &nat_external_addr,
             const_cast<nr_transport_addr*>(&internal_socket_->my_addr())))) {
    r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_copy: %d",
                                __FUNCTION__, r);
    return nullptr;
  }

  if ((r = nr_transport_addr_set_port(&nat_external_addr, 0))) {
    r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_set_port: %d",
                                __FUNCTION__, r);
    return nullptr;
  }

  RefPtr<NrSocketBase> external_socket;
  r = NrSocketBase::CreateSocket(&nat_external_addr, &external_socket);

  if (r) {
    r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in NrSocket::create: %d",
                                __FUNCTION__, r);
    return nullptr;
  }

  return external_socket;
}
Exemple #5
0
int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair)
  {
    int r,_status;
   
    if(!pair){
      r_log(LOG_ICE,LOG_ERR,"ICE-PAIR: No pair chosen");
      ABORT(R_BAD_ARGS);
    }

    if(pair->state!=NR_ICE_PAIR_STATE_SUCCEEDED){
      r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): tried to install non-succeeded pair %s, ignoring",pair->pctx->label,pair->as_string);
    }
    else{
      /* Ok, they chose one */
      /* 1. Send a new request with nominated. Do it as a scheduled
            event to avoid reentrancy issues  */
      NR_ASYNC_SCHEDULE(nr_ice_candidate_pair_restart_stun_nominated_cb,pair);
      /* 2. Tell ourselves this pair is ready */
      if(r=nr_ice_component_nominated_pair(pair->remote->component, pair))
        ABORT(r);
    }

    _status=0;
  abort:
    return(_status);
 }
static int nr_turn_client_start_refresh_timer(nr_turn_client_ctx *tctx,
                                              nr_turn_stun_ctx *sctx,
                                              UINT4 lifetime)
{
  int _status;

  assert(!tctx->refresh_timer_handle);

  if (lifetime <= TURN_REFRESH_SLACK_SECONDS) {
    r_log(NR_LOG_TURN, LOG_ERR, "Too short lifetime specified for turn %u", lifetime);
    ABORT(R_BAD_DATA);
  }

  if (lifetime > 3600)
    lifetime = 3600;

  lifetime -= TURN_REFRESH_SLACK_SECONDS;

  r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Setting refresh timer for %u seconds",
        tctx->label, lifetime);
  NR_ASYNC_TIMER_SET(lifetime * 1000, nr_turn_client_refresh_timer_cb, sctx,
                     &tctx->refresh_timer_handle);

  _status=0;
abort:
  if (_status) {
    nr_turn_client_failed(tctx);
  }
  return _status;
}
int TestNrSocket::PortMapping::send_from_queue() {
  MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP);
  int r = 0;

  while (!send_queue_.empty()) {
    UdpPacket &packet = *send_queue_.front();
    r_log(LOG_GENERIC, LOG_DEBUG,
          "PortMapping %s -> %s sending from queue to %s",
          external_socket_->my_addr().as_string,
          remote_address_.as_string,
          packet.remote_address_.as_string);

    r = external_socket_->sendto(packet.buffer_->data(),
                                 packet.buffer_->len(),
                                 0,
                                 &packet.remote_address_);

    if (r) {
      if (r != R_WOULDBLOCK) {
        r_log(LOG_GENERIC, LOG_ERR, "%s: Fatal error %d, stop trying",
              __FUNCTION__, r);
        send_queue_.clear();
      } else {
        r_log(LOG_GENERIC, LOG_DEBUG, "Would block, will retry later");
      }
      break;
    }

    send_queue_.pop_front();
  }

  return r;
}
Exemple #8
0
static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg)
{
    int _status;
    nr_stun_client_ctx *ctx=cb_arg;
    struct timeval now;
    INT8 ms_waited;

    /* Prevent this timer from being cancelled later */
    ctx->timer_handle=0;

    /* Shouldn't happen */
    if(ctx->state==NR_STUN_CLIENT_STATE_CANCELLED)
        ABORT(R_REJECTED);

    gettimeofday(&now, 0);
    if (r_timeval_diff_ms(&now, &ctx->timer_set, &ms_waited)) {
        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired",ctx->label);
    }
    else {
        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired (after %llu ms)",ctx->label, ms_waited);
    }

    if (ctx->request_ct >= ctx->maximum_transmits) {
        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timed out",ctx->label);
        ctx->state=NR_STUN_CLIENT_STATE_TIMED_OUT;
        ABORT(R_FAILED);
    }

    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
        ABORT(R_NOT_PERMITTED);

    /* as a side effect will reset the timer */
    nr_stun_client_send_request(ctx);

    _status = 0;
abort:
    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) {
        /* Cancel the timer firing */
        if (ctx->timer_handle) {
            NR_async_timer_cancel(ctx->timer_handle);
            ctx->timer_handle=0;
        }

        if (ctx->finished_cb) {
            NR_async_cb finished_cb = ctx->finished_cb;
            ctx->finished_cb = 0;  /* prevent 2nd call */
            /* finished_cb call must be absolutely last thing in function
             * because as a side effect this ctx may be operated on in the
             * callback */
            finished_cb(0,0,ctx->cb_arg);
        }
    }
    return;
}
// This should be called on the STS thread.
int NrSocket::sendto(const void *msg, size_t len,
                     int flags, nr_transport_addr *to) {
  ASSERT_ON_THREAD(ststhread_);
  int r,_status;
  PRNetAddr naddr;
  int32_t status;

  if ((r=nr_transport_addr_to_praddr(to, &naddr)))
    ABORT(r);

  if(fd_==nullptr)
    ABORT(R_EOD);

  if (nr_is_stun_request_message((UCHAR*)msg, len)) {
    // Global rate limiting for stun requests, to mitigate the ice hammer DoS
    // (see http://tools.ietf.org/html/draft-thomson-mmusic-ice-webrtc)

    // Tolerate rate of 8k/sec, for one second.
    static SimpleTokenBucket burst(8192*1, 8192);
    // Tolerate rate of 3.6k/sec over twenty seconds.
    static SimpleTokenBucket sustained(3686*20, 3686);

    // Check number of tokens in each bucket.
    if (burst.getTokens(UINT32_MAX) < len ||
        sustained.getTokens(UINT32_MAX) < len) {
      r_log(LOG_GENERIC, LOG_ERR,
                 "Global rate limit for STUN requests exceeded.");
      MOZ_ASSERT("Global rate limit for STUN requests exceeded. Go bug "
                 "[email protected] if you weren't intentionally spamming "
                 "ICE candidates, or don't know what that means.");
      ABORT(R_WOULDBLOCK);
    }

    // Take len tokens from both buckets.
    // (not threadsafe, but no problem since this is only called from STS)
    burst.getTokens(len);
    sustained.getTokens(len);
  }

  // TODO: Convert flags?
  status = PR_SendTo(fd_, msg, len, flags, &naddr, PR_INTERVAL_NO_WAIT);
  if (status < 0 || (size_t)status != len) {
    if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
      ABORT(R_WOULDBLOCK);

    r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s", to->as_string);
    ABORT(R_IO_ERROR);
  }

  _status=0;
abort:
  return(_status);
}
Exemple #10
0
int
nr_turn_client_process_response(nr_turn_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *turn_server_addr)
{
    int r,_status;
    nr_stun_client_ctx *stun_ctx;

    assert(ctx->phase >= 0 && ctx->phase < NUMBER_OF_STUN_CTX);
    if (ctx->phase < 0 || ctx->phase > NUMBER_OF_STUN_CTX)
        ABORT(R_INTERNAL);  /* should never happen */

    stun_ctx = ctx->stun_ctx[ctx->phase];

    if (ctx->state != NR_TURN_CLIENT_STATE_RUNNING
     && ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED) {
#if 0
//TODO: !nn! it really shouldn't be the case that we're processing a response in this state,
//TODO: but perhaps we failed and we haven't taken ourself off the
//TODO: ASYNC wait list, so an outstanding packet can cause us this grief
assert(0);
        ABORT(R_INTERNAL);  /* should never happen */
#else
//TODO: !nn! fix so we can never get into this state
r_log(NR_LOG_TURN,LOG_ERR,"TURN-CLIENT(%s): dropping packet in phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]);
return R_INTERNAL;
#endif
    }

    if (ctx->phase != NR_TURN_CLIENT_PHASE_INITIALIZED) {
        r_log(NR_LOG_TURN,LOG_DEBUG,"TURN-CLIENT(%s): Received response in phase %s", ctx->label, TURN_PHASE_LABEL[ctx->phase]);
    }
    else {
        ABORT(R_INTERNAL);
    }

    if ((r=nr_stun_client_process_response(stun_ctx, msg, len, turn_server_addr)))
        ABORT(r);

    _status=0;
  abort:
    if (ctx->state != NR_TURN_CLIENT_STATE_RUNNING) {
        if (ctx->finished_cb) {
            NR_async_cb finished_cb = ctx->finished_cb;
            ctx->finished_cb = 0;  /* prevent 2nd call */
            /* finished_cb call must be absolutely last thing in function
             * because as a side effect this ctx may be operated on in the
             * callback */
            finished_cb(0,0,ctx->cb_arg);
        }
    }

    return(_status);
}
Exemple #11
0
int
nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int drop_link_local, int *count)
{
    int r,_status=0;
    int i;
    char typestr[100];

#ifdef WIN32
    _status = stun_get_win32_addrs(addrs, maxaddrs, count);
#else
    _status = stun_getifaddrs(addrs, maxaddrs, count);
#endif

    if ((r=nr_stun_remove_duplicate_addrs(addrs, drop_loopback, drop_link_local, count)))
      ABORT(r);

    for (i = 0; i < *count; ++i) {
      nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr));
      r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n",
            i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr);
    }

abort:
    return _status;
}
Exemple #12
0
int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
  {
    int r,_status;

    r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): setting pair %s to %s",
      pctx->label,pair->as_string,nr_ice_cand_pair_states[state]);
    pair->state=state;

    if(pctx->state!=NR_ICE_PAIR_STATE_WAITING){
      if(state==NR_ICE_PAIR_STATE_WAITING)
        pctx->waiting_pairs++;
    }
    else{
      if(state!=NR_ICE_PAIR_STATE_WAITING)
        pctx->waiting_pairs--;

      assert(pctx->waiting_pairs>=0);
    }
    if(pair->state==NR_ICE_PAIR_STATE_FAILED){
      if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
        ABORT(r);
    }

    _status=0;
  abort:
    return(_status);
  }
Exemple #13
0
int nr_turn_client_cancel(nr_turn_client_ctx *ctx)
{
  nr_turn_stun_ctx *stun = 0;

  if (ctx->state == NR_TURN_CLIENT_STATE_CANCELLED ||
      ctx->state == NR_TURN_CLIENT_STATE_FAILED)
    return(0);

  if (ctx->label)
    r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): cancelling", ctx->label);

  /* Cancel the STUN client ctxs */
  stun = STAILQ_FIRST(&ctx->stun_ctxs);
  while (stun) {
    nr_stun_client_cancel(stun->stun);
    stun = STAILQ_NEXT(stun, entry);
  }

  /* Cancel the timers, if not already cancelled */
  NR_async_timer_cancel(ctx->connected_timer_handle);
  NR_async_timer_cancel(ctx->refresh_timer_handle);

  ctx->state = NR_TURN_CLIENT_STATE_CANCELLED;

  return(0);
}
// This should be called on the STS thread.
int NrSocket::sendto(const void *msg, size_t len,
                     int flags, nr_transport_addr *to) {
  ASSERT_ON_THREAD(ststhread_);
  int r,_status;
  PRNetAddr naddr;
  int32_t status;

  if ((r=nr_transport_addr_to_praddr(to, &naddr)))
    ABORT(r);

  if(fd_==nullptr)
    ABORT(R_EOD);

  // TODO: Convert flags?
  status = PR_SendTo(fd_, msg, len, flags, &naddr, PR_INTERVAL_NO_WAIT);
  if (status < 0 || (size_t)status != len) {
    if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
      ABORT(R_WOULDBLOCK);

    r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s", to->as_string);
    ABORT(R_IO_ERROR);
  }

  _status=0;
abort:
  return(_status);
}
int NrSocket::recvfrom(void * buf, size_t maxlen,
                       size_t *len, int flags,
                       nr_transport_addr *from) {
  ASSERT_ON_THREAD(ststhread_);
  int r,_status;
  PRNetAddr nfrom;
  int32_t status;

  status = PR_RecvFrom(fd_, buf, maxlen, flags, &nfrom, PR_INTERVAL_NO_WAIT);
  if (status <= 0) {
    if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
      ABORT(R_WOULDBLOCK);
    r_log(LOG_GENERIC, LOG_INFO, "Error in recvfrom");
    ABORT(R_IO_ERROR);
  }
  *len=status;

  if((r=nr_praddr_to_transport_addr(&nfrom,from,my_addr_.protocol,0)))
    ABORT(r);

  //r_log(LOG_GENERIC,LOG_DEBUG,"Read %d bytes from %s",*len,addr->as_string);

  _status=0;
abort:
  return(_status);
}
int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
  {
    int r,_status;

    r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): triggered check on %s",pctx->label,pair->codeword,pair->as_string);

    switch(pair->state){
      case NR_ICE_PAIR_STATE_FROZEN:
        nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
        /* Fall through */
      case NR_ICE_PAIR_STATE_WAITING:
        /* Start the checks */
        if(r=nr_ice_candidate_pair_start(pctx,pair))
          ABORT(r);
        break;
      case NR_ICE_PAIR_STATE_IN_PROGRESS:
        if(r=nr_stun_client_force_retransmit(pair->stun_client))
          ABORT(r);
        break;
      default:
        break;
    }

    /* Activate the media stream if required */
    if(pair->remote->stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN){
      if(r=nr_ice_media_stream_start_checks(pair->pctx,pair->remote->stream))
        ABORT(r);
    }

    _status=0;
  abort:
    return(_status);
  }
int nr_stun_client_force_retransmit(nr_stun_client_ctx *ctx)
  {
    int r,_status;

    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
        ABORT(R_NOT_PERMITTED);

    if (ctx->request_ct > ctx->maximum_transmits) {
        r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Too many retransmit attempts",ctx->label);
        ABORT(R_FAILED);
    }

    /* if there is a scheduled retransimt, get rid of the scheduled retransmit
     * and retransmit immediately */
    if (ctx->timer_handle) {
        NR_async_timer_cancel(ctx->timer_handle);
        ctx->timer_handle=0;

        if (r=nr_stun_client_send_request(ctx))
            ABORT(r);
    }

    _status=0;
  abort:

    return(_status);
  }
/* This takes ownership of nrsock whether it fails or not. */
static int nr_tcp_socket_ctx_create(nr_socket *nrsock, int is_framed,
  int max_pending, nr_tcp_socket_ctx **sockp)
  {
    int r, _status;
    nr_tcp_socket_ctx *sock = 0;
    nr_socket *tcpsock;

    if (!(sock = RCALLOC(sizeof(nr_tcp_socket_ctx)))) {
      nr_socket_destroy(&nrsock);
      ABORT(R_NO_MEMORY);
    }

    if ((r=nr_socket_buffered_stun_create(nrsock, max_pending, is_framed ? ICE_TCP_FRAMING : TURN_TCP_FRAMING, &tcpsock))){
      nr_socket_destroy(&nrsock);
      ABORT(r);
    }

    sock->inner=tcpsock;
    sock->is_framed=is_framed;

    if ((r=nr_ip4_port_to_transport_addr(ntohl(INADDR_ANY), 0, IPPROTO_TCP, &sock->remote_addr)))
      ABORT(r);

    *sockp=sock;

    _status=0;
abort:
    if (_status) {
      r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s failed with error %d",__FILE__,__LINE__,__FUNCTION__,_status);
      nr_tcp_socket_ctx_destroy(&sock);
    }
    return(_status);
  }
Exemple #19
0
/* TODO([email protected]): We currently don't support channels.
   We might in the future. Mozilla bug 857736 */
int nr_turn_client_send_indication(nr_turn_client_ctx *ctx,
                                   const UCHAR *msg, size_t len,
                                   int flags, nr_transport_addr *remote_addr)
{
  int r,_status;
  nr_stun_client_send_indication_params params = { { 0 } };
  nr_stun_message *ind = 0;

  if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
    ABORT(R_FAILED);

  r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Send indication len=%zu",
        ctx->label, len);

  if ((r=nr_turn_client_ensure_perm(ctx, remote_addr)))
    ABORT(r);

  if ((r=nr_transport_addr_copy(&params.remote_addr, remote_addr)))
    ABORT(r);

  params.data.data = (UCHAR*)msg;
  params.data.len = len;

  if ((r=nr_stun_build_send_indication(&params, &ind)))
    ABORT(r);

  if ((r=nr_turn_client_send_stun_request(ctx, ind, flags)))
    ABORT(r);

  _status=0;
abort:
  nr_stun_message_destroy(&ind);
  return(_status);
}
static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg)
  {
    int _status;
    nr_stun_client_ctx *ctx=cb_arg;
    struct timeval now;
    INT8 ms_waited;

    /* Prevent this timer from being cancelled later */
    ctx->timer_handle=0;

    /* Shouldn't happen */
    if(ctx->state==NR_STUN_CLIENT_STATE_CANCELLED)
      ABORT(R_REJECTED);

    gettimeofday(&now, 0);
    if (r_timeval_diff_ms(&now, &ctx->timer_set, &ms_waited)) {
        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired",ctx->label);
    }
    else {
        r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired (after %llu ms)",ctx->label, ms_waited);
    }

    if (ctx->request_ct >= ctx->maximum_transmits) {
        r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Timed out",ctx->label);
        ctx->state=NR_STUN_CLIENT_STATE_TIMED_OUT;
        ABORT(R_FAILED);
    }

    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
        ABORT(R_NOT_PERMITTED);

    /* as a side effect will reset the timer */
    nr_stun_client_send_request(ctx);

    _status = 0;
  abort:
    if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) {
        /* Cancel the timer firing */
        if (ctx->timer_handle){
            NR_async_timer_cancel(ctx->timer_handle);
            ctx->timer_handle=0;
        }

        nr_stun_client_fire_finished_cb(ctx);
    }
    return;
  }
int TestNrSocket::listen(int backlog) {
  MOZ_ASSERT(internal_socket_->my_addr().protocol == IPPROTO_TCP);
  r_log(LOG_GENERIC, LOG_DEBUG,
        "TestNrSocket %s listening",
        internal_socket_->my_addr().as_string);

  return internal_socket_->listen(backlog);
}
Exemple #22
0
void TestNrSocket::fire_readable_callback() {
  MOZ_ASSERT(poll_flags() & PR_POLL_READ);
  // Stop listening on all mapped sockets; we will start listening again
  // if the app starts listening to us again.
  cancel_port_mapping_async_wait(NR_ASYNC_WAIT_READ);
  r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s ready for read",
        my_addr_.as_string);
  fire_callback(NR_ASYNC_WAIT_READ);
}
int TestNrSocket::PortMapping::cancel(int how) {
  r_log(LOG_GENERIC, LOG_DEBUG,
        "PortMapping %s -> %s stop waiting for %s",
        external_socket_->my_addr().as_string,
        remote_address_.as_string,
        how == NR_ASYNC_WAIT_READ ? "read" : "write");

  return external_socket_->cancel(how);
}
Exemple #24
0
static void nr_turn_client_error_cb(NR_SOCKET s, int how, void *arg)
{
  nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;

  r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, %s",
        ctx->tctx->label, ctx->mode, __FUNCTION__);

  nr_turn_client_failed(ctx->tctx);
}
int nr_turn_client_cancel(nr_turn_client_ctx *ctx)
{
  nr_turn_stun_ctx *stun = 0;

  if (ctx->state == NR_TURN_CLIENT_STATE_CANCELLED ||
      ctx->state == NR_TURN_CLIENT_STATE_FAILED)
    return 0;

  if (ctx->label)
    r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): cancelling", ctx->label);

  /* If we are waiting for connect, we need to stop
     waiting for writability */
  if (ctx->state == NR_TURN_CLIENT_STATE_INITTED ||
      ctx->state == NR_TURN_CLIENT_STATE_ALLOCATION_WAIT) {
    NR_SOCKET fd;
    int r;

    r = nr_socket_getfd(ctx->sock, &fd);
    if (r) {
      /* We should be able to get the fd, but if we get an
         error, we shouldn't cancel. */
      r_log(NR_LOG_TURN, LOG_ERR, "TURN: Couldn't get internal fd");
    }
    else {
      NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
    }
  }

  /* Cancel the STUN client ctxs */
  stun = STAILQ_FIRST(&ctx->stun_ctxs);
  while (stun) {
    nr_stun_client_cancel(stun->stun);
    stun = STAILQ_NEXT(stun, entry);
  }

  /* Cancel the timers, if not already cancelled */
  NR_async_timer_cancel(ctx->connected_timer_handle);
  NR_async_timer_cancel(ctx->refresh_timer_handle);

  ctx->state = NR_TURN_CLIENT_STATE_CANCELLED;

  return(0);
}
int TestNrSocket::write(const void *msg, size_t len, size_t *written) {
  UCHAR *buf = static_cast<UCHAR*>(const_cast<void*>(msg));
  if (nat_->block_stun_ && nr_is_stun_message(buf, len)) {
    // Should cause this socket to be abandoned
    r_log(LOG_GENERIC, LOG_DEBUG,
          "TestNrSocket %s dropping outgoing TCP "
          "because it is configured to drop STUN",
          my_addr().as_string);
    return R_INTERNAL;
  }

  if (nat_->block_tcp_ && !tls_) {
    // Should cause this socket to be abandoned
    r_log(LOG_GENERIC, LOG_DEBUG,
          "TestNrSocket %s dropping outgoing TCP "
          "because it is configured to drop TCP",
          my_addr().as_string);
    return R_INTERNAL;
  }

  if (port_mappings_.empty()) {
    // The no-nat case, just pass call through.
    r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s writing",
          my_addr().as_string);

    return internal_socket_->write(msg, len, written);
  }
  destroy_stale_port_mappings();
  if (port_mappings_.empty()) {
    r_log(LOG_GENERIC, LOG_DEBUG,
          "TestNrSocket %s dropping outgoing TCP "
          "because the port mapping was stale",
          my_addr().as_string);
    return R_INTERNAL;
  }
  // This is TCP only
  MOZ_ASSERT(port_mappings_.size() == 1);
  r_log(LOG_GENERIC, LOG_DEBUG,
        "PortMapping %s -> %s writing",
        port_mappings_.front()->external_socket_->my_addr().as_string,
        port_mappings_.front()->remote_address_.as_string);
  port_mappings_.front()->last_used_ = PR_IntervalNow();
  return port_mappings_.front()->external_socket_->write(msg, len, written);
}
Exemple #27
0
static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name)
{
    int r,_status;
    HKEY adapter_reg;
    TCHAR adapter_key[_NR_MAX_KEY_LENGTH];
    TCHAR keyval_buf[_NR_MAX_KEY_LENGTH];
    TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH];
    DWORD keyval_len, key_type;
    size_t converted_chars, newlen;
    char *my_fn = 0;

#ifdef _UNICODE
    mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1,
               adapter_GUID, _TRUNCATE);
#else
    strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH);
#endif

    _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG));
    _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\"));
    _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar);
    _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection"));

    r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg);

    if (r != ERROR_SUCCESS) {
      r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r);
      ABORT(R_INTERNAL);
    }

    keyval_len = sizeof(keyval_buf);
    r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type,
                        (BYTE *)keyval_buf, &keyval_len);

    RegCloseKey(adapter_reg);

#ifdef UNICODE
    newlen = wcslen(keyval_buf)+1;
    my_fn = (char *) RCALLOC(newlen);
    if (!my_fn) {
      ABORT(R_NO_MEMORY);
    }
    wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE);
#else
    my_fn = r_strdup(keyval_buf);
#endif

    *friendly_name = my_fn;
    _status=0;

abort:
    if (_status) {
      if (my_fn) free(my_fn);
    }
    return(_status);
}
static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg)
 {
    nr_ice_cand_pair *pair=cb_arg;

    pair->restart_role_change_cb_timer=0;

    r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s):COMP(%d): Restarting pair as %s: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->pctx->controlling ? "CONTROLLING" : "CONTROLLED",pair->as_string);

    nr_ice_candidate_pair_restart(pair->pctx, pair);
  }
int TestNrSocket::PortMapping::async_wait(int how, NR_async_cb cb, void *cb_arg,
                                          char *function, int line) {
  r_log(LOG_GENERIC, LOG_DEBUG,
        "PortMapping %s -> %s waiting for %s",
        external_socket_->my_addr().as_string,
        remote_address_.as_string,
        how == NR_ASYNC_WAIT_READ ? "read" : "write");

  return external_socket_->async_wait(how, cb, cb_arg, function, line);
}
TestNrSocket::PortMapping* TestNrSocket::create_port_mapping(
    const nr_transport_addr &remote_address,
    const RefPtr<NrSocketBase> &external_socket) const {
  r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s creating port mapping %s -> %s",
        internal_socket_->my_addr().as_string,
        external_socket->my_addr().as_string,
        remote_address.as_string);

  return new PortMapping(remote_address, external_socket);
}