RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
                                  bool offerer,
                                  bool set_interface_priorities) {
  RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);

  // Initialize the crypto callbacks
  if (!initialized) {
    NR_reg_init(NR_REG_MODE_LOCAL);
    nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
    initialized = true;

    // Set the priorites for candidate type preferences
    NR_reg_set_uchar((char *)"ice.pref.type.srv_rflx",100);
    NR_reg_set_uchar((char *)"ice.pref.type.peer_rflx",105);
    NR_reg_set_uchar((char *)"ice.pref.type.prflx",99);
    NR_reg_set_uchar((char *)"ice.pref.type.host",125);
    NR_reg_set_uchar((char *)"ice.pref.type.relayed",126);

    if (set_interface_priorities) {
      NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255);
      NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254);
      NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253);
      NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252);
      NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251);
      NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252);
      NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251);
      NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249);
      NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250);
      NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249);
      NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248);
      NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247);
      NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251);
      NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234);
      NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233);
      NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
    }

    NR_reg_set_uint4((char *)"stun.client.maximum_transmits",4);
  }

  // Create the ICE context
  int r;

  UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
      NR_ICE_CTX_FLAGS_ANSWERER;
  flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;

  r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
                        &ctx->ctx_);
  if (r) {
    MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create ICE ctx for '" << name << "'");
    return nullptr;
  }

  // Create the handler objects
  ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
  ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
  ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
  ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
  ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed;
  ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;

  ctx->ice_handler_ = new nr_ice_handler();
  ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_;
  ctx->ice_handler_->obj = ctx;

  // Create the peer ctx. Because we do not support parallel forking, we
  // only have one peer ctx.
  std::string peer_name = name + ":default";
  r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_,
                             const_cast<char *>(peer_name.c_str()),
                             &ctx->peer_);
  if (r) {
    MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create ICE peer ctx for '" << name << "'");
    return nullptr;
  }

  nsresult rv;
  ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);

  if (!NS_SUCCEEDED(rv))
    return nullptr;

  return ctx;
}
Exemple #2
0
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
                                  bool offerer,
                                  bool set_interface_priorities,
                                  bool allow_loopback) {

  RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);

  // Initialize the crypto callbacks and logging stuff
  if (!initialized) {
    NR_reg_init(NR_REG_MODE_LOCAL);
    RLogRingBuffer::CreateInstance();
    nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
    initialized = true;

    // Set the priorites for candidate type preferences.
    // These numbers come from RFC 5245 S. 4.1.2.2
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0);

    if (set_interface_priorities) {
      NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255);
      NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254);
      NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253);
      NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252);
      NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251);
      NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252);
      NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251);
      NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249);
      NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250);
      NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249);
      NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248);
      NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247);
      NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251);
      NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235);
      NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234);
      NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233);
      NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
    }

    NR_reg_set_uint4((char *)"stun.client.maximum_transmits",7);
    NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD, 5000);

    if (allow_loopback) {
      NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);
    }
  }

  // Create the ICE context
  int r;

  UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
      NR_ICE_CTX_FLAGS_ANSWERER;
  flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;

  r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
                        &ctx->ctx_);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name << "'");
    return nullptr;
  }

#ifdef USE_INTERFACE_PRIORITIZER
  nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
  if (!prioritizer) {
    MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create interface prioritizer.");
    return nullptr;
  }

  r = nr_ice_ctx_set_interface_prioritizer(ctx->ctx_, prioritizer);
  if (r) {
    MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set interface prioritizer.");
    return nullptr;
  }
