/*
 *  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.
 */

#ifndef P2P_BASE_FAKE_DTLS_TRANSPORT_H_
#define P2P_BASE_FAKE_DTLS_TRANSPORT_H_

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/string_view.h"
#include "api/crypto/crypto_options.h"
#include "api/dtls_transport_interface.h"
#include "p2p/base/dtls_transport_internal.h"
#include "p2p/base/fake_ice_transport.h"
#include "rtc_base/fake_ssl_identity.h"
#include "rtc_base/network/received_packet.h"
#include "rtc_base/rtc_certificate.h"

namespace cricket {

// Fake DTLS transport which is implemented by wrapping a fake ICE transport.
// Doesn't interact directly with fake ICE transport for anything other than
// sending packets.
class FakeDtlsTransport : public DtlsTransportInternal {
 public:
  explicit FakeDtlsTransport(FakeIceTransport* ice_transport)
      : ice_transport_(ice_transport),
        transport_name_(ice_transport->transport_name()),
        component_(ice_transport->component()),
        dtls_fingerprint_("", nullptr) {
    RTC_DCHECK(ice_transport_);
    ice_transport_->RegisterReceivedPacketCallback(
        this, [&](rtc::PacketTransportInternal* transport,
                  const rtc::ReceivedPacket& packet) {
          OnIceTransportReadPacket(transport, packet);
        });
    ice_transport_->SignalNetworkRouteChanged.connect(
        this, &FakeDtlsTransport::OnNetworkRouteChanged);
  }

  explicit FakeDtlsTransport(std::unique_ptr<FakeIceTransport> ice)
      : owned_ice_transport_(std::move(ice)),
        transport_name_(owned_ice_transport_->transport_name()),
        component_(owned_ice_transport_->component()),
        dtls_fingerprint_("", rtc::ArrayView<const uint8_t>()) {
    ice_transport_ = owned_ice_transport_.get();
    ice_transport_->RegisterReceivedPacketCallback(
        this, [&](rtc::PacketTransportInternal* transport,
                  const rtc::ReceivedPacket& packet) {
          OnIceTransportReadPacket(transport, packet);
        });
    ice_transport_->SignalNetworkRouteChanged.connect(
        this, &FakeDtlsTransport::OnNetworkRouteChanged);
  }

  // If this constructor is called, a new fake ICE transport will be created,
  // and this FakeDtlsTransport will take the ownership.
  FakeDtlsTransport(const std::string& name, int component)
      : FakeDtlsTransport(std::make_unique<FakeIceTransport>(name, component)) {
  }
  FakeDtlsTransport(const std::string& name,
                    int component,
                    rtc::Thread* network_thread)
      : FakeDtlsTransport(std::make_unique<FakeIceTransport>(name,
                                                             component,
                                                             network_thread)) {}

  ~FakeDtlsTransport() override {
    if (dest_ && dest_->dest_ == this) {
      dest_->dest_ = nullptr;
    }
    ice_transport_->DeregisterReceivedPacketCallback(this);
  }

  // Get inner fake ICE transport.
  FakeIceTransport* fake_ice_transport() { return ice_transport_; }

  // If async, will send packets by "Post"-ing to message queue instead of
  // synchronously "Send"-ing.
  void SetAsync(bool async) { ice_transport_->SetAsync(async); }
  void SetAsyncDelay(int delay_ms) { ice_transport_->SetAsyncDelay(delay_ms); }

  // SetWritable, SetReceiving and SetDestination are the main methods that can
  // be used for testing, to simulate connectivity or lack thereof.
  void SetWritable(bool writable) {
    ice_transport_->SetWritable(writable);
    set_writable(writable);
  }
  void SetReceiving(bool receiving) {
    ice_transport_->SetReceiving(receiving);
    set_receiving(receiving);
  }
  void SetDtlsState(webrtc::DtlsTransportState state) {
    dtls_state_ = state;
    SendDtlsState(this, dtls_state_);
  }

  // Simulates the two DTLS transports connecting to each other.
  // If `asymmetric` is true this method only affects this FakeDtlsTransport.
  // If false, it affects `dest` as well.
  void SetDestination(FakeDtlsTransport* dest, bool asymmetric = false) {
    if (dest == dest_) {
      return;
    }
    RTC_DCHECK(!dest || !dest_)
        << "Changing fake destination from one to another is not supported.";
    if (dest && !dest_) {
      // This simulates the DTLS handshake.
      dest_ = dest;
      if (local_cert_ && dest_->local_cert_) {
        do_dtls_ = true;
        RTC_LOG(LS_INFO) << "FakeDtlsTransport is doing DTLS";
      } else {
        do_dtls_ = false;
        RTC_LOG(LS_INFO) << "FakeDtlsTransport is not doing DTLS";
      }
      SetWritable(true);
      if (!asymmetric) {
        dest->SetDestination(this, true);
      }
      // If the `dtls_role_` is unset, set it to SSL_CLIENT by default.
      if (!dtls_role_) {
        dtls_role_ = std::move(rtc::SSL_CLIENT);
      }
      SetDtlsState(webrtc::DtlsTransportState::kConnected);
      ice_transport_->SetDestination(
          static_cast<FakeIceTransport*>(dest->ice_transport()), asymmetric);
    } else {
      // Simulates loss of connectivity, by asymmetrically forgetting dest_.
      dest_ = nullptr;
      SetWritable(false);
      ice_transport_->SetDestination(nullptr, asymmetric);
    }
  }

