// Copyright (c) 2019 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.

// Sets up a dispatcher and sends requests via the QboneClient.

#include "quic/qbone/qbone_client.h"

#include "absl/strings/string_view.h"
#include "quic/core/quic_alarm_factory.h"
#include "quic/core/quic_default_packet_writer.h"
#include "quic/core/quic_dispatcher.h"
#include "quic/core/quic_epoll_alarm_factory.h"
#include "quic/core/quic_epoll_connection_helper.h"
#include "quic/core/quic_packet_reader.h"
#include "quic/platform/api/quic_mutex.h"
#include "quic/platform/api/quic_port_utils.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "quic/platform/api/quic_test_loopback.h"
#include "quic/qbone/qbone_constants.h"
#include "quic/qbone/qbone_packet_processor_test_tools.h"
#include "quic/qbone/qbone_server_session.h"
#include "quic/test_tools/crypto_test_utils.h"
#include "quic/test_tools/quic_connection_peer.h"
#include "quic/test_tools/quic_dispatcher_peer.h"
#include "quic/test_tools/quic_server_peer.h"
#include "quic/test_tools/server_thread.h"
#include "quic/tools/quic_memory_cache_backend.h"
#include "quic/tools/quic_server.h"

namespace quic {
namespace test {
namespace {

ParsedQuicVersionVector GetTestParams() {
  ParsedQuicVersionVector test_versions;

  // TODO(b/113130636): Make QBONE work with TLS.
  for (const auto& version : CurrentSupportedVersionsWithQuicCrypto()) {
    // QBONE requires MESSAGE frames
    if (!version.SupportsMessageFrames()) {
      continue;
    }
    test_versions.push_back(version);
  }

  return test_versions;
}

std::string TestPacketIn(const std::string& body) {
  return PrependIPv6HeaderForTest(body, 5);
}

std::string TestPacketOut(const std::string& body) {
  return PrependIPv6HeaderForTest(body, 4);
}

class DataSavingQbonePacketWriter : public QbonePacketWriter {
 public:
  void WritePacketToNetwork(const char* packet, size_t size) override {
    QuicWriterMutexLock lock(&mu_);
    data_.push_back(std::string(packet, size));
  }

  std::vector<std::string> data() {
    QuicWriterMutexLock lock(&mu_);
    return data_;
  }

 private:
  QuicMutex mu_;
  std::vector<std::string> data_;
};

// A subclass of a QBONE session that will own the connection passed in.
class ConnectionOwningQboneServerSession : public QboneServerSession {
 public:
  ConnectionOwningQboneServerSession(
      const ParsedQuicVersionVector& supported_versions,
      QuicConnection* connection,
      Visitor* owner,
      const QuicConfig& config,
      const QuicCryptoServerConfig* quic_crypto_server_config,
      QuicCompressedCertsCache* compressed_certs_cache,
      QbonePacketWriter* writer)
      : QboneServerSession(supported_versions,
                           connection,
                           owner,
                           config,
                           quic_crypto_server_config,
                           compressed_certs_cache,
                           writer,
                           TestLoopback6(),
                           TestLoopback6(),
                           64,
                           nullptr),
        connection_(connection) {}

 private:
  // Note that we don't expect the QboneServerSession or any of its parent
  // classes to do anything with the connection_ in their destructors.
  std::unique_ptr<QuicConnection> connection_;
};

class QuicQboneDispatcher : public QuicDispatcher {
 public:
  QuicQboneDispatcher(
      const QuicConfig* config,
      const QuicCryptoServerConfig* crypto_config,
      QuicVersionManager* version_manager,
      std::unique_ptr<QuicConnectionHelperInterface> helper,
      std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
      std::unique_ptr<QuicAlarmFactory> alarm_factory,
      QbonePacketWriter* writer)
      : QuicDispatcher(config,
                       crypto_config,
                       version_manager,
                       std::move(helper),
                       std::move(session_helper),
                       std::move(alarm_factory),
                       kQuicDefaultConnectionIdLength),
        writer_(writer) {}

  std::unique_ptr<QuicSession> CreateQuicSession(
      QuicConnectionId id, const QuicSocketAddress& self_address,
      const QuicSocketAddress& peer_address, absl::string_view alpn,
      const ParsedQuicVersion& version,
      const ParsedClientHello& /*parsed_chlo*/) override {
    QUICHE_CHECK_EQ(alpn, "qbone");
    QuicConnection* connection = new QuicConnection(
        id, self_address, peer_address, helper(), alarm_factory(), writer(),
        /* owns_writer= */ false, Perspective::IS_SERVER,
        ParsedQuicVersionVector{version});
    // The connection owning wrapper owns the connection created.
    auto session = std::make_unique<ConnectionOwningQboneServerSession>(
        GetSupportedVersions(), connection, this, config(), crypto_config(),
        compressed_certs_cache(), writer_);
    session->Initialize();
    return session;
  }