#endif  // USE_INTERFACE_PRIORITIZER

  if (ctx->generating_trickle()) {
    r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx);
    if (r) {
      MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name << "'");
      return nullptr;
    }
  }

  // Create the handler objects
  ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
  ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
  ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
  ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
  ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed;
  ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;
  ctx->ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking;

  ctx->ice_handler_ = new nr_ice_handler();
  ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_;
  ctx->ice_handler_->obj = ctx;

  // Create the peer ctx. Because we do not support parallel forking, we
  // only have one peer ctx.
  std::string peer_name = name + ":default";
  r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_,
                             const_cast<char *>(peer_name.c_str()),
                             &ctx->peer_);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name << "'");
    return nullptr;
  }

  nsresult rv;
  ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);

  if (!NS_SUCCEEDED(rv))
    return nullptr;

  return ctx;
}
Exemple #3
0
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
                                  bool offerer,
                                  bool allow_loopback,
                                  bool tcp_enabled,
                                  bool allow_link_local,
                                  bool hide_non_default,
                                  Policy policy) {
   RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);

  // Initialize the crypto callbacks and logging stuff
  if (!initialized) {
    NR_reg_init(NR_REG_MODE_LOCAL);
    nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
    initialized = true;

    // Set the priorites for candidate type preferences.
    // These numbers come from RFC 5245 S. 4.1.2.2
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX_TCP, 99);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX_TCP, 109);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST_TCP, 125);
    NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0);

    int32_t stun_client_maximum_transmits = 7;
    int32_t ice_trickle_grace_period = 5000;
    int32_t ice_tcp_so_sock_count = 3;
    int32_t ice_tcp_listen_backlog = 10;
    nsAutoCString force_net_interface;
#ifndef MOZILLA_XPCOMRT_API
    nsresult res;
    nsCOMPtr<nsIPrefService> prefs =
      do_GetService("@mozilla.org/preferences-service;1", &res);

    if (NS_SUCCEEDED(res)) {
      nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
      if (branch) {
        branch->GetIntPref(
            "media.peerconnection.ice.stun_client_maximum_transmits",
            &stun_client_maximum_transmits);
        branch->GetIntPref(
            "media.peerconnection.ice.trickle_grace_period",
            &ice_trickle_grace_period);
        branch->GetIntPref(
            "media.peerconnection.ice.tcp_so_sock_count",
            &ice_tcp_so_sock_count);
        branch->GetIntPref(
            "media.peerconnection.ice.tcp_listen_backlog",
            &ice_tcp_listen_backlog);
        branch->GetCharPref(
            "media.peerconnection.ice.force_interface",
            getter_Copies(force_net_interface));
      }
    }
