/*
 *  Copyright 2013 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/transport_description.h"

#include <cstddef>
#include <optional>
#include <string>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "api/rtc_error.h"
#include "p2p/base/p2p_constants.h"
#include "rtc_base/logging.h"
#include "rtc_base/ssl_fingerprint.h"
#include "rtc_base/strings/string_builder.h"

using webrtc::RTCError;
using webrtc::RTCErrorOr;
using webrtc::RTCErrorType;

namespace webrtc {
namespace {

bool IsIceChar(char c) {
  // Note: '-', '=', '#' and '_' are *not* valid ice-chars but temporarily
  // permitted in order to allow external software to upgrade.
  if (c == '-' || c == '=' || c == '#' || c == '_') {
    RTC_LOG(LS_WARNING)
        << "'-', '=', '#' and '_' are not valid ice-char and thus not "
        << "permitted in ufrag or pwd. This is a protocol violation that "
        << "is permitted to allow upgrading but will be rejected in "
        << "the future. See https://crbug.com/1053756";
    return true;
  }
  return absl::ascii_isalnum(c) || c == '+' || c == '/';
}

RTCError ValidateIceUfrag(absl::string_view raw_ufrag) {
  if (!(ICE_UFRAG_MIN_LENGTH <= raw_ufrag.size() &&
        raw_ufrag.size() <= ICE_UFRAG_MAX_LENGTH)) {
    StringBuilder sb;
    sb << "ICE ufrag must be between " << ICE_UFRAG_MIN_LENGTH << " and "
       << ICE_UFRAG_MAX_LENGTH << " characters long.";
    return RTCError(RTCErrorType::SYNTAX_ERROR, sb.Release());
  }

  if (!absl::c_all_of(raw_ufrag, IsIceChar)) {
    return RTCError(
        RTCErrorType::SYNTAX_ERROR,
        "ICE ufrag must contain only alphanumeric characters, '+', and '/'.");
  }

  return RTCError::OK();
}

RTCError ValidateIcePwd(absl::string_view raw_pwd) {
  if (!(ICE_PWD_MIN_LENGTH <= raw_pwd.size() &&
        raw_pwd.size() <= ICE_PWD_MAX_LENGTH)) {
    StringBuilder sb;
    sb << "ICE pwd must be between " << ICE_PWD_MIN_LENGTH << " and "
       << ICE_PWD_MAX_LENGTH << " characters long.";
    return RTCError(RTCErrorType::SYNTAX_ERROR, sb.Release());
  }

  if (!absl::c_all_of(raw_pwd, IsIceChar)) {
    return RTCError(
        RTCErrorType::SYNTAX_ERROR,
        "ICE pwd must contain only alphanumeric characters, '+', and '/'.");
  }

  return RTCError::OK();
}

}  // namespace

RTCErrorOr<IceParameters> IceParameters::Parse(absl::string_view raw_ufrag,
                                               absl::string_view raw_pwd) {
  IceParameters parameters(std::string(raw_ufrag), std::string(raw_pwd),
                           /* ice_renomination= */ false);
  auto result = parameters.Validate();
  if (!result.ok()) {
    return result;
  }
  return parameters;
}

RTCError IceParameters::Validate() const {
  // For legacy protocols.
  // TODO(zhihuang): Remove this once the legacy protocol is no longer
  // supported.
  if (ufrag.empty() && pwd.empty()) {
    return RTCError::OK();
  }

  auto ufrag_result = ValidateIceUfrag(ufrag);
  if (!ufrag_result.ok()) {
    return ufrag_result;
  }

  auto pwd_result = ValidateIcePwd(pwd);
  if (!pwd_result.ok()) {
    return pwd_result;
  }

  return RTCError::OK();
}

std::optional<ConnectionRole> StringToConnectionRole(
    absl::string_view role_str) {
  const char* const roles[] = {
      CONNECTIONROLE_ACTIVE_STR, CONNECTIONROLE_PASSIVE_STR,
      CONNECTIONROLE_ACTPASS_STR, CONNECTIONROLE_HOLDCONN_STR};

  for (size_t i = 0; i < std::size(roles); ++i) {
    if (absl::EqualsIgnoreCase(roles[i], role_str)) {
      return static_cast<ConnectionRole>(CONNECTIONROLE_ACTIVE + i);
    }
  }
  return std::nullopt;
}

bool ConnectionRoleToString(const ConnectionRole& role, std::string* role_str) {
  switch (role) {
    case CONNECTIONROLE_ACTIVE:
      *role_str = CONNECTIONROLE_ACTIVE_STR;
      break;
    case CONNECTIONROLE_ACTPASS:
      *role_str = CONNECTIONROLE_ACTPASS_STR;
      break;
    case CONNECTIONROLE_PASSIVE:
      *role_str = CONNECTIONROLE_PASSIVE_STR;
      break;
    case CONNECTIONROLE_HOLDCONN:
      *role_str = CONNECTIONROLE_HOLDCONN_STR;
      break;
    default:
      return false;
  }
  return true;
}

TransportDescription::TransportDescription()
    : ice_mode(ICEMODE_FULL),
      connection_role(CONNECTIONROLE_NONE),
      cryptex(false) {}

TransportDescription::TransportDescription(
    const std::vector<std::string>& transport_options,
    absl::string_view ice_ufrag,
    absl::string_view ice_pwd,
    IceMode ice_mode,
    ConnectionRole role,
    const SSLFingerprint* identity_fingerprint)
    : transport_options(transport_options),
      ice_ufrag(ice_ufrag),
      ice_pwd(ice_pwd),
      ice_mode(ice_mode),
      connection_role(role),
      identity_fingerprint(CopyFingerprint(identity_fingerprint)),
      cryptex(false) {}

TransportDescription::TransportDescription(absl::string_view ice_ufrag,
                                           absl::string_view ice_pwd)
    : ice_ufrag(ice_ufrag),
      ice_pwd(ice_pwd),
      ice_mode(ICEMODE_FULL),
      connection_role(CONNECTIONROLE_NONE),
      cryptex(false) {}

TransportDescription::TransportDescription(const TransportDescription& from)
    : transport_options(from.transport_options),
      ice_ufrag(from.ice_ufrag),
      ice_pwd(from.ice_pwd),
      ice_mode(from.ice_mode),
      connection_role(from.connection_role),
      identity_fingerprint(CopyFingerprint(from.identity_fingerprint.get())),
      cryptex(from.cryptex) {}

TransportDescription::~TransportDescription() = default;

TransportDescription& TransportDescription::operator=(
    const TransportDescription& from) {
  // Self-assignment
  if (this == &from)
    return *this;

  transport_options = from.transport_options;
  ice_ufrag = from.ice_ufrag;
  ice_pwd = from.ice_pwd;
  ice_mode = from.ice_mode;
  connection_role = from.connection_role;

  identity_fingerprint.reset(CopyFingerprint(from.identity_fingerprint.get()));
  cryptex = from.cryptex;
  return *this;
}

}  // namespace webrtc
