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