#endif
    NR_reg_set_uint4((char *)"stun.client.maximum_transmits",
                     stun_client_maximum_transmits);
    NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD,
                     ice_trickle_grace_period);
    NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
                     ice_tcp_so_sock_count);
    NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG,
                     ice_tcp_listen_backlog);

    NR_reg_set_char((char *)NR_ICE_REG_ICE_TCP_DISABLE, !tcp_enabled);

    if (allow_loopback) {
      NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);
    }

    if (allow_link_local) {
      NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
    }
    if (force_net_interface.Length() > 0) {
      // Stupid cast.... but needed
      const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface));
      NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get()));
    }
  }

  // Create the ICE context
  int r;

  UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
      NR_ICE_CTX_FLAGS_ANSWERER;
  flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
  if (policy == ICE_POLICY_RELAY) {
    flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY;
  }

  if (hide_non_default)
    flags |= NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS;

  r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
                        &ctx->ctx_);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name << "'");
    return nullptr;
  }

  nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
  if (!prioritizer) {
    MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer.");
    return nullptr;
  }

  r = nr_ice_ctx_set_interface_prioritizer(ctx->ctx_, prioritizer);
  if (r) {
    MOZ_MTLOG(LogLevel::Error, "Couldn't set interface prioritizer.");
    return nullptr;
  }

  if (ctx->generating_trickle()) {
    r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx);
    if (r) {
      MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name << "'");
      return nullptr;
    }
  }

  // Create the handler objects
  ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
  ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
  ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
  ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
  ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed;
  ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;
  ctx->ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking;

  ctx->ice_handler_ = new nr_ice_handler();
  ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_;
  ctx->ice_handler_->obj = ctx;

  // Create the peer ctx. Because we do not support parallel forking, we
  // only have one peer ctx.
  std::string peer_name = name + ":default";
  r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_,
                             const_cast<char *>(peer_name.c_str()),
                             &ctx->peer_);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name << "'");
    return nullptr;
  }

  nsresult rv;
  ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);

  if (!NS_SUCCEEDED(rv))
    return nullptr;

  return ctx;
}
bool
NrIceCtx::Initialize(const std::string& ufrag,
                     const std::string& pwd)
{
  MOZ_ASSERT(!ufrag.empty());
  MOZ_ASSERT(!pwd.empty());
  if (ufrag.empty() || pwd.empty()) {
    return false;
  }

  // Create the ICE context
  int r;

  UINT4 flags = offerer_ ? NR_ICE_CTX_FLAGS_OFFERER:
      NR_ICE_CTX_FLAGS_ANSWERER;
  flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
  switch (policy_) {
    case ICE_POLICY_RELAY:
      flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY;
      break;
    case ICE_POLICY_NO_HOST:
      flags |= NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES;
      break;
    case ICE_POLICY_ALL:
      break;
  }

  r = nr_ice_ctx_create_with_credentials(const_cast<char *>(name_.c_str()),
                                         flags,
                                         const_cast<char *>(ufrag.c_str()),
                                         const_cast<char *>(pwd.c_str()),
                                         &ctx_);
  MOZ_ASSERT(ufrag == ctx_->ufrag);
  MOZ_ASSERT(pwd == ctx_->pwd);

  if (r) {
    MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name_ << "'");
    return false;
  }

  nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
  if (!prioritizer) {
    MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer.");
    return false;
  }

  r = nr_ice_ctx_set_interface_prioritizer(ctx_, prioritizer);
  if (r) {
    MOZ_MTLOG(LogLevel::Error, "Couldn't set interface prioritizer.");
    return false;
  }

  if (generating_trickle()) {
    r = nr_ice_ctx_set_trickle_cb(ctx_, &NrIceCtx::trickle_cb, this);
    if (r) {
      MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name_ << "'");
      return false;
    }
  }

  nsCString mapping_type;
  nsCString filtering_type;
  bool block_udp = false;

  nsresult rv;
  nsCOMPtr<nsIPrefService> pref_service =
    do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);

  if (NS_SUCCEEDED(rv)) {
    nsCOMPtr<nsIPrefBranch> pref_branch;
    rv = pref_service->GetBranch(nullptr, getter_AddRefs(pref_branch));
    if (NS_SUCCEEDED(rv)) {
      rv = pref_branch->GetCharPref(
          "media.peerconnection.nat_simulator.mapping_type",
          getter_Copies(mapping_type));
      rv = pref_branch->GetCharPref(
          "media.peerconnection.nat_simulator.filtering_type",
          getter_Copies(filtering_type));
      rv = pref_branch->GetBoolPref(
          "media.peerconnection.nat_simulator.block_udp",
          &block_udp);
    }
  }

  if (!mapping_type.IsEmpty() && !filtering_type.IsEmpty()) {
    MOZ_MTLOG(ML_DEBUG, "NAT filtering type: " << filtering_type.get());
    MOZ_MTLOG(ML_DEBUG, "NAT mapping type: " << mapping_type.get());
    TestNat* test_nat = new TestNat;
    test_nat->filtering_type_ = TestNat::ToNatBehavior(filtering_type.get());
    test_nat->mapping_type_ = TestNat::ToNatBehavior(mapping_type.get());
    test_nat->block_udp_ = block_udp;
    test_nat->enabled_ = true;
    SetNat(test_nat);
  }

  // Create the handler objects
  ice_handler_vtbl_ = new nr_ice_handler_vtbl();
  ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
  ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
  ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
  ice_handler_vtbl_->ice_connected = &NrIceCtx::ice_connected;
  ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;
  ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking;
  ice_handler_vtbl_->ice_disconnected = &NrIceCtx::ice_disconnected;

  ice_handler_ = new nr_ice_handler();
  ice_handler_->vtbl = ice_handler_vtbl_;
  ice_handler_->obj = this;

  // Create the peer ctx. Because we do not support parallel forking, we
  // only have one peer ctx.
  std::string peer_name = name_ + ":default";
  r = nr_ice_peer_ctx_create(ctx_, ice_handler_,
                             const_cast<char *>(peer_name.c_str()),
                             &peer_);
  if (r) {
    MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name_ << "'");
    return false;
  }

  sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);

  if (!NS_SUCCEEDED(rv))
    return false;

  return true;
}