/*
 *  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 "api/jsep.h"

#include <algorithm>
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/sequence_checker.h"
#include "api/webrtc_sdp.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/transport_info.h"
#include "pc/session_description.h"
#include "rtc_base/checks.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/net_helpers.h"
#include "rtc_base/socket_address.h"

namespace webrtc {
namespace {
constexpr char kDummyAddress[] = "0.0.0.0";
constexpr int kDummyPort = 9;

// Update the connection address for the MediaContentDescription based on the
// candidates.
void UpdateConnectionAddress(const IceCandidateCollection& candidate_collection,
                             MediaContentDescription* media_desc) {
  int port = kDummyPort;
  std::string ip = kDummyAddress;
  std::string hostname;
  int current_preference = 0;  // Start with lowest preference.
  int current_family = AF_UNSPEC;
  for (size_t i = 0; i < candidate_collection.count(); ++i) {
    const IceCandidate* jsep_candidate = candidate_collection.at(i);
    if (jsep_candidate->candidate().component() !=
        ICE_CANDIDATE_COMPONENT_RTP) {
      continue;
    }
    // Default destination should be UDP only.
    if (jsep_candidate->candidate().protocol() != UDP_PROTOCOL_NAME) {
      continue;
    }
    const int preference = jsep_candidate->candidate().type_preference();
    const int family = jsep_candidate->candidate().address().ipaddr().family();
    // See if this candidate is more preferable then the current one if it's the
    // same family. Or if the current family is IPv4 already so we could safely
    // ignore all IPv6 ones. WebRTC bug 4269.
    // http://code.google.com/p/webrtc/issues/detail?id=4269
    if ((preference <= current_preference && current_family == family) ||
        (current_family == AF_INET && family == AF_INET6)) {
      continue;
    }
    current_preference = preference;
    current_family = family;
    const SocketAddress& candidate_addr = jsep_candidate->candidate().address();
    port = candidate_addr.port();
    ip = candidate_addr.ipaddr().ToString();
    hostname = candidate_addr.hostname();
  }
  SocketAddress connection_addr(ip, port);
  if (IPIsUnspec(connection_addr.ipaddr()) && !hostname.empty()) {
    // When a hostname candidate becomes the (default) connection address,
    // we use the dummy address 0.0.0.0 and port 9 in the c= and the m= lines.
    //
    // We have observed in deployment that with a FQDN in a c= line, SDP parsing
    // could fail in other JSEP implementations. We note that the wildcard
    // addresses (0.0.0.0 or ::) with port 9 are given the exception as the
    // connection address that will not result in an ICE mismatch
    // (draft-ietf-mmusic-ice-sip-sdp). Also, 0.0.0.0 or :: can be used as the
    // connection address in the initial offer or answer with trickle ICE
    // if the offerer or answerer does not want to include the host IP address
    // (draft-ietf-mmusic-trickle-ice-sip), and in particular 0.0.0.0 has been
    // widely deployed for this use without outstanding compatibility issues.
    // Combining the above considerations, we use 0.0.0.0 with port 9 to
    // populate the c= and the m= lines. See `BuildMediaDescription` in
    // webrtc_sdp.cc for the SDP generation with
    // `media_desc->connection_address()`.
    connection_addr = SocketAddress(kDummyAddress, kDummyPort);
  }
  media_desc->set_connection_address(connection_addr);
}

std::vector<IceCandidateCollection> CloneCandidateCollection(
    const std::vector<IceCandidateCollection>& original) {
  std::vector<IceCandidateCollection> ret;
  ret.reserve(original.size());
  for (const auto& collection : original) {
    ret.push_back(collection.Clone());
  }
  return ret;
}
}  // namespace

const char SessionDescriptionInterface::kOffer[] = "offer";
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
const char SessionDescriptionInterface::kAnswer[] = "answer";
const char SessionDescriptionInterface::kRollback[] = "rollback";

const char* SdpTypeToString(SdpType type) {
  switch (type) {
    case SdpType::kOffer:
      return SessionDescriptionInterface::kOffer;
    case SdpType::kPrAnswer:
      return SessionDescriptionInterface::kPrAnswer;
    case SdpType::kAnswer:
      return SessionDescriptionInterface::kAnswer;
    case SdpType::kRollback:
      return SessionDescriptionInterface::kRollback;
  }
  return "";
}

std::optional<SdpType> SdpTypeFromString(const std::string& type_str) {
  if (type_str == SessionDescriptionInterface::kOffer) {
    return SdpType::kOffer;
  } else if (type_str == SessionDescriptionInterface::kPrAnswer) {
    return SdpType::kPrAnswer;
  } else if (type_str == SessionDescriptionInterface::kAnswer) {
    return SdpType::kAnswer;
  } else if (type_str == SessionDescriptionInterface::kRollback) {
    return SdpType::kRollback;
  } else {
    return std::nullopt;
  }
}

std::unique_ptr<IceCandidate> CreateIceCandidate(const std::string& sdp_mid,
                                                 int sdp_mline_index,
                                                 const Candidate& candidate) {
  return std::make_unique<IceCandidate>(sdp_mid, sdp_mline_index, candidate);
}

IceCandidate* CreateIceCandidate(const std::string& sdp_mid,
                                 int sdp_mline_index,
                                 const std::string& sdp,
                                 SdpParseError* error) {
  return IceCandidate::Create(sdp_mid, sdp_mline_index, sdp, error).release();
}

std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view sdp) {
  return CreateSessionDescription(type, sdp, nullptr);
}

std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view sdp,
    SdpParseError* error_out) {
  if (type == SdpType::kRollback) {
    return CreateRollbackSessionDescription();
  }
  return SdpDeserialize(type, sdp, error_out);
}

std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view session_id,
    absl::string_view session_version,
    std::unique_ptr<SessionDescription> description) {
  return SessionDescriptionInterface::Create(type, std::move(description),
                                             session_id, session_version);
}

std::unique_ptr<SessionDescriptionInterface> CreateRollbackSessionDescription(
    absl::string_view session_id,
    absl::string_view session_version) {
  return SessionDescriptionInterface::Create(
      SdpType::kRollback, /*description=*/nullptr, session_id, session_version);
}