  // Fake DtlsTransportInternal implementation.
  webrtc::DtlsTransportState dtls_state() const override { return dtls_state_; }
  const std::string& transport_name() const override { return transport_name_; }
  int component() const override { return component_; }
  const rtc::SSLFingerprint& dtls_fingerprint() const {
    return dtls_fingerprint_;
  }
  webrtc::RTCError SetRemoteParameters(absl::string_view alg,
                                       const uint8_t* digest,
                                       size_t digest_len,
                                       absl::optional<rtc::SSLRole> role) {
    if (role) {
      SetDtlsRole(*role);
    }
    SetRemoteFingerprint(alg, digest, digest_len);
    return webrtc::RTCError::OK();
  }
  bool SetRemoteFingerprint(absl::string_view alg,
                            const uint8_t* digest,
                            size_t digest_len) {
    dtls_fingerprint_ =
        rtc::SSLFingerprint(alg, rtc::MakeArrayView(digest, digest_len));
    return true;
  }
  bool SetDtlsRole(rtc::SSLRole role) override {
    dtls_role_ = std::move(role);
    return true;
  }
  bool GetDtlsRole(rtc::SSLRole* role) const override {
    if (!dtls_role_) {
      return false;
    }
    *role = *dtls_role_;
    return true;
  }
  bool SetLocalCertificate(
      const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override {
    do_dtls_ = true;
    local_cert_ = certificate;
    return true;
  }
  void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) {
    remote_cert_ = cert;
  }
  bool IsDtlsActive() const override { return do_dtls_; }
  bool GetSslVersionBytes(int* version) const override {
    if (!do_dtls_) {
      return false;
    }
    *version = 0x0102;
    return true;
  }
  bool GetSrtpCryptoSuite(int* crypto_suite) override {
    if (!do_dtls_) {
      return false;
    }
    *crypto_suite = crypto_suite_;
    return true;
  }
  void SetSrtpCryptoSuite(int crypto_suite) { crypto_suite_ = crypto_suite; }

  bool GetSslCipherSuite(int* cipher_suite) override {
    if (ssl_cipher_suite_) {
      *cipher_suite = *ssl_cipher_suite_;
      return true;
    }
    return false;
  }
  void SetSslCipherSuite(absl::optional<int> cipher_suite) {
    ssl_cipher_suite_ = cipher_suite;
  }
  uint16_t GetSslPeerSignatureAlgorithm() const override { return 0; }
  rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
    return local_cert_;
  }
  std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override {
    if (!remote_cert_) {
      return nullptr;
    }
    return std::make_unique<rtc::SSLCertChain>(remote_cert_->Clone());
  }
  bool ExportKeyingMaterial(absl::string_view label,
                            const uint8_t* context,
                            size_t context_len,
                            bool use_context,
                            uint8_t* result,
                            size_t result_len) override {
    if (!do_dtls_) {
      return false;
    }
    memset(result, 0xff, result_len);
    return true;
  }
  void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) {
    ssl_max_version_ = version;
  }
  rtc::SSLProtocolVersion ssl_max_protocol_version() const {
    return ssl_max_version_;
  }

  IceTransportInternal* ice_transport() override { return ice_transport_; }

  // PacketTransportInternal implementation, which passes through to fake ICE
  // transport for sending actual packets.
  bool writable() const override { return writable_; }
  bool receiving() const override { return receiving_; }
  int SendPacket(const char* data,
                 size_t len,
                 const rtc::PacketOptions& options,
                 int flags) override {
    // We expect only SRTP packets to be sent through this interface.
    if (flags != PF_SRTP_BYPASS && flags != 0) {
      return -1;
    }
    return ice_transport_->SendPacket(data, len, options, flags);
  }
  int SetOption(rtc::Socket::Option opt, int value) override {
    return ice_transport_->SetOption(opt, value);
  }
  bool GetOption(rtc::Socket::Option opt, int* value) override {
    return ice_transport_->GetOption(opt, value);
  }
  int GetError() override { return ice_transport_->GetError(); }

  absl::optional<rtc::NetworkRoute> network_route() const override {
    return ice_transport_->network_route();
  }

 private:
  void OnIceTransportReadPacket(PacketTransportInternal* ice_,
                                const rtc::ReceivedPacket& packet) {
    NotifyPacketReceived(packet);
  }

  void set_receiving(bool receiving) {
    if (receiving_ == receiving) {
      return;
    }
    receiving_ = receiving;
    SignalReceivingState(this);
  }

  void set_writable(bool writable) {
    if (writable_ == writable) {
      return;
    }
    writable_ = writable;
    if (writable_) {
      SignalReadyToSend(this);
    }
    SignalWritableState(this);
  }

  void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route) {
    SignalNetworkRouteChanged(network_route);
  }

  FakeIceTransport* ice_transport_;
  std::unique_ptr<FakeIceTransport> owned_ice_transport_;
  std::string transport_name_;
  int component_;
  FakeDtlsTransport* dest_ = nullptr;
  rtc::scoped_refptr<rtc::RTCCertificate> local_cert_;
  rtc::FakeSSLCertificate* remote_cert_ = nullptr;
  bool do_dtls_ = false;
  rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
  rtc::SSLFingerprint dtls_fingerprint_;
  absl::optional<rtc::SSLRole> dtls_role_;
  int crypto_suite_ = rtc::kSrtpAes128CmSha1_80;
  absl::optional<int> ssl_cipher_suite_;

  webrtc::DtlsTransportState dtls_state_ = webrtc::DtlsTransportState::kNew;

  bool receiving_ = false;
  bool writable_ = false;
};

}  // namespace cricket

#endif  // P2P_BASE_FAKE_DTLS_TRANSPORT_H_
