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

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <span>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/string_view.h"
#include "api/environment/environment.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "api/transport/stun.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/byte_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/string_utils.h"

namespace webrtc {

// RFC 5389 says SHOULD be 500ms.
// For years, this was 100ms, but for networks that
// experience moments of high RTT (such as 2G networks), this doesn't
// work well.
const int STUN_INITIAL_RTO = 250;  // milliseconds

// The timeout doubles each retransmission, up to this many times
// RFC 5389 says SHOULD retransmit 7 times.
// This has been 8 for years (not sure why).
const int STUN_MAX_RETRANSMISSIONS = 8;  // Total sends: 9

// We also cap the doubling, even though the standard doesn't say to.
// This has been 1.6 seconds for years, but for networks that
// experience moments of high RTT (such as 2G networks), this doesn't
// work well.
const int STUN_MAX_RTO = 8000;  // milliseconds, or 5 doublings

StunRequestManager::StunRequestManager(
    TaskQueueBase* thread,
    std::function<void(std::span<const uint8_t>, StunRequest*)> send_packet)
    : thread_(thread), send_packet_(std::move(send_packet)) {}

StunRequestManager::~StunRequestManager() = default;

void StunRequestManager::Send(std::unique_ptr<StunRequest> request,
                              TimeDelta delay) {
  RTC_DCHECK_RUN_ON(thread_);
  RTC_DCHECK_EQ(this, request->manager());
  RTC_DCHECK(!request->AuthenticationRequired() ||
             request->msg()->integrity() !=
                 StunMessage::IntegrityStatus::kNotSet)
      << "Sending request w/o integrity!";
  auto [iter, was_inserted] =
      requests_.emplace(request->id(), std::move(request));
  RTC_DCHECK(was_inserted);
  iter->second->Send(delay);
}

void StunRequestManager::FlushForTest(int msg_type) {
  RTC_DCHECK_RUN_ON(thread_);
  for (const auto& [unused, request] : requests_) {
    if (msg_type == kAllRequestsForTest || msg_type == request->type()) {
      // Calling `Send` implies starting the send operation which may be posted
      // on a timer and be repeated on a timer until timeout. To make sure that
      // a call to `Send` doesn't conflict with a previously started `Send`
      // operation, we reset the `task_safety_` flag here, which has the effect
      // of canceling any outstanding tasks and prepare a new flag for
      // operations related to this call to `Send`.
      request->ResetTasksForTest();
      request->Send(TimeDelta::Zero());
    }
  }
}

bool StunRequestManager::HasRequestForTest(int msg_type) {
  RTC_DCHECK_RUN_ON(thread_);
  RTC_DCHECK_NE(msg_type, kAllRequestsForTest);
  for (const auto& [unused, request] : requests_) {
    if (msg_type == request->type()) {
      return true;
    }
  }
  return false;
}

void StunRequestManager::Clear() {
  RTC_DCHECK_RUN_ON(thread_);
  requests_.clear();
}

bool StunRequestManager::CheckResponse(StunMessage* msg) {
  RTC_DCHECK_RUN_ON(thread_);
  RequestMap::iterator iter = requests_.find(msg->transaction_id());
  if (iter == requests_.end())
    return false;

  StunRequest* request = iter->second.get();

  // Now that we know the request, we can see if the response is
  // integrity-protected or not. Some requests explicitly disables
  // integrity checks using SetAuthenticationRequired.
  // TODO(chromium:1177125): Remove below!
  // And we suspect that for some tests, the message integrity is not set in the
  // request. Complain, and then don't check.
  bool skip_integrity_checking =
      (request->msg()->integrity() == StunMessage::IntegrityStatus::kNotSet);
  if (!request->AuthenticationRequired()) {
    if (request->type() != STUN_BINDING_REQUEST) {
      if (msg->type() == GetStunSuccessResponseType(request->type())) {
        RTC_LOG(LS_WARNING)
            << "Discarding unauthenticated success response (0x"
            << ToHex(msg->type()) << ") to TURN request of type 0x"
            << ToHex(request->type())
            << ", id=" << hex_encode(msg->transaction_id());
        return false;
      }
      if (msg->type() == GetStunErrorResponseType(request->type())) {
        int error_code = msg->GetErrorCodeValue();
        if (error_code != STUN_ERROR_UNAUTHORIZED &&
            error_code != STUN_ERROR_TRY_ALTERNATE) {
          RTC_LOG(LS_WARNING)
              << "Discarding unauthenticated error response with code "
              << error_code << " to TURN request of type 0x"
              << ToHex(request->type())
              << ", id=" << hex_encode(msg->transaction_id());
          return false;
        }
      }
    }
  } else if (skip_integrity_checking) {
    // TODO(chromium:1177125): Remove below!
    // This indicates lazy test writing (not adding integrity attribute).
    // Complain, but only in debug mode (while developing).
    RTC_LOG(LS_ERROR)
        << "CheckResponse called on a passwordless request. Fix test!";
    RTC_DCHECK(false)
        << "CheckResponse called on a passwordless request. Fix test!";
  } else {
    if (msg->integrity() == StunMessage::IntegrityStatus::kNotSet) {
      // Checking status for the first time. Normal.
      msg->ValidateMessageIntegrity(request->msg()->password());
    } else if (msg->integrity() == StunMessage::IntegrityStatus::kIntegrityOk &&
               msg->password() == request->msg()->password()) {
      // Status is already checked, with the same password. This is the case
      // we would want to see happen.
    } else if (msg->integrity() ==
               StunMessage::IntegrityStatus::kIntegrityBad) {
      // This indicates that the original check had the wrong password.
      // Bad design, needs revisiting.
      // TODO(crbug.com/1177125): Fix this.
      msg->RevalidateMessageIntegrity(request->msg()->password());
    } else {
      RTC_CHECK_NOTREACHED();
    }
  }

  if (!msg->GetNonComprehendedAttributes().empty()) {
    // If a response contains unknown comprehension-required attributes, it's
    // simply discarded and the transaction is considered failed. See RFC5389
    // sections 7.3.3 and 7.3.4.
    RTC_LOG(LS_ERROR) << ": Discarding response due to unknown "
                         "comprehension-required attribute.";
    requests_.erase(iter);
    return false;
  } else if (msg->type() == GetStunSuccessResponseType(request->type())) {
    if (!msg->IntegrityOk() && !skip_integrity_checking) {
      return false;
    }
    // Erase element from hash before calling callback. This ensures
    // that the callback can modify the StunRequestManager any way it
    // sees fit.
    std::unique_ptr<StunRequest> owned_request = std::move(iter->second);
    requests_.erase(iter);
    owned_request->OnResponse(msg);
    return true;
  } else if (msg->type() == GetStunErrorResponseType(request->type())) {
    // Erase element from hash before calling callback. This ensures
    // that the callback can modify the StunRequestManager any way it
    // sees fit.
    std::unique_ptr<StunRequest> owned_request = std::move(iter->second);
    requests_.erase(iter);
    owned_request->OnErrorResponse(msg);
    return true;
  } else {
    RTC_LOG(LS_ERROR) << "Received response with wrong type: " << msg->type()
                      << " (expecting "
                      << GetStunSuccessResponseType(request->type()) << ")";
    return false;
  }
}

bool StunRequestManager::empty() const {
  RTC_DCHECK_RUN_ON(thread_);
  return requests_.empty();
}

bool StunRequestManager::CheckResponse(std::span<const uint8_t> payload) {
  RTC_DCHECK_RUN_ON(thread_);
  // Check the appropriate bytes of the stream to see if they match the
  // transaction ID of a response we are expecting.

  if (payload.size() < 20)
    return false;

  absl::string_view id(
      reinterpret_cast<const char*>(payload.data()) + kStunTransactionIdOffset,
      kStunTransactionIdLength);
  RequestMap::iterator iter = requests_.find(id);
  if (iter == requests_.end())
    return false;

  // Parse the STUN message and continue processing as usual.

  ByteBufferReader buf(payload);
  std::unique_ptr<StunMessage> response(iter->second->msg_->CreateNew());
  if (!response->Read(&buf)) {
    RTC_LOG(LS_WARNING) << "Failed to read STUN response " << hex_encode(id);
    return false;
  }

  return CheckResponse(response.get());
}

void StunRequestManager::OnRequestTimedOut(StunRequest* request) {
  RTC_DCHECK_RUN_ON(thread_);
  requests_.erase(request->id());
}

void StunRequestManager::SendPacket(std::span<const uint8_t> data,
                                    StunRequest* request) {
  RTC_DCHECK_EQ(this, request->manager());
  send_packet_(data, request);
}

StunRequest::StunRequest(const Environment& env, StunRequestManager& manager)
    : env_(env),
      manager_(manager),
      msg_(std::make_unique<StunMessage>(STUN_INVALID_MESSAGE_TYPE)),
      tstamp_(Timestamp::Zero()),
      count_(0),
      timeout_(false) {
  RTC_DCHECK_RUN_ON(network_thread());
}

StunRequest::StunRequest(const Environment& env,
                         StunRequestManager& manager,
                         std::unique_ptr<StunMessage> message)
    : env_(env),
      manager_(manager),
      msg_(std::move(message)),
      tstamp_(Timestamp::Zero()),
      count_(0),
      timeout_(false) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(!msg_->transaction_id().empty());
}

