// 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)
                                       : QuicMakeUnique<QuicVersionManager>(
                                             AllSupportedVersions())),
      create_session_alarm_(QuicWrapUnique(
          alarm_factory_->CreateAlarm(new CreateSessionDelegate(this)))),
      connection_helper_(
          QuicMakeUnique<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(QuicErrorCode error_code,
                                              const std::string& error_details,
                                              ConnectionCloseSource source) {
  // First, see if we can restart the session with a mutually-supported version.
  if (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(error_code, error_details, source);
}

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

void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) {
  delegate_->OnMessageSent(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)
                                       : QuicMakeUnique<QuicVersionManager>(
                                             AllSupportedVersions())),
      pre_connection_helper_(
          QuicMakeUnique<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_ = QuicMakeUnique<QuartcDispatcher>(
      QuicMakeUnique<QuicConfig>(CreateQuicConfig(config_)),
      std::move(crypto_config_.config), crypto_config_.serialized_crypto_config,
      version_manager_.get(), std::move(pre_connection_helper_),
      QuicMakeUnique<QuartcCryptoServerStreamHelper>(),
      QuicMakeUnique<QuartcAlarmFactoryWrapper>(alarm_factory_),
      QuicMakeUnique<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