// static
std::unique_ptr<SessionDescriptionInterface>
SessionDescriptionInterface::Create(
    SdpType type,
    std::unique_ptr<SessionDescription> description,
    absl::string_view id,
    absl::string_view version,
    std::vector<IceCandidateCollection> candidates) {
  if (!description && type != SdpType::kRollback)
    return nullptr;
  return absl::WrapUnique(new SessionDescriptionInterface(
      type, std::move(description), id, version, std::move(candidates)));
}

SessionDescriptionInterface::~SessionDescriptionInterface() = default;

void SessionDescriptionInterface::RelinquishThreadOwnership() {
  // Ideally we should require that the method can only be called from the
  // thread that the sequence checker is currently attached to. However that's
  // not compatible with some cases outside of webrtc where initializations
  // happens on one thread and then the object is moved to a second thread (e.g.
  // signaling) where a call is made into webrtc. At that point we'd hit a
  // dcheck like this in webrtc: RTC_DCHECK_RUN_ON(&sequence_checker_);
  sequence_checker_.Detach();
  // Tie the checker to the current thread, which permits iterating
  // `candidate_collection_`
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  for (IceCandidateCollection& collection : candidate_collection_) {
    collection.RelinquishThreadOwnership();
  }
  sequence_checker_.Detach();  // Unties the checker from the current thread.
}

SessionDescriptionInterface::SessionDescriptionInterface(
    SdpType type,
    std::unique_ptr<SessionDescription> desc,
    absl::string_view id,
    absl::string_view version,
    std::vector<IceCandidateCollection> candidates)
    : sdp_type_(type),
      id_(id),
      version_(version),
      description_(std::move(desc)),
      candidate_collection_(std::move(candidates)) {
  RTC_DCHECK(description() || type == SdpType::kRollback);
  RTC_DCHECK(candidate_collection_.empty() ||
             candidate_collection_.size() == number_of_mediasections());
  candidate_collection_.resize(number_of_mediasections());
}