StunRequest::~StunRequest() {}

int StunRequest::type() {
  RTC_DCHECK(msg_ != nullptr);
  return msg_->type();
}

const StunMessage* StunRequest::msg() const {
  return msg_.get();
}

TimeDelta StunRequest::Elapsed() const {
  RTC_DCHECK_RUN_ON(network_thread());
  return env_.clock().CurrentTime() - tstamp_;
}

void StunRequest::SendInternal() {
  RTC_DCHECK_RUN_ON(network_thread());
  if (timeout_) {
    OnTimeout();
    manager_.OnRequestTimedOut(this);
    return;
  }

  tstamp_ = env_.clock().CurrentTime();

  ByteBufferWriter buf;
  msg_->Write(&buf);
  manager_.SendPacket(buf.DataView(), this);

  OnSent();
  SendDelayed(TimeDelta::Millis(resend_delay()));
}

void StunRequest::SendDelayed(TimeDelta delay) {
  network_thread()->PostDelayedTask(
      SafeTask(task_safety_.flag(), [this]() { SendInternal(); }), delay);
}

void StunRequest::Send(TimeDelta delay) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK_GE(delay.ms(), 0);

  RTC_DCHECK(!task_safety_.flag()->alive()) << "Send already called?";
  task_safety_.flag()->SetAlive();

  delay.IsZero() ? SendInternal() : SendDelayed(delay);
}

void StunRequest::ResetTasksForTest() {
  RTC_DCHECK_RUN_ON(network_thread());
  task_safety_.reset(PendingTaskSafetyFlag::CreateDetachedInactive());
  count_ = 0;
  RTC_DCHECK(!timeout_);
}

void StunRequest::OnSent() {
  RTC_DCHECK_RUN_ON(network_thread());
  count_ += 1;
  int retransmissions = (count_ - 1);
  if (retransmissions >= STUN_MAX_RETRANSMISSIONS) {
    timeout_ = true;
  }
  RTC_DLOG(LS_VERBOSE) << "Sent STUN request " << count_
                       << "; resend delay = " << resend_delay();
}

int StunRequest::resend_delay() {
  RTC_DCHECK_RUN_ON(network_thread());
  if (count_ == 0) {
    return 0;
  }
  int retransmissions = (count_ - 1);
  int rto = STUN_INITIAL_RTO << retransmissions;
  return std::min(rto, STUN_MAX_RTO);
}

void StunRequest::set_timed_out() {
  RTC_DCHECK_RUN_ON(network_thread());
  timeout_ = true;
}

}  // namespace webrtc
