/*
 *  Copyright 2017 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/ice_transport_internal.h"

#include <algorithm>
#include <optional>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/packet_transport_internal.h"
#include "rtc_base/checks.h"
#include "rtc_base/net_helper.h"

namespace webrtc {
namespace {

// RTCConfiguration uses kUndefined (-1) to indicate unset optional parameters.
std::optional<TimeDelta> RTCConfigurationToIceConfigOptionalMillis(
    int rtc_configuration_parameter) {
  if (rtc_configuration_parameter ==
      PeerConnectionInterface::RTCConfiguration::kUndefined) {
    return std::nullopt;
  }
  return TimeDelta::Millis(rtc_configuration_parameter);
}

std::optional<TimeDelta> ToOptionalMillis(std::optional<int> ms) {
  if (ms == std::nullopt) {
    return std::nullopt;
  }
  return TimeDelta::Millis(*ms);
}

ContinualGatheringPolicy GetContinualGatheringPolicy(
    const PeerConnectionInterface::RTCConfiguration& config) {
  switch (config.continual_gathering_policy) {
    case PeerConnectionInterface::GATHER_ONCE:
      return GATHER_ONCE;
    case PeerConnectionInterface::GATHER_CONTINUALLY:
      return GATHER_CONTINUALLY;
    default:
      break;
  }
  RTC_DCHECK_NOTREACHED();
  return GATHER_ONCE;
}

}  // namespace

RTCError VerifyCandidate(const Candidate& cand) {
  // No address zero.
  if (cand.address().IsNil() || cand.address().IsAnyIP()) {
    return RTCError(RTCErrorType::INVALID_PARAMETER,
                    "candidate has address of zero");
  }

  // Disallow all ports below 1024, except for 80 and 443 on public addresses.
  int port = cand.address().port();
  if (cand.protocol() == TCP_PROTOCOL_NAME &&
      (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) {
    // Expected for active-only candidates per
    // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
    // Libjingle clients emit port 0, in "active" mode.
    return RTCError::OK();
  }
  if (port < 1024) {
    if ((port != 80) && (port != 443)) {
      return RTCError(RTCErrorType::INVALID_PARAMETER,
                      "candidate has port below 1024, but not 80 or 443");
    }

    if (cand.address().IsPrivateIP()) {
      return RTCError(
          RTCErrorType::INVALID_PARAMETER,
          "candidate has port of 80 or 443 with private IP address");
    }
  }

  return RTCError::OK();
}

RTCError VerifyCandidates(const Candidates& candidates) {
  for (const Candidate& candidate : candidates) {
    RTCError error = VerifyCandidate(candidate);
    if (!error.ok())
      return error;
  }
  return RTCError::OK();
}

IceConfig::IceConfig() = default;

IceConfig::IceConfig(TimeDelta receiving_timeout,
                     TimeDelta backup_connection_ping_interval,
                     ContinualGatheringPolicy gathering_policy,
                     bool prioritize_most_likely_candidate_pairs,
                     TimeDelta stable_writable_connection_ping_interval,
                     bool presume_writable_when_fully_relayed,
                     TimeDelta regather_on_failed_networks_interval,
                     TimeDelta receiving_switching_delay)
    : receiving_timeout(receiving_timeout),
      backup_connection_ping_interval(backup_connection_ping_interval),
      continual_gathering_policy(gathering_policy),
      prioritize_most_likely_candidate_pairs(
          prioritize_most_likely_candidate_pairs),
      stable_writable_connection_ping_interval(
          stable_writable_connection_ping_interval),
      presume_writable_when_fully_relayed(presume_writable_when_fully_relayed),
      regather_on_failed_networks_interval(
          regather_on_failed_networks_interval),
      receiving_switching_delay(receiving_switching_delay) {}

IceConfig::IceConfig(const PeerConnectionInterface::RTCConfiguration& config)
    : receiving_timeout(RTCConfigurationToIceConfigOptionalMillis(
          config.ice_connection_receiving_timeout)),
      backup_connection_ping_interval(RTCConfigurationToIceConfigOptionalMillis(
          config.ice_backup_candidate_pair_ping_interval)),
      continual_gathering_policy(GetContinualGatheringPolicy(config)),
      prioritize_most_likely_candidate_pairs(
          config.prioritize_most_likely_ice_candidate_pairs),
      stable_writable_connection_ping_interval(
          ToOptionalMillis(config.stable_writable_connection_ping_interval_ms)),
      presume_writable_when_fully_relayed(
          config.presume_writable_when_fully_relayed),
      surface_ice_candidates_on_ice_transport_type_changed(
          config.surface_ice_candidates_on_ice_transport_type_changed),
      ice_check_interval_strong_connectivity(
          ToOptionalMillis(config.ice_check_interval_strong_connectivity)),
      ice_check_interval_weak_connectivity(
          ToOptionalMillis(config.ice_check_interval_weak_connectivity)),
      ice_check_min_interval(ToOptionalMillis(config.ice_check_min_interval)),
      ice_unwritable_timeout(ToOptionalMillis(config.ice_unwritable_timeout)),
      ice_unwritable_min_checks(config.ice_unwritable_min_checks),
      ice_inactive_timeout(ToOptionalMillis(config.ice_inactive_timeout)),
      stun_keepalive_interval(
          ToOptionalMillis(config.stun_candidate_keepalive_interval)),
      network_preference(config.network_preference) {}

IceConfig::~IceConfig() = default;

TimeDelta IceConfig::receiving_timeout_or_default() const {
  return receiving_timeout.value_or(kReceivingTimeout);
}
TimeDelta IceConfig::backup_connection_ping_interval_or_default() const {
  return backup_connection_ping_interval.value_or(
      kBackupConnectionPingInterval);
}
TimeDelta IceConfig::stable_writable_connection_ping_interval_or_default()
    const {
  return stable_writable_connection_ping_interval.value_or(
      kStrongAndStableWritableConnectionPingInterval);
}
TimeDelta IceConfig::regather_on_failed_networks_interval_or_default() const {
  return regather_on_failed_networks_interval.value_or(
      kRegatherOnFailedNetworksInterval);
}
TimeDelta IceConfig::receiving_switching_delay_or_default() const {
  return receiving_switching_delay.value_or(kReceivingSwitchingDelay);
}
TimeDelta IceConfig::ice_check_interval_strong_connectivity_or_default() const {
  return ice_check_interval_strong_connectivity.value_or(kStrongPingInterval);
}
TimeDelta IceConfig::ice_check_interval_weak_connectivity_or_default() const {
  return ice_check_interval_weak_connectivity.value_or(kWeakPingInterval);
}
TimeDelta IceConfig::ice_check_min_interval_or_default() const {
  return ice_check_min_interval.value_or(TimeDelta::Millis(-1));
}
TimeDelta IceConfig::ice_unwritable_timeout_or_default() const {
  return ice_unwritable_timeout.value_or(kConnectionWriteConnectTimeout);
}
int IceConfig::ice_unwritable_min_checks_or_default() const {
  return ice_unwritable_min_checks.value_or(kConnectionWriteConnectFailures);
}
TimeDelta IceConfig::ice_inactive_timeout_or_default() const {
  return ice_inactive_timeout.value_or(kConnectionWriteTimeout);
}
TimeDelta IceConfig::stun_keepalive_interval_or_default() const {
  return stun_keepalive_interval.value_or(kStunKeepaliveInterval);
}

RTCError IceConfig::IsValid() const {
  if (ice_check_interval_strong_connectivity_or_default() <
      ice_check_interval_weak_connectivity.value_or(kWeakPingInterval)) {
    return RTCError(RTCErrorType::INVALID_PARAMETER,
                    "Ping interval of candidate pairs is shorter when ICE is "
                    "strongly connected than that when ICE is weakly "
                    "connected");
  }

  if (receiving_timeout_or_default() <
      std::max(ice_check_interval_strong_connectivity_or_default(),
               ice_check_min_interval_or_default())) {
    return RTCError(
        RTCErrorType::INVALID_PARAMETER,
        "Receiving timeout is shorter than the minimal ping interval.");
  }

  if (backup_connection_ping_interval_or_default() <
      ice_check_interval_strong_connectivity_or_default()) {
    return RTCError(RTCErrorType::INVALID_PARAMETER,
                    "Ping interval of backup candidate pairs is shorter than "
                    "that of general candidate pairs when ICE is strongly "
                    "connected");
  }

  if (stable_writable_connection_ping_interval_or_default() <
      ice_check_interval_strong_connectivity_or_default()) {
    return RTCError(RTCErrorType::INVALID_PARAMETER,
                    "Ping interval of stable and writable candidate pairs is "
                    "shorter than that of general candidate pairs when ICE is "
                    "strongly connected");
  }

  if (ice_unwritable_timeout_or_default() > ice_inactive_timeout_or_default()) {
    return RTCError(RTCErrorType::INVALID_PARAMETER,
                    "The timeout period for the writability state to become "
                    "UNRELIABLE is longer than that to become TIMEOUT.");
  }

  return RTCError::OK();
}

IceTransportInternal::IceTransportInternal(TaskQueueBase* attached_queue)
    : PacketTransportInternal(attached_queue) {}

IceTransportInternal::~IceTransportInternal() = default;

void IceTransportInternal::AddGatheringStateCallback(
    const void* removal_tag,
    absl::AnyInvocable<void(IceTransportInternal*)> callback) {
  gathering_state_callback_list_.AddReceiver(removal_tag, std::move(callback));
}
void IceTransportInternal::RemoveGatheringStateCallback(
    const void* removal_tag) {
  gathering_state_callback_list_.RemoveReceivers(removal_tag);
}

void IceTransportInternal::SubscribeCandidateGathered(
    void* tag,
    absl::AnyInvocable<void(IceTransportInternal*, const Candidate&)>
        callback) {
  candidate_gathered_callbacks_.AddReceiver(tag, std::move(callback));
}

void IceTransportInternal::SubscribeRoleConflict(
    void* tag,
    absl::AnyInvocable<void(IceTransportInternal*)> callback) {
  role_conflict_callbacks_.AddReceiver(tag, std::move(callback));
}

void IceTransportInternal::SubscribeIceTransportStateChanged(
    void* tag,
    absl::AnyInvocable<void(IceTransportInternal*)> callback) {
  ice_transport_state_changed_callbacks_.AddReceiver(tag, std::move(callback));
}

}  // namespace webrtc
