/*
 *  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 "pc/ice_server_parsing.h"

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

#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/port.h"
#include "p2p/base/port_allocator.h"
#include "p2p/base/port_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/string_to_number.h"

namespace webrtc {

namespace {
// Number of tokens must be preset when TURN uri has transport param.
const size_t kTurnTransportTokensNum = 2;
// The default stun port.
const int kDefaultStunPort = 3478;
const int kDefaultStunTlsPort = 5349;
const char kTransport[] = "transport";

// Allowed characters in hostname per RFC 3986 Appendix A "reg-name"
const char kRegNameCharacters[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789"
    "-._~"          // unreserved
    "%"             // pct-encoded
    "!$&'()*+,;=";  // sub-delims

// NOTE: Must be in the same order as the ServiceType enum.
const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"};

// NOTE: A loop below assumes that the first value of this enum is 0 and all
// other values are incremental.
enum class ServiceType {
  STUN = 0,  // Indicates a STUN server.
  STUNS,     // Indicates a STUN server used with a TLS session.
  TURN,      // Indicates a TURN server
  TURNS,     // Indicates a TURN server used with a TLS session.
  INVALID,   // Unknown.
};
static_assert(static_cast<size_t>(ServiceType::INVALID) ==
                  std::size(kValidIceServiceTypes),
              "kValidIceServiceTypes must have as many strings as ServiceType "
              "has values.");

// `in_str` should follow of RFC 7064/7065 syntax, but with an optional
// "?transport=" already stripped. I.e.,
// stunURI       = scheme ":" host [ ":" port ]
// scheme        = "stun" / "stuns" / "turn" / "turns"
// host          = IP-literal / IPv4address / reg-name
// port          = *DIGIT

// Return tuple is service_type, host, with service_type == ServiceType::INVALID
// on failure.
std::tuple<ServiceType, absl::string_view> GetServiceTypeAndHostnameFromUri(
    absl::string_view in_str) {
  const auto colonpos = in_str.find(':');
  if (colonpos == absl::string_view::npos) {
    RTC_LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str;
    return {ServiceType::INVALID, ""};
  }
  if ((colonpos + 1) == in_str.length()) {
    RTC_LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str;
    return {ServiceType::INVALID, ""};
  }
  for (size_t i = 0; i < std::size(kValidIceServiceTypes); ++i) {
    if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) {
      return {static_cast<ServiceType>(i), in_str.substr(colonpos + 1)};
    }
  }
  return {ServiceType::INVALID, ""};
}

std::optional<int> ParsePort(absl::string_view in_str) {
  // Make sure port only contains digits. StringToNumber doesn't check this.
  for (const char& c : in_str) {
    if (!std::isdigit(static_cast<unsigned char>(c))) {
      return false;
    }
  }
  return StringToNumber<int>(in_str);
}

// This method parses IPv6 and IPv4 literal strings, along with hostnames in
// standard hostname:port format.
// Consider following formats as correct.
// `hostname:port`, |[IPV6 address]:port|, |IPv4 address|:port,
// `hostname`, |[IPv6 address]|, |IPv4 address|.

// Return tuple is success, host, port.
std::tuple<bool, absl::string_view, int> ParseHostnameAndPortFromString(
    absl::string_view in_str,
    int default_port) {
  if (in_str.empty()) {
    return {false, "", 0};
  }
  absl::string_view host;
  int port = default_port;

  if (in_str.at(0) == '[') {
    // IP_literal syntax
    auto closebracket = in_str.rfind(']');
    if (closebracket == absl::string_view::npos) {
      return {false, "", 0};
    }
    auto colonpos = in_str.find(':', closebracket);
    if (absl::string_view::npos != colonpos) {
      if (std::optional<int> opt_port =
              ParsePort(in_str.substr(closebracket + 2))) {
        port = *opt_port;
      } else {
        return {false, "", 0};
      }
    }
    host = in_str.substr(1, closebracket - 1);
  } else {
    // IPv4address or reg-name syntax
    auto colonpos = in_str.find(':');
    if (absl::string_view::npos != colonpos) {
      if (std::optional<int> opt_port =
              ParsePort(in_str.substr(colonpos + 1))) {
        port = *opt_port;
      } else {
        return {false, "", 0};
      }
      host = in_str.substr(0, colonpos);
    } else {
      host = in_str;
    }
    // RFC 3986 section 3.2.2 and Appendix A - "reg-name" syntax
    if (host.find_first_not_of(kRegNameCharacters) != absl::string_view::npos) {
      return {false, "", 0};
    }
  }
  return {!host.empty(), host, port};
}

// Adds a STUN or TURN server to the appropriate list,
// by parsing `url` and using the username/password in `server`.
RTCError ParseIceServerUrl(const PeerConnectionInterface::IceServer& server,
                           absl::string_view url,
                           ServerAddresses* stun_servers,
                           std::vector<RelayServerConfig>* turn_servers) {
  // RFC 7064
  // stunURI       = scheme ":" host [ ":" port ]
  // scheme        = "stun" / "stuns"

  // RFC 7065
  // turnURI       = scheme ":" host [ ":" port ]
  //                 [ "?transport=" transport ]
  // scheme        = "turn" / "turns"
  // transport     = "udp" / "tcp" / transport-ext
  // transport-ext = 1*unreserved

  // RFC 3986
  // host     = IP-literal / IPv4address / reg-name
  // port     = *DIGIT

  RTC_DCHECK(stun_servers != nullptr);
  RTC_DCHECK(turn_servers != nullptr);
  ProtocolType turn_transport_type = PROTO_UDP;
  RTC_DCHECK(!url.empty());
  std::vector<absl::string_view> tokens = split(url, '?');
  absl::string_view uri_without_transport = tokens[0];
  // Let's look into transport= param, if it exists.
  if (tokens.size() == kTurnTransportTokensNum) {  // ?transport= is present.
    std::vector<absl::string_view> transport_tokens = split(tokens[1], '=');
    if (transport_tokens[0] != kTransport) {
      LOG_AND_RETURN_ERROR(
          RTCErrorType::SYNTAX_ERROR,
          "ICE server parsing failed: Invalid transport parameter key.");
    }
    if (transport_tokens.size() < 2) {
      LOG_AND_RETURN_ERROR(
          RTCErrorType::SYNTAX_ERROR,
          "ICE server parsing failed: Transport parameter missing value.");
    }

    std::optional<ProtocolType> proto = StringToProto(transport_tokens[1]);
    if (!proto || (*proto != PROTO_UDP && *proto != PROTO_TCP)) {
      LOG_AND_RETURN_ERROR(
          RTCErrorType::SYNTAX_ERROR,
          "ICE server parsing failed: Transport parameter should "
          "always be udp or tcp.");
    }
    turn_transport_type = *proto;
  }

  auto [service_type, hoststring] =
      GetServiceTypeAndHostnameFromUri(uri_without_transport);
  if (service_type == ServiceType::INVALID) {
    RTC_LOG(LS_ERROR) << "Invalid transport parameter in ICE URI: " << url;
    LOG_AND_RETURN_ERROR(
        RTCErrorType::SYNTAX_ERROR,
        "ICE server parsing failed: Invalid transport parameter in ICE URI");
  }

  // GetServiceTypeAndHostnameFromUri should never give an empty hoststring
  RTC_DCHECK(!hoststring.empty());

  // stun with ?transport (or any ?) is not valid.
  if ((service_type == ServiceType::STUN ||
       service_type == ServiceType::STUNS) &&
      tokens.size() > 1) {
    LOG_AND_RETURN_ERROR(
        RTCErrorType::SYNTAX_ERROR,
        "ICE server parsing failed: Invalid stun url with query parameters");
  }

  int default_port = kDefaultStunPort;
  if (service_type == ServiceType::TURNS) {
    default_port = kDefaultStunTlsPort;
    turn_transport_type = PROTO_TLS;
  }

  if (hoststring.find('@') != absl::string_view::npos) {
    RTC_LOG(LS_ERROR) << "Invalid url with long deprecated user@host syntax: "
                      << uri_without_transport;
    LOG_AND_RETURN_ERROR(RTCErrorType::SYNTAX_ERROR,
                         "ICE server parsing failed: Invalid url with long "
                         "deprecated user@host syntax");
  }

  auto [success, address, port] =
      ParseHostnameAndPortFromString(hoststring, default_port);
  if (!success) {
    RTC_LOG(LS_ERROR) << "Invalid hostname format: " << uri_without_transport;
    LOG_AND_RETURN_ERROR(RTCErrorType::SYNTAX_ERROR,
                         "ICE server parsing failed: Invalid hostname format");
  }

  if (port <= 0 || port > 0xffff) {
    RTC_LOG(LS_ERROR) << "Invalid port: " << port;
    LOG_AND_RETURN_ERROR(RTCErrorType::SYNTAX_ERROR,
                         "ICE server parsing failed: Invalid port");
  }

  switch (service_type) {
    case ServiceType::STUN:
    case ServiceType::STUNS:
      stun_servers->insert(SocketAddress(address, port));
      break;
    case ServiceType::TURN:
    case ServiceType::TURNS: {
      if (server.username.empty() || server.password.empty()) {
        // The WebRTC spec requires throwing an InvalidAccessError when username
        // or credential are ommitted; this is the native equivalent.
        LOG_AND_RETURN_ERROR(
            RTCErrorType::INVALID_PARAMETER,
            "ICE server parsing failed: TURN server with empty "
            "username or password");
      }
      // RFC 8489 limits the size of the STUN username field to 509 characters.
      if (server.username.size() > kMaxTurnUsernameLength) {
        LOG_AND_RETURN_ERROR(
            RTCErrorType::INVALID_PARAMETER,
            "ICE server parsing failed: TURN server username is too long");
      }
      // If the hostname field is not empty, then the server address must be
      // the resolved IP for that host, the hostname is needed later for TLS
      // handshake (SNI and Certificate verification).
      absl::string_view hostname =
          server.hostname.empty() ? address : server.hostname;
      SocketAddress socket_address(hostname, port);
      if (!server.hostname.empty()) {
        IPAddress ip;
        if (!IPFromString(address, &ip)) {
          // When hostname is set, the server address must be a
          // resolved ip address.
          LOG_AND_RETURN_ERROR(
              RTCErrorType::INVALID_PARAMETER,
              "ICE server parsing failed: "
              "IceServer has hostname field set, but URI does not "
              "contain an IP address.");
        }
        socket_address.SetResolvedIP(ip);
      }
      RelayServerConfig config =
          RelayServerConfig(socket_address, server.username, server.password,
                            turn_transport_type);
      if (server.tls_cert_policy ==
          PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck) {
        config.tls_cert_policy =
            TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
      }
      config.tls_alpn_protocols = server.tls_alpn_protocols;
      config.tls_elliptic_curves = server.tls_elliptic_curves;

      turn_servers->push_back(config);
      break;
    }
    default:
      // We shouldn't get to this point with an invalid service_type, we should
      // have returned an error already.
      LOG_AND_RETURN_ERROR(
          RTCErrorType::INTERNAL_ERROR,
          "ICE server parsing failed: Unexpected service type");
  }
  return RTCError::OK();
}

}  // namespace

RTCError ParseIceServersOrError(
    const PeerConnectionInterface::IceServers& servers,
    ServerAddresses* stun_servers,
    std::vector<RelayServerConfig>* turn_servers) {
  for (const PeerConnectionInterface::IceServer& server : servers) {
    if (!server.urls.empty()) {
      for (const std::string& url : server.urls) {
        if (url.empty()) {
          LOG_AND_RETURN_ERROR(RTCErrorType::SYNTAX_ERROR,
                               "ICE server parsing failed: Empty uri.");
        }
        RTCError err =
            ParseIceServerUrl(server, url, stun_servers, turn_servers);
        if (!err.ok()) {
          return err;
        }
      }
    } else if (!server.uri.empty()) {
      // Fallback to old .uri if new .urls isn't present.
      RTCError err =
          ParseIceServerUrl(server, server.uri, stun_servers, turn_servers);

      if (!err.ok()) {
        return err;
      }
    } else {
      LOG_AND_RETURN_ERROR(RTCErrorType::SYNTAX_ERROR,
                           "ICE server parsing failed: Empty uri.");
    }
  }
  return RTCError::OK();
}

RTCError ParseAndValidateIceServersFromConfiguration(
    const PeerConnectionInterface::RTCConfiguration& configuration,
    ServerAddresses& stun_servers,
    std::vector<RelayServerConfig>& turn_servers) {
  RTC_DCHECK(stun_servers.empty());
  RTC_DCHECK(turn_servers.empty());
  RTCError err = ParseIceServersOrError(configuration.servers, &stun_servers,
                                        &turn_servers);
  if (!err.ok()) {
    return err;
  }

  // Restrict number of TURN servers.
  if (turn_servers.size() > kMaxTurnServers) {
    RTC_LOG(LS_WARNING) << "Number of configured TURN servers is "
                        << turn_servers.size()
                        << " which exceeds the maximum allowed number of "
                        << kMaxTurnServers;
    turn_servers.resize(kMaxTurnServers);
  }

  // Add the turn logging id to all turn servers
  for (RelayServerConfig& turn_server : turn_servers) {
    turn_server.turn_logging_id = configuration.turn_logging_id;
  }

  return RTCError::OK();
}

}  // namespace webrtc