 private:
  QbonePacketWriter* writer_;
};

class QboneTestServer : public QuicServer {
 public:
  explicit QboneTestServer(std::unique_ptr<ProofSource> proof_source)
      : QuicServer(std::move(proof_source), &response_cache_) {}
  QuicDispatcher* CreateQuicDispatcher() override {
    QuicEpollAlarmFactory alarm_factory(epoll_server());
    return new QuicQboneDispatcher(
        &config(), &crypto_config(), version_manager(),
        std::unique_ptr<QuicEpollConnectionHelper>(
            new QuicEpollConnectionHelper(epoll_server(),
                                          QuicAllocator::BUFFER_POOL)),
        std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
            new QboneCryptoServerStreamHelper()),
        std::unique_ptr<QuicEpollAlarmFactory>(
            new QuicEpollAlarmFactory(epoll_server())),
        &writer_);
  }

  std::vector<std::string> data() { return writer_.data(); }

 private:
  quic::QuicMemoryCacheBackend response_cache_;
  DataSavingQbonePacketWriter writer_;
};

class QboneTestClient : public QboneClient {
 public:
  QboneTestClient(QuicSocketAddress server_address,
                  const QuicServerId& server_id,
                  const ParsedQuicVersionVector& supported_versions,
                  QuicEpollServer* epoll_server,
                  std::unique_ptr<ProofVerifier> proof_verifier)
      : QboneClient(server_address,
                    server_id,
                    supported_versions,
                    /*session_owner=*/nullptr,
                    QuicConfig(),
                    epoll_server,
                    std::move(proof_verifier),
                    &qbone_writer_,
                    nullptr) {}

  ~QboneTestClient() override {}

  void SendData(const std::string& data) {
    qbone_session()->ProcessPacketFromNetwork(data);
  }

  void WaitForWriteToFlush() {
    while (connected() && session()->HasDataToWrite()) {
      WaitForEvents();
    }
  }

  // Returns true when the data size is reached or false on timeouts.
  bool WaitForDataSize(int n, QuicTime::Delta timeout) {
    const QuicClock* clock =
        quic::test::QuicConnectionPeer::GetHelper(session()->connection())
            ->GetClock();
    const QuicTime deadline = clock->Now() + timeout;
    while (data().size() < n) {
      if (clock->Now() > deadline) {
        return false;
      }
      WaitForEvents();
    }
    return true;
  }

  std::vector<std::string> data() { return qbone_writer_.data(); }

 private:
  DataSavingQbonePacketWriter qbone_writer_;
};

class QboneClientTest : public QuicTestWithParam<ParsedQuicVersion> {};

INSTANTIATE_TEST_SUITE_P(Tests,
                         QboneClientTest,
                         ::testing::ValuesIn(GetTestParams()),
                         ::testing::PrintToStringParamName());

TEST_P(QboneClientTest, SendDataFromClient) {
  auto server = new QboneTestServer(crypto_test_utils::ProofSourceForTesting());
  QuicSocketAddress server_address(TestLoopback(),
                                   QuicPickServerPortForTestsOrDie());
  ServerThread server_thread(server, server_address);
  server_thread.Initialize();
  server_address =
      QuicSocketAddress(server_address.host(), server_thread.GetPort());
  server_thread.Start();

  QuicEpollServer epoll_server;
  QboneTestClient client(
      server_address,
      QuicServerId("test.example.com", server_address.port(), false),
      ParsedQuicVersionVector{GetParam()}, &epoll_server,
      crypto_test_utils::ProofVerifierForTesting());
  ASSERT_TRUE(client.Initialize());
  ASSERT_TRUE(client.Connect());
  ASSERT_TRUE(client.WaitForOneRttKeysAvailable());
  client.SendData(TestPacketIn("hello"));
  client.SendData(TestPacketIn("world"));
  client.WaitForWriteToFlush();

  // Wait until the server has received at least two packets, timeout after 5s.
  ASSERT_TRUE(
      server_thread.WaitUntil([&] { return server->data().size() >= 2; },
                              QuicTime::Delta::FromSeconds(5)));

  std::string long_data(
      QboneConstants::kMaxQbonePacketBytes - sizeof(ip6_hdr) - 1, 'A');

  // Pretend the server gets data.
  server_thread.Schedule([&server, &long_data]() {
    EXPECT_THAT(server->data()[0], testing::Eq(TestPacketOut("hello")));
    EXPECT_THAT(server->data()[1], testing::Eq(TestPacketOut("world")));
    auto server_session = static_cast<QboneServerSession*>(
        QuicDispatcherPeer::GetFirstSessionIfAny(
            QuicServerPeer::GetDispatcher(server)));
    server_session->ProcessPacketFromNetwork(
        TestPacketIn("Somethingsomething"));
    server_session->ProcessPacketFromNetwork(TestPacketIn(long_data));
    server_session->ProcessPacketFromNetwork(TestPacketIn(long_data));
  });
  ASSERT_TRUE(client.WaitForDataSize(3, QuicTime::Delta::FromSeconds(5)));
  EXPECT_THAT(client.data()[0],
              testing::Eq(TestPacketOut("Somethingsomething")));
  EXPECT_THAT(client.data()[1], testing::Eq(TestPacketOut(long_data)));
  EXPECT_THAT(client.data()[2], testing::Eq(TestPacketOut(long_data)));

  client.Disconnect();
  server_thread.Quit();
  server_thread.Join();
}

}  // namespace
}  // namespace test
}  // namespace quic
