// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h"

#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h"

namespace quic {

namespace {

// Wrapper around a QuicAlarmFactory which delegates to the wrapped factory.
// Usee to convert an unowned pointer into an owned pointer, so that the new
// "owner" does not delete the underlying factory.  Note that this is only valid
// when the unowned pointer is already guaranteed to outlive the new "owner".
class QuartcAlarmFactoryWrapper : public QuicAlarmFactory {
 public:
  explicit QuartcAlarmFactoryWrapper(QuicAlarmFactory* impl) : impl_(impl) {}

  QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
  QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
      QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
      QuicConnectionArena* arena) override;

 private:
  QuicAlarmFactory* impl_;
};

QuicAlarm* QuartcAlarmFactoryWrapper::CreateAlarm(
    QuicAlarm::Delegate* delegate) {
  return impl_->CreateAlarm(delegate);
}

QuicArenaScopedPtr<QuicAlarm> QuartcAlarmFactoryWrapper::CreateAlarm(
    QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
    QuicConnectionArena* arena) {
  return impl_->CreateAlarm(std::move(delegate), arena);
}

}  // namespace

QuartcClientEndpoint::QuartcClientEndpoint(
    QuicAlarmFactory* alarm_factory,
    const QuicClock* clock,
    QuicRandom* random,
    QuartcEndpoint::Delegate* delegate,
    const QuartcSessionConfig& config,
    QuicStringPiece serialized_server_config,
    std::unique_ptr<QuicVersionManager> version_manager)
    : alarm_factory_(alarm_factory),
      clock_(clock),
      delegate_(delegate),
      serialized_server_config_(serialized_server_config),
      version_manager_(version_manager ? std::move(version_manager)
                                       : std::make_unique<QuicVersionManager>(
                                             AllSupportedVersions())),
      create_session_alarm_(QuicWrapUnique(
          alarm_factory_->CreateAlarm(new CreateSessionDelegate(this)))),
      connection_helper_(
          std::make_unique<QuartcConnectionHelper>(clock_, random)),
      config_(config) {}

void QuartcClientEndpoint::Connect(QuartcPacketTransport* packet_transport) {
  packet_transport_ = packet_transport;
  // For the first attempt to connect, use any version that the client supports.
  current_versions_ = version_manager_->GetSupportedVersions();
  create_session_alarm_->Set(clock_->Now());
}

void QuartcClientEndpoint::OnCreateSessionAlarm() {
  session_ = CreateQuartcClientSession(
      config_, clock_, alarm_factory_, connection_helper_.get(),
      current_versions_, serialized_server_config_, packet_transport_);
  session_->SetDelegate(this);
  delegate_->OnSessionCreated(session_.get());
}

void QuartcClientEndpoint::OnCryptoHandshakeComplete() {
  delegate_->OnCryptoHandshakeComplete();
}

void QuartcClientEndpoint::OnConnectionWritable() {
  delegate_->OnConnectionWritable();
}

void QuartcClientEndpoint::OnIncomingStream(QuartcStream* stream) {
  delegate_->OnIncomingStream(stream);
}

void QuartcClientEndpoint::OnCongestionControlChange(
    QuicBandwidth bandwidth_estimate,
    QuicBandwidth pacing_rate,
    QuicTime::Delta latest_rtt) {
  delegate_->OnCongestionControlChange(bandwidth_estimate, pacing_rate,
                                       latest_rtt);
}

void QuartcClientEndpoint::OnConnectionClosed(
    const QuicConnectionCloseFrame& frame,
    ConnectionCloseSource source) {
  // First, see if we can restart the session with a mutually-supported version.
  if (frame.quic_error_code == QUIC_INVALID_VERSION && session_ &&
      session_->connection() &&
      !session_->connection()->server_supported_versions().empty()) {
    for (const auto& client_version :
         version_manager_->GetSupportedVersions()) {
      if (QuicContainsValue(session_->connection()->server_supported_versions(),
                            client_version)) {
        // Found a mutually-supported version.  Reconnect using that version.
        current_versions_.clear();
        current_versions_.push_back(client_version);
        create_session_alarm_->Set(clock_->Now());
        return;
      }
    }
  }

  // Permanent version negotiation errors are forwarded to the |delegate_|,
  // along with all other errors.
  delegate_->OnConnectionClosed(frame, source);
}

void QuartcClientEndpoint::OnMessageReceived(QuicStringPiece message) {
  delegate_->OnMessageReceived(message);
}

void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) {
  delegate_->OnMessageSent(datagram_id);
}

void QuartcClientEndpoint::OnMessageAcked(int64_t datagram_id,
                                          QuicTime receive_timestamp) {
  delegate_->OnMessageAcked(datagram_id, receive_timestamp);
}

void QuartcClientEndpoint::OnMessageLost(int64_t datagram_id) {
  delegate_->OnMessageLost(datagram_id);
}

QuartcServerEndpoint::QuartcServerEndpoint(
    QuicAlarmFactory* alarm_factory,
    const QuicClock* clock,
    QuicRandom* random,
    QuartcEndpoint::Delegate* delegate,
    const QuartcSessionConfig& config,
    std::unique_ptr<QuicVersionManager> version_manager)
    : alarm_factory_(alarm_factory),
      delegate_(delegate),
      config_(config),
      version_manager_(version_manager ? std::move(version_manager)
                                       : std::make_unique<QuicVersionManager>(
                                             AllSupportedVersions())),
      pre_connection_helper_(
          std::make_unique<QuartcConnectionHelper>(clock, random)),
      crypto_config_(
          CreateCryptoServerConfig(pre_connection_helper_->GetRandomGenerator(),
                                   clock,
                                   config.pre_shared_key)) {}

void QuartcServerEndpoint::Connect(QuartcPacketTransport* packet_transport) {
  DCHECK(pre_connection_helper_ != nullptr);
  dispatcher_ = std::make_unique<QuartcDispatcher>(
      std::make_unique<QuicConfig>(CreateQuicConfig(config_)),
      std::move(crypto_config_.config), version_manager_.get(),
      std::move(pre_connection_helper_),
      std::make_unique<QuartcCryptoServerStreamHelper>(),
      std::make_unique<QuartcAlarmFactoryWrapper>(alarm_factory_),
      std::make_unique<QuartcPacketWriter>(packet_transport,
                                           config_.max_packet_size),
      this);
  // The dispatcher requires at least one call to |ProcessBufferedChlos| to
  // set the number of connections it is allowed to create.
  dispatcher_->ProcessBufferedChlos(/*max_connections_to_create=*/1);
}

void QuartcServerEndpoint::OnSessionCreated(QuartcSession* session) {
  session->SetDelegate(delegate_);
  delegate_->OnSessionCreated(session);
}

}  // namespace quic
