Introduce MASQUE, part 2: client code

This CL introduces the client code for MASQUE as defined by <https://tools.ietf.org/html/draft-schinazi-masque>. Most of the work here is plumbing in order to override the right methods of the QUIC codebase. The meat of the MASQUE protocol work is in the parent cl/278956073.

gfe-relnote: n/a, adds unused code
PiperOrigin-RevId: 285443244
Change-Id: I76c66a4d89b8b70aada4f15f03ac5ec139ada22f
diff --git a/quic/masque/masque_encapsulated_epoll_client.cc b/quic/masque/masque_encapsulated_epoll_client.cc
new file mode 100644
index 0000000..7c9749a
--- /dev/null
+++ b/quic/masque/masque_encapsulated_epoll_client.cc
@@ -0,0 +1,125 @@
+// Copyright 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.
+
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/masque/masque_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h"
+#include "net/third_party/quiche/src/quic/masque/masque_epoll_client.h"
+#include "net/third_party/quiche/src/quic/masque/masque_utils.h"
+
+namespace quic {
+
+namespace {
+
+// Custom packet writer that allows getting all of a connection's outgoing
+// packets.
+class MasquePacketWriter : public QuicPacketWriter {
+ public:
+  explicit MasquePacketWriter(MasqueEncapsulatedEpollClient* client)
+      : client_(client) {}
+  WriteResult WritePacket(const char* buffer,
+                          size_t buf_len,
+                          const QuicIpAddress& /*self_address*/,
+                          const QuicSocketAddress& peer_address,
+                          PerPacketOptions* /*options*/) override {
+    DCHECK(peer_address.IsInitialized());
+    QUIC_DVLOG(1) << "MasquePacketWriter trying to write " << buf_len
+                  << " bytes to " << peer_address;
+    quiche::QuicheStringPiece packet(buffer, buf_len);
+    client_->masque_client()->masque_client_session()->SendPacket(
+        client_->session()->connection()->client_connection_id(),
+        client_->session()->connection()->connection_id(), packet,
+        peer_address);
+    return WriteResult(WRITE_STATUS_OK, buf_len);
+  }
+
+  bool IsWriteBlocked() const override { return false; }
+
+  void SetWritable() override {}
+
+  QuicByteCount GetMaxPacketSize(
+      const QuicSocketAddress& /*peer_address*/) const override {
+    return kMasqueMaxEncapsulatedPacketSize;
+  }
+
+  bool SupportsReleaseTime() const override { return false; }
+
+  bool IsBatchMode() const override { return false; }
+  char* GetNextWriteLocation(
+      const QuicIpAddress& /*self_address*/,
+      const QuicSocketAddress& /*peer_address*/) override {
+    return nullptr;
+  }
+
+  WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
+
+ private:
+  MasqueEncapsulatedEpollClient* client_;  // Unowned.
+};
+
+// Custom network helper that allows injecting a custom packet writer in order
+// to get all of a connection's outgoing packets.
+class MasqueClientEpollNetworkHelper : public QuicClientEpollNetworkHelper {
+ public:
+  MasqueClientEpollNetworkHelper(QuicEpollServer* epoll_server,
+                                 MasqueEncapsulatedEpollClient* client)
+      : QuicClientEpollNetworkHelper(epoll_server, client), client_(client) {}
+  QuicPacketWriter* CreateQuicPacketWriter() override {
+    return new MasquePacketWriter(client_);
+  }
+
+ private:
+  MasqueEncapsulatedEpollClient* client_;  // Unowned.
+};
+
+}  // namespace
+
+MasqueEncapsulatedEpollClient::MasqueEncapsulatedEpollClient(
+    QuicSocketAddress server_address,
+    const QuicServerId& server_id,
+    QuicEpollServer* epoll_server,
+    std::unique_ptr<ProofVerifier> proof_verifier,
+    MasqueEpollClient* masque_client)
+    : QuicClient(
+          server_address,
+          server_id,
+          MasqueSupportedVersions(),
+          MasqueEncapsulatedConfig(),
+          epoll_server,
+          std::make_unique<MasqueClientEpollNetworkHelper>(epoll_server, this),
+          std::move(proof_verifier)),
+      masque_client_(masque_client) {}
+
+MasqueEncapsulatedEpollClient::~MasqueEncapsulatedEpollClient() {
+  masque_client_->masque_client_session()->UnregisterConnectionId(
+      client_connection_id_);
+}
+
+std::unique_ptr<QuicSession>
+MasqueEncapsulatedEpollClient::CreateQuicClientSession(
+    const ParsedQuicVersionVector& supported_versions,
+    QuicConnection* connection) {
+  QUIC_DLOG(INFO) << "Creating MASQUE encapsulated session for "
+                  << connection->connection_id();
+  return std::make_unique<MasqueEncapsulatedClientSession>(
+      *config(), supported_versions, connection, server_id(), crypto_config(),
+      push_promise_index(), masque_client_->masque_client_session());
+}
+
+MasqueEncapsulatedClientSession*
+MasqueEncapsulatedEpollClient::masque_encapsulated_client_session() {
+  return static_cast<MasqueEncapsulatedClientSession*>(QuicClient::session());
+}
+
+QuicConnectionId MasqueEncapsulatedEpollClient::GetClientConnectionId() {
+  if (client_connection_id_.IsEmpty()) {
+    client_connection_id_ = QuicUtils::CreateRandomConnectionId();
+    masque_client_->masque_client_session()->RegisterConnectionId(
+        client_connection_id_, masque_encapsulated_client_session());
+  }
+  return client_connection_id_;
+}
+
+}  // namespace quic