size_t SessionDescriptionInterface::number_of_mediasections() const {
  return description_ ? description_->contents().size() : 0u;
}

std::unique_ptr<SessionDescriptionInterface>
SessionDescriptionInterface::Clone() const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  return SessionDescriptionInterface::Create(
      sdp_type_, description() ? description()->Clone() : nullptr, id(),
      version(), CloneCandidateCollection(candidate_collection_));
}

bool SessionDescriptionInterface::AddCandidate(const IceCandidate* candidate) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  if (!candidate)
    return false;
  size_t index = 0;
  if (!GetMediasectionIndex(candidate, &index)) {
    return false;
  }
  ContentInfo& content = description()->contents()[index];
  const TransportInfo* transport_info =
      description()->GetTransportInfoByName(content.mid());
  if (!transport_info) {
    return false;
  }

  Candidate updated_candidate = candidate->candidate();
  if (updated_candidate.username().empty()) {
    updated_candidate.set_username(transport_info->description.ice_ufrag);
  }
  if (updated_candidate.password().empty()) {
    updated_candidate.set_password(transport_info->description.ice_pwd);
  }

  // Use `content.mid()` as the mid for the updated candidate. The
  // `candidate->sdp_mid()` property *should* be the same. However, in some
  // cases specifying an empty mid but a valid index is a way to add a candidate
  // without knowing (or caring about) the mid. This is done in several tests.
  RTC_DCHECK(candidate->sdp_mid().empty() ||
             candidate->sdp_mid() == content.mid())
      << "sdp_mid='" << candidate->sdp_mid() << "' content.mid()='"
      << content.mid() << "'";
  auto updated_candidate_wrapper = std::make_unique<IceCandidate>(
      content.mid(), static_cast<int>(index), updated_candidate);
  IceCandidateCollection& candidates = candidate_collection_[index];
  if (!candidates.HasCandidate(updated_candidate_wrapper.get())) {
    candidates.add(std::move(updated_candidate_wrapper));
    UpdateConnectionAddress(candidates, content.media_description());
  }

  return true;
}

bool SessionDescriptionInterface::RemoveCandidate(
    const IceCandidate* candidate) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  size_t index = 0u;
  if (!GetMediasectionIndex(candidate, &index)) {
    return false;
  }
  IceCandidateCollection& candidates = candidate_collection_[index];
  if (!candidates.remove(candidate)) {
    return false;
  }
  UpdateConnectionAddress(candidates,
                          description()->contents()[index].media_description());
  return true;
}

const IceCandidateCollection* SessionDescriptionInterface::candidates(
    size_t mediasection_index) const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  if (mediasection_index >= candidate_collection_.size())
    return nullptr;
  return &candidate_collection_[mediasection_index];
}

std::string SessionDescriptionInterface::ToString() const {
  return SdpSerialize(*this);
}

bool SessionDescriptionInterface::IsValidMLineIndex(int index) const {
  RTC_DCHECK(description());
  return index >= 0 &&
         index < static_cast<int>(description()->contents().size());
}

bool SessionDescriptionInterface::GetMediasectionIndex(
    const IceCandidate* candidate,
    size_t* index) const {
  if (!candidate || !index || !description()) {
    return false;
  }

  auto mid = candidate->sdp_mid();
  if (!mid.empty()) {
    *index = GetMediasectionIndex(mid);
  } else {
    // An sdp_mline_index of -1 will be treated as invalid.
    *index = static_cast<size_t>(candidate->sdp_mline_index());
  }
  return IsValidMLineIndex(*index);
}

int SessionDescriptionInterface::GetMediasectionIndex(
    absl::string_view mid) const {
  const auto& contents = description()->contents();
  auto it =
      std::find_if(contents.begin(), contents.end(),
                   [&](const auto& content) { return mid == content.mid(); });
  return it == contents.end() ? -1 : std::distance(contents.begin(), it);
}

}  // namespace webrtc
