/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "p2p/base/port_allocator.h"

#include <iterator>
#include <optional>
#include <set>
#include <utility>

#include "absl/strings/string_view.h"
#include "p2p/base/ice_credentials_iterator.h"
#include "rtc_base/checks.h"
#include "rtc_base/crypto_random.h"

namespace cricket {

RelayServerConfig::RelayServerConfig() {}

RelayServerConfig::RelayServerConfig(const rtc::SocketAddress& address,
                                     absl::string_view username,
                                     absl::string_view password,
                                     ProtocolType proto)
    : credentials(username, password) {
  ports.push_back(ProtocolAddress(address, proto));
}

RelayServerConfig::RelayServerConfig(absl::string_view address,
                                     int port,
                                     absl::string_view username,
                                     absl::string_view password,
                                     ProtocolType proto)
    : RelayServerConfig(rtc::SocketAddress(address, port),
                        username,
                        password,
                        proto) {}

// Legacy constructor where "secure" and PROTO_TCP implies PROTO_TLS.
RelayServerConfig::RelayServerConfig(absl::string_view address,
                                     int port,
                                     absl::string_view username,
                                     absl::string_view password,
                                     ProtocolType proto,
                                     bool secure)
    : RelayServerConfig(address,
                        port,
                        username,
                        password,
                        (proto == PROTO_TCP && secure ? PROTO_TLS : proto)) {}

RelayServerConfig::RelayServerConfig(const RelayServerConfig&) = default;

RelayServerConfig::~RelayServerConfig() = default;

PortAllocatorSession::PortAllocatorSession(absl::string_view content_name,
                                           int component,
                                           absl::string_view ice_ufrag,
                                           absl::string_view ice_pwd,
                                           uint32_t flags)
    : flags_(flags),
      generation_(0),
      content_name_(content_name),
      component_(component),
      ice_ufrag_(ice_ufrag),
      ice_pwd_(ice_pwd) {
  // Pooled sessions are allowed to be created with empty content name,
  // component, ufrag and password.
  RTC_DCHECK(ice_ufrag.empty() == ice_pwd.empty());
}

PortAllocatorSession::~PortAllocatorSession() = default;

bool PortAllocatorSession::IsCleared() const {
  return false;
}

bool PortAllocatorSession::IsStopped() const {
  return false;
}

uint32_t PortAllocatorSession::generation() {
  return generation_;
}

void PortAllocatorSession::set_generation(uint32_t generation) {
  generation_ = generation;
}

PortAllocator::PortAllocator()
    : flags_(kDefaultPortAllocatorFlags),
      min_port_(0),
      max_port_(0),
      max_ipv6_networks_(kDefaultMaxIPv6Networks),
      step_delay_(kDefaultStepDelay),
      allow_tcp_listen_(true),
      candidate_filter_(CF_ALL),
      tiebreaker_(rtc::CreateRandomId64()) {
  // The allocator will be attached to a thread in Initialize.
  thread_checker_.Detach();
}

void PortAllocator::Initialize() {
  RTC_DCHECK(thread_checker_.IsCurrent());
  initialized_ = true;
}

PortAllocator::~PortAllocator() {
  CheckRunOnValidThreadIfInitialized();
}

void PortAllocator::set_restrict_ice_credentials_change(bool value) {
  restrict_ice_credentials_change_ = value;
}

// Deprecated
bool PortAllocator::SetConfiguration(
    const ServerAddresses& stun_servers,
    const std::vector<RelayServerConfig>& turn_servers,
    int candidate_pool_size,
    bool prune_turn_ports,
    webrtc::TurnCustomizer* turn_customizer,
    const std::optional<int>& stun_candidate_keepalive_interval) {
  webrtc::PortPrunePolicy turn_port_prune_policy =
      prune_turn_ports ? webrtc::PRUNE_BASED_ON_PRIORITY : webrtc::NO_PRUNE;
  return SetConfiguration(stun_servers, turn_servers, candidate_pool_size,
                          turn_port_prune_policy, turn_customizer,
                          stun_candidate_keepalive_interval);
}

bool PortAllocator::SetConfiguration(
    const ServerAddresses& stun_servers,
    const std::vector<RelayServerConfig>& turn_servers,
    int candidate_pool_size,
    webrtc::PortPrunePolicy turn_port_prune_policy,
    webrtc::TurnCustomizer* turn_customizer,
    const std::optional<int>& stun_candidate_keepalive_interval) {
  RTC_DCHECK_GE(candidate_pool_size, 0);
  RTC_DCHECK_LE(candidate_pool_size, static_cast<int>(UINT16_MAX));
  CheckRunOnValidThreadIfInitialized();
  // A positive candidate pool size would lead to the creation of a pooled
  // allocator session and starting getting ports, which we should only do on
  // the network thread.
  RTC_DCHECK(candidate_pool_size == 0 || thread_checker_.IsCurrent());
  bool ice_servers_changed =
      (stun_servers != stun_servers_ || turn_servers != turn_servers_);
  stun_servers_ = stun_servers;
  turn_servers_ = turn_servers;
  turn_port_prune_policy_ = turn_port_prune_policy;

  candidate_pool_size_ = candidate_pool_size;

  // If ICE servers changed, throw away any existing pooled sessions and create
  // new ones.
  if (ice_servers_changed) {
    pooled_sessions_.clear();
  }

  turn_customizer_ = turn_customizer;

  // If `candidate_pool_size_` is less than the number of pooled sessions, get
  // rid of the extras.
  while (candidate_pool_size_ < static_cast<int>(pooled_sessions_.size())) {
    pooled_sessions_.back().reset(nullptr);
    pooled_sessions_.pop_back();
  }

  // `stun_candidate_keepalive_interval_` will be used in STUN port allocation
  // in future sessions. We also update the ready ports in the pooled sessions.
  // Ports in sessions that are taken and owned by P2PTransportChannel will be
  // updated there via IceConfig.
  stun_candidate_keepalive_interval_ = stun_candidate_keepalive_interval;
  for (const auto& session : pooled_sessions_) {
    session->SetStunKeepaliveIntervalForReadyPorts(
        stun_candidate_keepalive_interval_);
  }

  // If `candidate_pool_size_` is greater than the number of pooled sessions,
  // create new sessions.
  while (static_cast<int>(pooled_sessions_.size()) < candidate_pool_size_) {
    IceParameters iceCredentials =
        IceCredentialsIterator::CreateRandomIceCredentials();
    PortAllocatorSession* pooled_session =
        CreateSessionInternal("", 0, iceCredentials.ufrag, iceCredentials.pwd);
    pooled_session->set_pooled(true);
    pooled_session->StartGettingPorts();
    pooled_sessions_.push_back(
        std::unique_ptr<PortAllocatorSession>(pooled_session));
  }
  return true;
}

std::unique_ptr<PortAllocatorSession> PortAllocator::CreateSession(
    absl::string_view content_name,
    int component,
    absl::string_view ice_ufrag,
    absl::string_view ice_pwd) {
  CheckRunOnValidThreadAndInitialized();
  auto session = std::unique_ptr<PortAllocatorSession>(
      CreateSessionInternal(content_name, component, ice_ufrag, ice_pwd));
  session->SetCandidateFilter(candidate_filter());
  return session;
}

std::unique_ptr<PortAllocatorSession> PortAllocator::TakePooledSession(
    absl::string_view content_name,
    int component,
    absl::string_view ice_ufrag,
    absl::string_view ice_pwd) {
  CheckRunOnValidThreadAndInitialized();
  RTC_DCHECK(!ice_ufrag.empty());
  RTC_DCHECK(!ice_pwd.empty());
  if (pooled_sessions_.empty()) {
    return nullptr;
  }

  IceParameters credentials(ice_ufrag, ice_pwd, false);
  // If restrict_ice_credentials_change_ is TRUE, then call FindPooledSession
  // with ice credentials. Otherwise call it with nullptr which means
  // "find any" pooled session.
  auto cit = FindPooledSession(restrict_ice_credentials_change_ ? &credentials
                                                                : nullptr);
  if (cit == pooled_sessions_.end()) {
    return nullptr;
  }

  auto it =
      pooled_sessions_.begin() + std::distance(pooled_sessions_.cbegin(), cit);
  std::unique_ptr<PortAllocatorSession> ret = std::move(*it);
  ret->SetIceParameters(content_name, component, ice_ufrag, ice_pwd);
  ret->set_pooled(false);
  // According to JSEP, a pooled session should filter candidates only
  // after it's taken out of the pool.
  ret->SetCandidateFilter(candidate_filter());
  pooled_sessions_.erase(it);
  return ret;
}

const PortAllocatorSession* PortAllocator::GetPooledSession(
    const IceParameters* ice_credentials) const {
  CheckRunOnValidThreadAndInitialized();
  auto it = FindPooledSession(ice_credentials);
  if (it == pooled_sessions_.end()) {
    return nullptr;
  } else {
    return it->get();
  }
}

std::vector<std::unique_ptr<PortAllocatorSession>>::const_iterator
PortAllocator::FindPooledSession(const IceParameters* ice_credentials) const {
  for (auto it = pooled_sessions_.begin(); it != pooled_sessions_.end(); ++it) {
    if (ice_credentials == nullptr ||
        ((*it)->ice_ufrag() == ice_credentials->ufrag &&
         (*it)->ice_pwd() == ice_credentials->pwd)) {
      return it;
    }
  }
  return pooled_sessions_.end();
}

void PortAllocator::DiscardCandidatePool() {
  CheckRunOnValidThreadIfInitialized();
  pooled_sessions_.clear();
}

void PortAllocator::SetCandidateFilter(uint32_t filter) {
  CheckRunOnValidThreadIfInitialized();
  if (candidate_filter_ == filter) {
    return;
  }
  uint32_t prev_filter = candidate_filter_;
  candidate_filter_ = filter;
  SignalCandidateFilterChanged(prev_filter, filter);
}

void PortAllocator::GetCandidateStatsFromPooledSessions(
    CandidateStatsList* candidate_stats_list) {
  CheckRunOnValidThreadAndInitialized();
  for (const auto& session : pooled_sessions()) {
    session->GetCandidateStatsFromReadyPorts(candidate_stats_list);
  }
}

std::vector<IceParameters> PortAllocator::GetPooledIceCredentials() {
  CheckRunOnValidThreadAndInitialized();
  std::vector<IceParameters> list;
  for (const auto& session : pooled_sessions_) {
    list.push_back(
        IceParameters(session->ice_ufrag(), session->ice_pwd(), false));
  }
  return list;
}

Candidate PortAllocator::SanitizeCandidate(const Candidate& c) const {
  CheckRunOnValidThreadAndInitialized();
  // For a local host candidate, we need to conceal its IP address candidate if
  // the mDNS obfuscation is enabled.
  bool use_hostname_address =
      (c.is_local() || c.is_prflx()) && MdnsObfuscationEnabled();
  // If adapter enumeration is disabled or host candidates are disabled,
  // clear the raddr of STUN candidates to avoid local address leakage.
  bool filter_stun_related_address =
      ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
       (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) ||
      !(candidate_filter_ & CF_HOST) || MdnsObfuscationEnabled();
  // If the candidate filter doesn't allow reflexive addresses, empty TURN raddr
  // to avoid reflexive address leakage.
  bool filter_turn_related_address = !(candidate_filter_ & CF_REFLEXIVE);
  // Sanitize related_address when using MDNS.
  bool filter_prflx_related_address = MdnsObfuscationEnabled();
  bool filter_related_address =
      ((c.is_stun() && filter_stun_related_address) ||
       (c.is_relay() && filter_turn_related_address) ||
       (c.is_prflx() && filter_prflx_related_address));
  return c.ToSanitizedCopy(use_hostname_address, filter_related_address);
}

}  // namespace cricket
