DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (1aeaa33a64f9)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
#include <sstream>

#include "logging.h"

// nICEr includes
extern "C" {
#include "nr_api.h"
#include "ice_ctx.h"
}

// Local includes
#include "nricectxhandler.h"
#include "nricemediastream.h"
#include "nriceresolver.h"

namespace mozilla {

MOZ_MTLOG_MODULE("mtransport")

NrIceCtxHandler::NrIceCtxHandler(const std::string& name,
                                 NrIceCtx::Policy policy)
    : current_ctx(new NrIceCtx(name, policy)),
      old_ctx(nullptr),
      restart_count(0) {}

RefPtr<NrIceCtxHandler> NrIceCtxHandler::Create(const std::string& name,
                                                bool allow_loopback,
                                                bool tcp_enabled,
                                                bool allow_link_local,
                                                NrIceCtx::Policy policy) {
  // InitializeGlobals only executes once
  NrIceCtx::InitializeGlobals(allow_loopback, tcp_enabled, allow_link_local);

  RefPtr<NrIceCtxHandler> ctx = new NrIceCtxHandler(name, policy);

  if (ctx == nullptr || ctx->current_ctx == nullptr ||
      !ctx->current_ctx->Initialize()) {
    return nullptr;
  }

  return ctx;
}

RefPtr<NrIceMediaStream> NrIceCtxHandler::CreateStream(const std::string& name,
                                                       int components) {
  // To make tracking NrIceMediaStreams easier during ICE restart
  // prepend an int to the name that increments with each ICE restart
  std::ostringstream os;
  os << restart_count << "-" << name;
  return NrIceMediaStream::Create(this->current_ctx, os.str(), components);
}

RefPtr<NrIceCtx> NrIceCtxHandler::CreateCtx() const {
  return CreateCtx(NrIceCtx::GetNewUfrag(), NrIceCtx::GetNewPwd());
}

RefPtr<NrIceCtx> NrIceCtxHandler::CreateCtx(const std::string& ufrag,
                                            const std::string& pwd) const {
  RefPtr<NrIceCtx> new_ctx =
      new NrIceCtx(this->current_ctx->name(), this->current_ctx->policy());
  if (new_ctx == nullptr) {
    return nullptr;
  }

  if (!new_ctx->Initialize(ufrag, pwd)) {
    return nullptr;
  }

  // copy the stun, and turn servers from the current context
  int r = nr_ice_ctx_set_stun_servers(new_ctx->ctx_,
                                      this->current_ctx->ctx_->stun_servers,
                                      this->current_ctx->ctx_->stun_server_ct);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Error while setting STUN servers in CreateCtx"
                            << " (likely ice restart related)");
    return nullptr;
  }

  r = nr_ice_ctx_copy_turn_servers(new_ctx->ctx_,
                                   this->current_ctx->ctx_->turn_servers,
                                   this->current_ctx->ctx_->turn_server_ct);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Error while copying TURN servers in CreateCtx"
                            << " (likely ice restart related)");
    return nullptr;
  }

  // grab the NrIceResolver stashed in the nr_resolver and allocate another
  // for the new ctx.  Note: there may not be an nr_resolver.
  if (this->current_ctx->ctx_->resolver) {
    NrIceResolver* resolver =
        static_cast<NrIceResolver*>(this->current_ctx->ctx_->resolver->obj);
    if (!resolver ||
        NS_FAILED(new_ctx->SetResolver(resolver->AllocateResolver()))) {
      MOZ_MTLOG(ML_ERROR, "Error while setting dns resolver in CreateCtx"
                              << " (likely ice restart related)");
      return nullptr;
    }
  }

  return new_ctx;
}

bool NrIceCtxHandler::BeginIceRestart(RefPtr<NrIceCtx> new_ctx) {
  MOZ_ASSERT(!old_ctx, "existing ice restart in progress");
  if (old_ctx) {
    MOZ_MTLOG(ML_ERROR, "Existing ice restart in progress");
    return false;  // ice restart already in progress
  }

  if (new_ctx == nullptr) {
    return false;
  }

  ++restart_count;
  old_ctx = current_ctx;
  current_ctx = new_ctx;
  return true;
}

void NrIceCtxHandler::FinalizeIceRestart() {
  if (old_ctx) {
    // Fixup the telemetry by transferring old stats to current ctx.
    NrIceStats stats = old_ctx->Destroy();
    current_ctx->AccumulateStats(stats);
  }

  // no harm calling this even if we're not in the middle of restarting
  old_ctx = nullptr;
}

void NrIceCtxHandler::RollbackIceRestart() {
  if (old_ctx == nullptr) {
    return;
  }
  current_ctx = old_ctx;
  old_ctx = nullptr;
}

NrIceStats NrIceCtxHandler::Destroy() {
  NrIceStats stats;

  // designed to be called more than once so if stats are desired, this can be
  // called just prior to the destructor
  if (old_ctx && current_ctx) {
    stats = old_ctx->Destroy();
    current_ctx->AccumulateStats(stats);
  }

  if (current_ctx) {
    stats = current_ctx->Destroy();
  }

  old_ctx = nullptr;
  current_ctx = nullptr;

  return stats;
}

NrIceCtxHandler::~NrIceCtxHandler() { Destroy(); }

}  // namespace mozilla