Remove legacy MASQUE mode This CL deletes the implementation of the earliest MASQUE draft. Since we are moving forward with a new design, this will reduce complexity. This CL is not flag protected because MASQUE is not yet used in production. PiperOrigin-RevId: 442372570
diff --git a/quiche/quic/masque/masque_client_bin.cc b/quiche/quic/masque/masque_client_bin.cc index 8fd5e52..f973227 100644 --- a/quiche/quic/masque/masque_client_bin.cc +++ b/quiche/quic/masque/masque_client_bin.cc
@@ -29,9 +29,9 @@ bool, disable_certificate_verification, false, "If true, don't verify the server certificate."); -DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, masque_mode, "", - "Allows setting MASQUE mode, valid values are " - "open and legacy. Defaults to open."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, masque_mode, "", + "Allows setting MASQUE mode, currently only valid value is \"open\"."); namespace quic { @@ -83,9 +83,7 @@ } MasqueMode masque_mode = MasqueMode::kOpen; std::string mode_string = GetQuicFlag(FLAGS_masque_mode); - if (mode_string == "legacy") { - masque_mode = MasqueMode::kLegacy; - } else if (!mode_string.empty() && mode_string != "open") { + if (!mode_string.empty() && mode_string != "open") { std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl; return 1; }
diff --git a/quiche/quic/masque/masque_client_session.cc b/quiche/quic/masque/masque_client_session.cc index 9a69dad..b053659 100644 --- a/quiche/quic/masque/masque_client_session.cc +++ b/quiche/quic/masque/masque_client_session.cc
@@ -30,42 +30,7 @@ crypto_config, push_promise_index), masque_mode_(masque_mode), uri_template_(uri_template), - owner_(owner), - compression_engine_(this) {} - -void MasqueClientSession::OnMessageReceived(absl::string_view message) { - if (masque_mode_ == MasqueMode::kLegacy) { - QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length(); - QuicConnectionId client_connection_id, server_connection_id; - QuicSocketAddress target_server_address; - std::vector<char> packet; - bool version_present; - if (!compression_engine_.DecompressDatagram( - message, &client_connection_id, &server_connection_id, - &target_server_address, &packet, &version_present)) { - return; - } - - auto connection_id_registration = - client_connection_id_registrations_.find(client_connection_id); - if (connection_id_registration == - client_connection_id_registrations_.end()) { - QUIC_DLOG(ERROR) << "MasqueClientSession failed to dispatch " - << client_connection_id; - return; - } - EncapsulatedClientSession* encapsulated_client_session = - connection_id_registration->second; - encapsulated_client_session->ProcessPacket( - absl::string_view(packet.data(), packet.size()), target_server_address); - - QUIC_DVLOG(1) << "Sent " << packet.size() << " bytes to connection for " - << client_connection_id; - return; - } - QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen); - QuicSpdySession::OnMessageReceived(message); -} + owner_(owner) {} void MasqueClientSession::OnMessageAcked(QuicMessageId message_id, QuicTime /*receive_timestamp*/) { @@ -174,16 +139,8 @@ } void MasqueClientSession::SendPacket( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, absl::string_view packet, - const QuicSocketAddress& target_server_address, + absl::string_view packet, const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session) { - if (masque_mode_ == MasqueMode::kLegacy) { - compression_engine_.CompressAndSendPacket(packet, client_connection_id, - server_connection_id, - target_server_address); - return; - } const ConnectUdpClientState* connect_udp = GetOrCreateConnectUdpClientState( target_server_address, encapsulated_client_session); if (connect_udp == nullptr) { @@ -200,34 +157,8 @@ << MessageStatusToString(message_status); } -void MasqueClientSession::RegisterConnectionId( - QuicConnectionId client_connection_id, +void MasqueClientSession::CloseConnectUdpStream( EncapsulatedClientSession* encapsulated_client_session) { - QUIC_DLOG(INFO) << "Registering " << client_connection_id - << " to encapsulated client"; - QUICHE_DCHECK( - client_connection_id_registrations_.find(client_connection_id) == - client_connection_id_registrations_.end() || - client_connection_id_registrations_[client_connection_id] == - encapsulated_client_session); - client_connection_id_registrations_[client_connection_id] = - encapsulated_client_session; -} - -void MasqueClientSession::UnregisterConnectionId( - QuicConnectionId client_connection_id, - EncapsulatedClientSession* encapsulated_client_session) { - QUIC_DLOG(INFO) << "Unregistering " << client_connection_id; - if (masque_mode_ == MasqueMode::kLegacy) { - if (client_connection_id_registrations_.find(client_connection_id) != - client_connection_id_registrations_.end()) { - client_connection_id_registrations_.erase(client_connection_id); - owner_->UnregisterClientConnectionId(client_connection_id); - compression_engine_.UnregisterClientConnectionId(client_connection_id); - } - return; - } - for (auto it = connect_udp_client_states_.begin(); it != connect_udp_client_states_.end();) { if (it->encapsulated_client_session() == encapsulated_client_session) {
diff --git a/quiche/quic/masque/masque_client_session.h b/quiche/quic/masque/masque_client_session.h index 6e469b2..05162b5 100644 --- a/quiche/quic/masque/masque_client_session.h +++ b/quiche/quic/masque/masque_client_session.h
@@ -10,7 +10,6 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/http/quic_spdy_client_session.h" -#include "quiche/quic/masque/masque_compression_engine.h" #include "quiche/quic/masque/masque_utils.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_socket_address.h" @@ -30,10 +29,6 @@ public: virtual ~Owner() {} - // Notifies the owner that the client connection ID is no longer in use. - virtual void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) = 0; - // Notifies the owner that a settings frame has been received. virtual void OnSettingsReceived() = 0; }; @@ -70,7 +65,6 @@ MasqueClientSession& operator=(const MasqueClientSession&) = delete; // From QuicSession. - void OnMessageReceived(absl::string_view message) override; void OnMessageAcked(QuicMessageId message_id, QuicTime receive_timestamp) override; void OnMessageLost(QuicMessageId message_id) override; @@ -82,26 +76,12 @@ bool OnSettingsFrame(const SettingsFrame& frame) override; // Send encapsulated packet. - void SendPacket(QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - absl::string_view packet, + void SendPacket(absl::string_view packet, const QuicSocketAddress& target_server_address, EncapsulatedClientSession* encapsulated_client_session); - // Register encapsulated client. This allows clients that are encapsulated - // within this MASQUE session to indicate they own a given client connection - // ID so incoming packets with that connection ID are routed back to them. - // Callers must not register a second different |encapsulated_client_session| - // with the same |client_connection_id|. Every call must be matched with a - // call to UnregisterConnectionId. - void RegisterConnectionId( - QuicConnectionId client_connection_id, - EncapsulatedClientSession* encapsulated_client_session); - - // Unregister encapsulated client. |client_connection_id| must match a - // value previously passed to RegisterConnectionId. - void UnregisterConnectionId( - QuicConnectionId client_connection_id, + // Close CONNECT-UDP stream tied to this encapsulated client session. + void CloseConnectUdpStream( EncapsulatedClientSession* encapsulated_client_session); private: @@ -155,11 +135,7 @@ MasqueMode masque_mode_; std::string uri_template_; std::list<ConnectUdpClientState> connect_udp_client_states_; - absl::flat_hash_map<QuicConnectionId, EncapsulatedClientSession*, - QuicConnectionIdHash> - client_connection_id_registrations_; Owner* owner_; // Unowned; - MasqueCompressionEngine compression_engine_; }; } // namespace quic
diff --git a/quiche/quic/masque/masque_compression_engine.cc b/quiche/quic/masque/masque_compression_engine.cc deleted file mode 100644 index 3d05740..0000000 --- a/quiche/quic/masque/masque_compression_engine.cc +++ /dev/null
@@ -1,526 +0,0 @@ -// 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 "quiche/quic/masque/masque_compression_engine.h" - -#include <cstdint> - -#include "absl/strings/string_view.h" -#include "quiche/quic/core/quic_data_reader.h" -#include "quiche/quic/core/quic_data_writer.h" -#include "quiche/quic/core/quic_framer.h" -#include "quiche/quic/core/quic_session.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_containers.h" -#include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/common/quiche_buffer_allocator.h" -#include "quiche/common/quiche_text_utils.h" - -namespace quic { - -namespace { -// |kFlowId0| is used to indicate creation of a new compression context. -const QuicDatagramStreamId kFlowId0 = 0; - -enum MasqueAddressFamily : uint8_t { - MasqueAddressFamilyIPv4 = 4, - MasqueAddressFamilyIPv6 = 6, -}; - -} // namespace - -MasqueCompressionEngine::MasqueCompressionEngine( - QuicSpdySession* masque_session) - : masque_session_(masque_session), - next_available_flow_id_( - masque_session_->perspective() == Perspective::IS_CLIENT ? 0 : 1) {} - -QuicDatagramStreamId MasqueCompressionEngine::FindOrCreateCompressionContext( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, bool client_connection_id_present, - bool server_connection_id_present, bool* validated) { - QuicDatagramStreamId flow_id = kFlowId0; - *validated = false; - for (const auto& kv : contexts_) { - const MasqueCompressionContext& context = kv.second; - if (context.server_address != server_address) { - continue; - } - if (client_connection_id_present && - context.client_connection_id != client_connection_id) { - continue; - } - if (server_connection_id_present && - context.server_connection_id != server_connection_id) { - continue; - } - - flow_id = kv.first; - QUICHE_DCHECK_NE(flow_id, kFlowId0); - *validated = context.validated; - QUIC_DVLOG(1) << "Compressing using " << (*validated ? "" : "un") - << "validated flow_id " << flow_id << " to " - << context.server_address << " client " - << context.client_connection_id << " server " - << context.server_connection_id; - break; - } - - if (flow_id != kFlowId0) { - // Found a compression context, use it. - return flow_id; - } - - // Create new compression context. - next_available_flow_id_ += 2; - flow_id = next_available_flow_id_; - QUIC_DVLOG(1) << "Compression assigning new flow_id " << flow_id << " to " - << server_address << " client " << client_connection_id - << " server " << server_connection_id; - MasqueCompressionContext context; - context.client_connection_id = client_connection_id; - context.server_connection_id = server_connection_id; - context.server_address = server_address; - contexts_[flow_id] = context; - - return flow_id; -} - -bool MasqueCompressionEngine::WriteCompressedPacketToSlice( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, - QuicConnectionId destination_connection_id, - QuicConnectionId source_connection_id, QuicDatagramStreamId flow_id, - bool validated, uint8_t first_byte, bool long_header, - QuicDataReader* reader, QuicDataWriter* writer) { - if (validated) { - QUIC_DVLOG(1) << "Compressing using validated flow_id " << flow_id; - if (!writer->WriteVarInt62(flow_id)) { - QUIC_BUG(quic_bug_10981_1) << "Failed to write flow_id"; - return false; - } - } else { - QUIC_DVLOG(1) << "Compressing using unvalidated flow_id " << flow_id; - if (!writer->WriteVarInt62(kFlowId0)) { - QUIC_BUG(quic_bug_10981_2) << "Failed to write kFlowId0"; - return false; - } - if (!writer->WriteVarInt62(flow_id)) { - QUIC_BUG(quic_bug_10981_3) << "Failed to write flow_id"; - return false; - } - if (!writer->WriteLengthPrefixedConnectionId(client_connection_id)) { - QUIC_BUG(quic_bug_10981_4) << "Failed to write client_connection_id"; - return false; - } - if (!writer->WriteLengthPrefixedConnectionId(server_connection_id)) { - QUIC_BUG(quic_bug_10981_5) << "Failed to write server_connection_id"; - return false; - } - if (!writer->WriteUInt16(server_address.port())) { - QUIC_BUG(quic_bug_10981_6) << "Failed to write port"; - return false; - } - QuicIpAddress peer_ip = server_address.host(); - QUICHE_DCHECK(peer_ip.IsInitialized()); - std::string peer_ip_bytes = peer_ip.ToPackedString(); - QUICHE_DCHECK(!peer_ip_bytes.empty()); - uint8_t address_id; - if (peer_ip.address_family() == IpAddressFamily::IP_V6) { - address_id = MasqueAddressFamilyIPv6; - if (peer_ip_bytes.length() != QuicIpAddress::kIPv6AddressSize) { - QUIC_BUG(quic_bug_10981_7) << "Bad IPv6 length " << server_address; - return false; - } - } else if (peer_ip.address_family() == IpAddressFamily::IP_V4) { - address_id = MasqueAddressFamilyIPv4; - if (peer_ip_bytes.length() != QuicIpAddress::kIPv4AddressSize) { - QUIC_BUG(quic_bug_10981_8) << "Bad IPv4 length " << server_address; - return false; - } - } else { - QUIC_BUG(quic_bug_10981_9) - << "Unexpected server_address " << server_address; - return false; - } - if (!writer->WriteUInt8(address_id)) { - QUIC_BUG(quic_bug_10981_10) << "Failed to write address_id"; - return false; - } - if (!writer->WriteStringPiece(peer_ip_bytes)) { - QUIC_BUG(quic_bug_10981_11) << "Failed to write IP address"; - return false; - } - } - if (!writer->WriteUInt8(first_byte)) { - QUIC_BUG(quic_bug_10981_12) << "Failed to write first_byte"; - return false; - } - if (long_header) { - QuicVersionLabel version_label; - if (!reader->ReadUInt32(&version_label)) { - QUIC_DLOG(ERROR) << "Failed to read version"; - return false; - } - if (!writer->WriteUInt32(version_label)) { - QUIC_BUG(quic_bug_10981_13) << "Failed to write version"; - return false; - } - QuicConnectionId packet_destination_connection_id, - packet_source_connection_id; - if (!reader->ReadLengthPrefixedConnectionId( - &packet_destination_connection_id) || - !reader->ReadLengthPrefixedConnectionId(&packet_source_connection_id)) { - QUIC_DLOG(ERROR) << "Failed to parse long header connection IDs"; - return false; - } - if (packet_destination_connection_id != destination_connection_id) { - QUIC_DLOG(ERROR) << "Long header packet's destination_connection_id " - << packet_destination_connection_id - << " does not match expected " - << destination_connection_id; - return false; - } - if (packet_source_connection_id != source_connection_id) { - QUIC_DLOG(ERROR) << "Long header packet's source_connection_id " - << packet_source_connection_id - << " does not match expected " << source_connection_id; - return false; - } - } else { - QuicConnectionId packet_destination_connection_id; - if (!reader->ReadConnectionId(&packet_destination_connection_id, - destination_connection_id.length())) { - QUIC_DLOG(ERROR) - << "Failed to read short header packet's destination_connection_id"; - return false; - } - if (packet_destination_connection_id != destination_connection_id) { - QUIC_DLOG(ERROR) << "Short header packet's destination_connection_id " - << packet_destination_connection_id - << " does not match expected " - << destination_connection_id; - return false; - } - } - absl::string_view packet_payload = reader->ReadRemainingPayload(); - if (!writer->WriteStringPiece(packet_payload)) { - QUIC_BUG(quic_bug_10981_14) << "Failed to write packet_payload"; - return false; - } - return true; -} - -void MasqueCompressionEngine::CompressAndSendPacket( - absl::string_view packet, QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address) { - QUIC_DVLOG(2) << "Compressing client " << client_connection_id << " server " - << server_connection_id << "\n" - << quiche::QuicheTextUtils::HexDump(packet); - QUICHE_DCHECK(server_address.IsInitialized()); - if (packet.empty()) { - QUIC_BUG(quic_bug_10981_15) << "Tried to send empty packet"; - return; - } - QuicDataReader reader(packet.data(), packet.length()); - uint8_t first_byte; - if (!reader.ReadUInt8(&first_byte)) { - QUIC_BUG(quic_bug_10981_16) << "Failed to read first_byte"; - return; - } - const bool long_header = (first_byte & FLAGS_LONG_HEADER) != 0; - bool client_connection_id_present = true, server_connection_id_present = true; - QuicConnectionId destination_connection_id, source_connection_id; - if (masque_session_->perspective() == Perspective::IS_SERVER) { - destination_connection_id = client_connection_id; - source_connection_id = server_connection_id; - if (!long_header) { - server_connection_id_present = false; - } - } else { - destination_connection_id = server_connection_id; - source_connection_id = client_connection_id; - if (!long_header) { - client_connection_id_present = false; - } - } - - bool validated = false; - QuicDatagramStreamId flow_id = FindOrCreateCompressionContext( - client_connection_id, server_connection_id, server_address, - client_connection_id_present, server_connection_id_present, &validated); - - size_t slice_length = packet.length() - destination_connection_id.length(); - if (long_header) { - slice_length -= sizeof(uint8_t) * 2 + source_connection_id.length(); - } - if (validated) { - slice_length += QuicDataWriter::GetVarInt62Len(flow_id); - } else { - slice_length += QuicDataWriter::GetVarInt62Len(kFlowId0) + - QuicDataWriter::GetVarInt62Len(flow_id) + sizeof(uint8_t) + - client_connection_id.length() + sizeof(uint8_t) + - server_connection_id.length() + - sizeof(server_address.port()) + sizeof(uint8_t) + - server_address.host().ToPackedString().length(); - } - quiche::QuicheBuffer buffer( - masque_session_->connection()->helper()->GetStreamSendBufferAllocator(), - slice_length); - QuicDataWriter writer(buffer.size(), buffer.data()); - - if (!WriteCompressedPacketToSlice( - client_connection_id, server_connection_id, server_address, - destination_connection_id, source_connection_id, flow_id, validated, - first_byte, long_header, &reader, &writer)) { - return; - } - - MessageResult message_result = - masque_session_->SendMessage(quiche::QuicheMemSlice(std::move(buffer))); - - QUIC_DVLOG(1) << "Sent packet compressed with flow ID " << flow_id - << " and got message result " << message_result; -} - -bool MasqueCompressionEngine::ParseCompressionContext( - QuicDataReader* reader, MasqueCompressionContext* context) { - QuicDatagramStreamId new_flow_id; - if (!reader->ReadVarInt62(&new_flow_id)) { - QUIC_DLOG(ERROR) << "Could not read new_flow_id"; - return false; - } - QuicConnectionId new_client_connection_id; - if (!reader->ReadLengthPrefixedConnectionId(&new_client_connection_id)) { - QUIC_DLOG(ERROR) << "Could not read new_client_connection_id"; - return false; - } - QuicConnectionId new_server_connection_id; - if (!reader->ReadLengthPrefixedConnectionId(&new_server_connection_id)) { - QUIC_DLOG(ERROR) << "Could not read new_server_connection_id"; - return false; - } - uint16_t port; - if (!reader->ReadUInt16(&port)) { - QUIC_DLOG(ERROR) << "Could not read port"; - return false; - } - uint8_t address_id; - if (!reader->ReadUInt8(&address_id)) { - QUIC_DLOG(ERROR) << "Could not read address_id"; - return false; - } - size_t ip_bytes_length; - if (address_id == MasqueAddressFamilyIPv6) { - ip_bytes_length = QuicIpAddress::kIPv6AddressSize; - } else if (address_id == MasqueAddressFamilyIPv4) { - ip_bytes_length = QuicIpAddress::kIPv4AddressSize; - } else { - QUIC_DLOG(ERROR) << "Unknown address_id " << static_cast<int>(address_id); - return false; - } - char ip_bytes[QuicIpAddress::kMaxAddressSize]; - if (!reader->ReadBytes(ip_bytes, ip_bytes_length)) { - QUIC_DLOG(ERROR) << "Could not read IP address"; - return false; - } - QuicIpAddress ip_address; - ip_address.FromPackedString(ip_bytes, ip_bytes_length); - if (!ip_address.IsInitialized()) { - QUIC_BUG(quic_bug_10981_17) << "Failed to parse IP address"; - return false; - } - QuicSocketAddress new_server_address = QuicSocketAddress(ip_address, port); - auto context_pair = contexts_.find(new_flow_id); - if (context_pair == contexts_.end()) { - context->client_connection_id = new_client_connection_id; - context->server_connection_id = new_server_connection_id; - context->server_address = new_server_address; - context->validated = true; - contexts_[new_flow_id] = *context; - QUIC_DVLOG(1) << "Registered new flow_id " << new_flow_id << " to " - << new_server_address << " client " - << new_client_connection_id << " server " - << new_server_connection_id; - } else { - *context = context_pair->second; - if (context->client_connection_id != new_client_connection_id) { - QUIC_LOG(ERROR) - << "Received incorrect context registration for existing flow_id " - << new_flow_id << " mismatched client " - << context->client_connection_id << " " << new_client_connection_id; - return false; - } - if (context->server_connection_id != new_server_connection_id) { - QUIC_LOG(ERROR) - << "Received incorrect context registration for existing flow_id " - << new_flow_id << " mismatched server " - << context->server_connection_id << " " << new_server_connection_id; - return false; - } - if (context->server_address != new_server_address) { - QUIC_LOG(ERROR) - << "Received incorrect context registration for existing flow_id " - << new_flow_id << " mismatched server " << context->server_address - << " " << new_server_address; - return false; - } - if (!context->validated) { - context->validated = true; - contexts_[new_flow_id] = *context; - QUIC_DLOG(INFO) << "Successfully validated remotely-unvalidated flow_id " - << new_flow_id << " to " << new_server_address - << " client " << new_client_connection_id << " server " - << new_server_connection_id; - } else { - QUIC_DVLOG(1) << "Decompressing using incoming locally-validated " - "remotely-unvalidated flow_id " - << new_flow_id << " to " << new_server_address << " client " - << new_client_connection_id << " server " - << new_server_connection_id; - } - } - return true; -} - -bool MasqueCompressionEngine::WriteDecompressedPacket( - QuicDataReader* reader, const MasqueCompressionContext& context, - std::vector<char>* packet, bool* version_present) { - QuicConnectionId destination_connection_id, source_connection_id; - if (masque_session_->perspective() == Perspective::IS_SERVER) { - destination_connection_id = context.server_connection_id; - source_connection_id = context.client_connection_id; - } else { - destination_connection_id = context.client_connection_id; - source_connection_id = context.server_connection_id; - } - - size_t packet_length = - reader->BytesRemaining() + destination_connection_id.length(); - uint8_t first_byte; - if (!reader->ReadUInt8(&first_byte)) { - QUIC_DLOG(ERROR) << "Failed to read first_byte"; - return false; - } - *version_present = (first_byte & FLAGS_LONG_HEADER) != 0; - if (*version_present) { - packet_length += sizeof(uint8_t) * 2 + source_connection_id.length(); - } - *packet = std::vector<char>(packet_length); - QuicDataWriter writer(packet->size(), packet->data()); - if (!writer.WriteUInt8(first_byte)) { - QUIC_BUG(quic_bug_10981_18) << "Failed to write first_byte"; - return false; - } - if (*version_present) { - QuicVersionLabel version_label; - if (!reader->ReadUInt32(&version_label)) { - QUIC_DLOG(ERROR) << "Failed to read version"; - return false; - } - if (!writer.WriteUInt32(version_label)) { - QUIC_BUG(quic_bug_10981_19) << "Failed to write version"; - return false; - } - if (!writer.WriteLengthPrefixedConnectionId(destination_connection_id)) { - QUIC_BUG(quic_bug_10981_20) - << "Failed to write long header destination_connection_id"; - return false; - } - if (!writer.WriteLengthPrefixedConnectionId(source_connection_id)) { - QUIC_BUG(quic_bug_10981_21) - << "Failed to write long header source_connection_id"; - return false; - } - } else { - if (!writer.WriteConnectionId(destination_connection_id)) { - QUIC_BUG(quic_bug_10981_22) - << "Failed to write short header destination_connection_id"; - return false; - } - } - absl::string_view payload = reader->ReadRemainingPayload(); - if (!writer.WriteStringPiece(payload)) { - QUIC_BUG(quic_bug_10981_23) << "Failed to write payload"; - return false; - } - return true; -} - -bool MasqueCompressionEngine::DecompressDatagram( - absl::string_view datagram, QuicConnectionId* client_connection_id, - QuicConnectionId* server_connection_id, QuicSocketAddress* server_address, - std::vector<char>* packet, bool* version_present) { - QUIC_DVLOG(1) << "Decompressing DATAGRAM frame of length " - << datagram.length(); - QuicDataReader reader(datagram); - QuicDatagramStreamId flow_id; - if (!reader.ReadVarInt62(&flow_id)) { - QUIC_DLOG(ERROR) << "Could not read flow_id"; - return false; - } - MasqueCompressionContext context; - if (flow_id == kFlowId0) { - if (!ParseCompressionContext(&reader, &context)) { - return false; - } - } else { - auto context_pair = contexts_.find(flow_id); - if (context_pair == contexts_.end()) { - QUIC_DLOG(ERROR) << "Received unknown flow_id " << flow_id; - return false; - } - context = context_pair->second; - - if (!context.validated) { - context.validated = true; - contexts_[flow_id] = context; - QUIC_DLOG(INFO) << "Successfully validated remotely-validated flow_id " - << flow_id << " to " << context.server_address - << " client " << context.client_connection_id - << " server " << context.server_connection_id; - } else { - QUIC_DVLOG(1) << "Decompressing using incoming locally-validated " - "remotely-validated flow_id " - << flow_id << " to " << context.server_address << " client " - << context.client_connection_id << " server " - << context.server_connection_id; - } - } - - if (!WriteDecompressedPacket(&reader, context, packet, version_present)) { - return false; - } - - *server_address = context.server_address; - *client_connection_id = context.client_connection_id; - *server_connection_id = context.server_connection_id; - - QUIC_DVLOG(2) << "Decompressed client " << context.client_connection_id - << " server " << context.server_connection_id << "\n" - << quiche::QuicheTextUtils::HexDump( - absl::string_view(packet->data(), packet->size())); - - return true; -} - -void MasqueCompressionEngine::UnregisterClientConnectionId( - QuicConnectionId client_connection_id) { - std::vector<QuicDatagramStreamId> flow_ids_to_remove; - for (const auto& kv : contexts_) { - const MasqueCompressionContext& context = kv.second; - if (context.client_connection_id == client_connection_id) { - flow_ids_to_remove.push_back(kv.first); - } - } - for (QuicDatagramStreamId flow_id : flow_ids_to_remove) { - contexts_.erase(flow_id); - } -} - -} // namespace quic
diff --git a/quiche/quic/masque/masque_compression_engine.h b/quiche/quic/masque/masque_compression_engine.h deleted file mode 100644 index 8c09de2..0000000 --- a/quiche/quic/masque/masque_compression_engine.h +++ /dev/null
@@ -1,120 +0,0 @@ -// 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. - -#ifndef QUICHE_QUIC_MASQUE_MASQUE_COMPRESSION_ENGINE_H_ -#define QUICHE_QUIC_MASQUE_MASQUE_COMPRESSION_ENGINE_H_ - -#include "absl/container/flat_hash_map.h" -#include "absl/strings/string_view.h" -#include "quiche/quic/core/http/quic_spdy_session.h" -#include "quiche/quic/core/quic_connection_id.h" -#include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_containers.h" -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_socket_address.h" - -namespace quic { - -// MASQUE compression engine used by client and servers. -// This class allows converting QUIC packets into a compressed form suitable -// for sending over QUIC DATAGRAM frames. It leverages a flow identifier at the -// start of each datagram to indicate which compression context was used to -// compress this packet, or to create new compression contexts. -// Compression contexts contain client and server connection IDs and the -// server's IP and port. This allows compressing that information in most -// packets without requiring access to the cryptographic keys of the end-to-end -// encapsulated session. When the flow identifier is 0, the DATAGRAM contains -// all the contents of the compression context. When the flow identifier is -// non-zero, those fields are removed so the encapsulated QUIC packet is -// transmitted without connection IDs and reassembled by the peer on -// decompression. This only needs to contain the HTTP server's IP address since -// the client's IP address is not visible to the HTTP server. - -class QUIC_NO_EXPORT MasqueCompressionEngine { - public: - // Caller must ensure that |masque_session| has a lifetime longer than the - // newly constructed MasqueCompressionEngine. - explicit MasqueCompressionEngine(QuicSpdySession* masque_session); - - // Disallow copy and assign. - MasqueCompressionEngine(const MasqueCompressionEngine&) = delete; - MasqueCompressionEngine& operator=(const MasqueCompressionEngine&) = delete; - - // Compresses packet and sends it in a DATAGRAM frame over a MASQUE session. - // When used from MASQUE client to MASQUE server, the MASQUE server will then - // send the packet to the provided |server_address|. - // When used from MASQUE server to MASQUE client, the MASQUE client will then - // hand off the uncompressed packet to an encapsulated session that will treat - // it as having come from the provided |server_address|. - // The connection IDs are the one used by the encapsulated |packet|. - void CompressAndSendPacket(absl::string_view packet, - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address); - - // Decompresses received DATAGRAM frame contents from |datagram| and places - // them in |packet|. Reverses the transformation from CompressAndSendPacket. - // The connection IDs are the one used by the encapsulated |packet|. - // |server_address| will be filled with the |server_address| passed to - // CompressAndSendPacket. |version_present| will contain whether the - // encapsulated |packet| contains a Version field. - bool DecompressDatagram(absl::string_view datagram, - QuicConnectionId* client_connection_id, - QuicConnectionId* server_connection_id, - QuicSocketAddress* server_address, - std::vector<char>* packet, bool* version_present); - - // Clears all entries referencing |client_connection_id| from the - // compression table. - void UnregisterClientConnectionId(QuicConnectionId client_connection_id); - - private: - struct QUIC_NO_EXPORT MasqueCompressionContext { - QuicConnectionId client_connection_id; - QuicConnectionId server_connection_id; - QuicSocketAddress server_address; - bool validated = false; - }; - - // Finds or creates a new compression context to use during compression. - // |client_connection_id_present| and |server_connection_id_present| indicate - // whether the corresponding connection ID is present in the current packet. - // |validated| will contain whether the compression context that matches - // these arguments is currently validated or not. - QuicDatagramStreamId FindOrCreateCompressionContext( - QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, - bool client_connection_id_present, bool server_connection_id_present, - bool* validated); - - // Writes compressed packet to |slice| during compression. - bool WriteCompressedPacketToSlice(QuicConnectionId client_connection_id, - QuicConnectionId server_connection_id, - const QuicSocketAddress& server_address, - QuicConnectionId destination_connection_id, - QuicConnectionId source_connection_id, - QuicDatagramStreamId flow_id, - bool validated, uint8_t first_byte, - bool long_header, QuicDataReader* reader, - QuicDataWriter* writer); - - // Parses compression context from flow ID 0 during decompression. - bool ParseCompressionContext(QuicDataReader* reader, - MasqueCompressionContext* context); - - // Writes decompressed packet to |packet| during decompression. - bool WriteDecompressedPacket(QuicDataReader* reader, - const MasqueCompressionContext& context, - std::vector<char>* packet, - bool* version_present); - - QuicSpdySession* masque_session_; // Unowned. - absl::flat_hash_map<QuicDatagramStreamId, MasqueCompressionContext> contexts_; - QuicDatagramStreamId next_available_flow_id_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_MASQUE_MASQUE_COMPRESSION_ENGINE_H_
diff --git a/quiche/quic/masque/masque_dispatcher.cc b/quiche/quic/masque/masque_dispatcher.cc index 6db6f8c..d0440a6 100644 --- a/quiche/quic/masque/masque_dispatcher.cc +++ b/quiche/quic/masque/masque_dispatcher.cc
@@ -38,50 +38,11 @@ ParsedQuicVersionVector{version}); auto session = std::make_unique<MasqueServerSession>( - masque_mode_, config(), GetSupportedVersions(), connection, this, this, + masque_mode_, config(), GetSupportedVersions(), connection, this, epoll_server_, session_helper(), crypto_config(), compressed_certs_cache(), masque_server_backend_); session->Initialize(); return session; } -bool MasqueDispatcher::OnFailedToDispatchPacket( - const ReceivedPacketInfo& packet_info) { - auto connection_id_registration = client_connection_id_registrations_.find( - packet_info.destination_connection_id); - if (connection_id_registration == client_connection_id_registrations_.end()) { - QUIC_DLOG(INFO) << "MasqueDispatcher failed to dispatch " << packet_info; - return false; - } - MasqueServerSession* masque_server_session = - connection_id_registration->second; - masque_server_session->HandlePacketFromServer(packet_info); - return true; -} - -void MasqueDispatcher::RegisterClientConnectionId( - QuicConnectionId client_connection_id, - MasqueServerSession* masque_server_session) { - QUIC_DLOG(INFO) << "Registering encapsulated " << client_connection_id - << " to MASQUE session " - << masque_server_session->connection_id(); - - // Make sure we don't try to overwrite an existing registration with a - // different session. - QUIC_BUG_IF(quic_bug_12013_1, - client_connection_id_registrations_.find(client_connection_id) != - client_connection_id_registrations_.end() && - client_connection_id_registrations_[client_connection_id] != - masque_server_session) - << "Overwriting existing registration for " << client_connection_id; - client_connection_id_registrations_[client_connection_id] = - masque_server_session; -} - -void MasqueDispatcher::UnregisterClientConnectionId( - QuicConnectionId client_connection_id) { - QUIC_DLOG(INFO) << "Unregistering " << client_connection_id; - client_connection_id_registrations_.erase(client_connection_id); -} - } // namespace quic
diff --git a/quiche/quic/masque/masque_dispatcher.h b/quiche/quic/masque/masque_dispatcher.h index 90d319c..b5ef5bb 100644 --- a/quiche/quic/masque/masque_dispatcher.h +++ b/quiche/quic/masque/masque_dispatcher.h
@@ -17,8 +17,7 @@ // QUIC dispatcher that handles new MASQUE connections and can proxy traffic // between MASQUE clients and QUIC servers. -class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher, - public MasqueServerSession::Visitor { +class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher { public: explicit MasqueDispatcher( MasqueMode masque_mode, const QuicConfig* config, @@ -41,25 +40,10 @@ const ParsedQuicVersion& version, const quic::ParsedClientHello& parsed_chlo) override; - bool OnFailedToDispatchPacket(const ReceivedPacketInfo& packet_info) override; - - // From MasqueServerSession::Visitor. - void RegisterClientConnectionId( - QuicConnectionId client_connection_id, - MasqueServerSession* masque_server_session) override; - - void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) override; - private: MasqueMode masque_mode_; QuicEpollServer* epoll_server_; // Unowned. MasqueServerBackend* masque_server_backend_; // Unowned. - // Mapping from client connection IDs to server sessions, allows routing - // incoming packets to the right MASQUE connection. - absl::flat_hash_map<QuicConnectionId, MasqueServerSession*, - QuicConnectionIdHash> - client_connection_id_registrations_; }; } // namespace quic
diff --git a/quiche/quic/masque/masque_encapsulated_client_session.cc b/quiche/quic/masque/masque_encapsulated_client_session.cc index 988b511..077430f 100644 --- a/quiche/quic/masque/masque_encapsulated_client_session.cc +++ b/quiche/quic/masque/masque_encapsulated_client_session.cc
@@ -33,8 +33,7 @@ void MasqueEncapsulatedClientSession::OnConnectionClosed( const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) { QuicSpdyClientSession::OnConnectionClosed(frame, source); - masque_client_session_->UnregisterConnectionId( - connection()->client_connection_id(), this); + masque_client_session_->CloseConnectUdpStream(this); } } // namespace quic
diff --git a/quiche/quic/masque/masque_encapsulated_epoll_client.cc b/quiche/quic/masque/masque_encapsulated_epoll_client.cc index 41dde4e..242d265 100644 --- a/quiche/quic/masque/masque_encapsulated_epoll_client.cc +++ b/quiche/quic/masque/masque_encapsulated_epoll_client.cc
@@ -29,9 +29,7 @@ << " bytes to " << peer_address; absl::string_view 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, - client_->masque_encapsulated_client_session()); + packet, peer_address, client_->masque_encapsulated_client_session()); return WriteResult(WRITE_STATUS_OK, buf_len); } @@ -93,8 +91,8 @@ masque_client_(masque_client) {} MasqueEncapsulatedEpollClient::~MasqueEncapsulatedEpollClient() { - masque_client_->masque_client_session()->UnregisterConnectionId( - client_connection_id_, masque_encapsulated_client_session()); + masque_client_->masque_client_session()->CloseConnectUdpStream( + masque_encapsulated_client_session()); } std::unique_ptr<QuicSession> @@ -113,13 +111,4 @@ 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
diff --git a/quiche/quic/masque/masque_encapsulated_epoll_client.h b/quiche/quic/masque/masque_encapsulated_epoll_client.h index cbe1bcd..2b98652 100644 --- a/quiche/quic/masque/masque_encapsulated_epoll_client.h +++ b/quiche/quic/masque/masque_encapsulated_epoll_client.h
@@ -32,8 +32,6 @@ const ParsedQuicVersionVector& supported_versions, QuicConnection* connection) override; - QuicConnectionId GetClientConnectionId() override; - // MASQUE client that this client is encapsulated in. MasqueEpollClient* masque_client() { return masque_client_; } @@ -42,7 +40,6 @@ private: MasqueEpollClient* masque_client_; // Unowned. - QuicConnectionId client_connection_id_; }; } // namespace quic
diff --git a/quiche/quic/masque/masque_epoll_client.cc b/quiche/quic/masque/masque_epoll_client.cc index 6d6470b..705ea15 100644 --- a/quiche/quic/masque/masque_epoll_client.cc +++ b/quiche/quic/masque/masque_epoll_client.cc
@@ -91,36 +91,6 @@ return nullptr; } - if (masque_client->masque_mode() == MasqueMode::kLegacy) { - // Construct the legacy mode init request. - spdy::Http2HeaderBlock header_block; - header_block[":method"] = "POST"; - header_block[":scheme"] = "https"; - header_block[":authority"] = masque_client->authority(); - header_block[":path"] = "/.well-known/masque/init"; - std::string body = "foo"; - - // Make sure to store the response, for later output. - masque_client->set_store_response(true); - - // Send the MASQUE init command. - masque_client->SendRequestAndWaitForResponse(header_block, body, - /*fin=*/true); - - if (!masque_client->connected()) { - QUIC_LOG(ERROR) - << "MASQUE init request caused connection failure. Error: " - << QuicErrorCodeToString(masque_client->session()->error()); - return nullptr; - } - - const int response_code = masque_client->latest_response_code(); - if (response_code != 200) { - QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code " - << response_code; - return nullptr; - } - } return masque_client; } @@ -133,22 +103,4 @@ return connected() && settings_received_; } -void MasqueEpollClient::UnregisterClientConnectionId( - QuicConnectionId client_connection_id) { - std::string body(client_connection_id.data(), client_connection_id.length()); - - // Construct a GET or POST request for supplied URL. - spdy::Http2HeaderBlock header_block; - header_block[":method"] = "POST"; - header_block[":scheme"] = "https"; - header_block[":authority"] = authority(); - header_block[":path"] = "/.well-known/masque/unregister"; - - // Make sure to store the response, for later output. - set_store_response(true); - - // Send the MASQUE unregister command. - SendRequest(header_block, body, /*fin=*/true); -} - } // namespace quic
diff --git a/quiche/quic/masque/masque_epoll_client.h b/quiche/quic/masque/masque_epoll_client.h index 7b36bf6..7eff270 100644 --- a/quiche/quic/masque/masque_epoll_client.h +++ b/quiche/quic/masque/masque_epoll_client.h
@@ -38,9 +38,6 @@ // From MasqueClientSession::Owner. void OnSettingsReceived() override; - // Send a MASQUE client connection ID unregister command to the server. - void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) override; MasqueMode masque_mode() const { return masque_mode_; }
diff --git a/quiche/quic/masque/masque_server_backend.cc b/quiche/quic/masque/masque_server_backend.cc index 8dfe8b8..8e74e16 100644 --- a/quiche/quic/masque/masque_server_backend.cc +++ b/quiche/quic/masque/masque_server_backend.cc
@@ -20,7 +20,6 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest( const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { auto method_pair = request_headers.find(":method"); if (method_pair == request_headers.end()) { @@ -29,34 +28,11 @@ } absl::string_view method = method_pair->second; std::string masque_path = ""; - if (masque_mode_ == MasqueMode::kLegacy) { - auto path_pair = request_headers.find(":path"); - auto scheme_pair = request_headers.find(":scheme"); - if (path_pair == request_headers.end() || - scheme_pair == request_headers.end()) { - // This request is missing required headers. - return false; - } - absl::string_view path = path_pair->second; - absl::string_view scheme = scheme_pair->second; - if (scheme != "https" || method != "POST" || request_body.empty()) { - // MASQUE requests MUST be a non-empty https POST. - return false; - } - - if (path.rfind("/.well-known/masque/", 0) != 0) { - // This request is not a MASQUE path. - return false; - } - masque_path = std::string(path.substr(sizeof("/.well-known/masque/") - 1)); - } else { - QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen); - auto protocol_pair = request_headers.find(":protocol"); - if (method != "CONNECT" || protocol_pair == request_headers.end() || - protocol_pair->second != "connect-udp") { - // This is not a MASQUE request. - return false; - } + auto protocol_pair = request_headers.find(":protocol"); + if (method != "CONNECT" || protocol_pair == request_headers.end() || + protocol_pair->second != "connect-udp") { + // This is not a MASQUE request. + return false; } if (!server_authority_.empty()) { @@ -82,8 +58,7 @@ BackendClient* backend_client = it->second.backend_client; std::unique_ptr<QuicBackendResponse> response = - backend_client->HandleMasqueRequest(masque_path, request_headers, - request_body, request_handler); + backend_client->HandleMasqueRequest(request_headers, request_handler); if (response == nullptr) { QUIC_LOG(ERROR) << "Backend client did not process request for " << masque_path << request_headers.DebugString(); @@ -103,8 +78,7 @@ const spdy::Http2HeaderBlock& request_headers, const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { - if (MaybeHandleMasqueRequest(request_headers, request_body, - request_handler)) { + if (MaybeHandleMasqueRequest(request_headers, request_handler)) { // Request was handled as a MASQUE request. return; }
diff --git a/quiche/quic/masque/masque_server_backend.h b/quiche/quic/masque/masque_server_backend.h index 7480a86..8f35c3b 100644 --- a/quiche/quic/masque/masque_server_backend.h +++ b/quiche/quic/masque/masque_server_backend.h
@@ -21,9 +21,7 @@ class QUIC_NO_EXPORT BackendClient { public: virtual std::unique_ptr<QuicBackendResponse> HandleMasqueRequest( - const std::string& masque_path, const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) = 0; virtual ~BackendClient() = default; }; @@ -56,7 +54,6 @@ // Handle MASQUE request. bool MaybeHandleMasqueRequest( const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler); MasqueMode masque_mode_;
diff --git a/quiche/quic/masque/masque_server_bin.cc b/quiche/quic/masque/masque_server_bin.cc index ac1c189..bae882f 100644 --- a/quiche/quic/masque/masque_server_bin.cc +++ b/quiche/quic/masque/masque_server_bin.cc
@@ -31,9 +31,9 @@ "Specifies the authority over which the server will accept MASQUE " "requests. Defaults to empty which allows all authorities."); -DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, masque_mode, "", - "Allows setting MASQUE mode, valid values are " - "open and legacy. Defaults to open."); +DEFINE_QUICHE_COMMAND_LINE_FLAG( + std::string, masque_mode, "", + "Allows setting MASQUE mode, currently only valid value is \"open\"."); int main(int argc, char* argv[]) { quiche::QuicheSystemEventLoop event_loop("masque_server"); @@ -47,9 +47,7 @@ quic::MasqueMode masque_mode = quic::MasqueMode::kOpen; std::string mode_string = GetQuicFlag(FLAGS_masque_mode); - if (mode_string == "legacy") { - masque_mode = quic::MasqueMode::kLegacy; - } else if (!mode_string.empty() && mode_string != "open") { + if (!mode_string.empty() && mode_string != "open") { std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl; return 1; }
diff --git a/quiche/quic/masque/masque_server_session.cc b/quiche/quic/masque/masque_server_session.cc index 268421f..3a81caa 100644 --- a/quiche/quic/masque/masque_server_session.cc +++ b/quiche/quic/masque/masque_server_session.cc
@@ -78,7 +78,7 @@ MasqueServerSession::MasqueServerSession( MasqueMode masque_mode, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - QuicConnection* connection, QuicSession::Visitor* visitor, Visitor* owner, + QuicConnection* connection, QuicSession::Visitor* visitor, QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, @@ -87,9 +87,7 @@ helper, crypto_config, compressed_certs_cache, masque_server_backend), masque_server_backend_(masque_server_backend), - owner_(owner), epoll_server_(epoll_server), - compression_engine_(this), masque_mode_(masque_mode) { // Artificially increase the max packet length to 1350 to ensure we can fit // QUIC packets inside DATAGRAM frames. @@ -100,44 +98,6 @@ QUICHE_DCHECK_NE(epoll_server_, nullptr); } -void MasqueServerSession::OnMessageReceived(absl::string_view message) { - if (masque_mode_ == MasqueMode::kLegacy) { - QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length(); - QuicConnectionId client_connection_id, server_connection_id; - QuicSocketAddress target_server_address; - std::vector<char> packet; - bool version_present; - if (!compression_engine_.DecompressDatagram( - message, &client_connection_id, &server_connection_id, - &target_server_address, &packet, &version_present)) { - return; - } - - QUIC_DVLOG(1) << "Received packet of length " << packet.size() << " for " - << target_server_address << " client " - << client_connection_id; - - if (version_present) { - if (client_connection_id.length() != kQuicDefaultConnectionIdLength) { - QUIC_DLOG(ERROR) - << "Dropping long header with invalid client_connection_id " - << client_connection_id; - return; - } - owner_->RegisterClientConnectionId(client_connection_id, this); - } - - WriteResult write_result = connection()->writer()->WritePacket( - packet.data(), packet.size(), connection()->self_address().host(), - target_server_address, nullptr); - QUIC_DVLOG(1) << "Got " << write_result << " for " << packet.size() - << " bytes to " << target_server_address; - return; - } - QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen); - QuicSpdySession::OnMessageReceived(message); -} - void MasqueServerSession::OnMessageAcked(QuicMessageId message_id, QuicTime /*receive_timestamp*/) { QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id; @@ -166,206 +126,155 @@ } std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest( - const std::string& masque_path, const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { - if (masque_mode_ != MasqueMode::kLegacy) { - auto path_pair = request_headers.find(":path"); - auto scheme_pair = request_headers.find(":scheme"); - auto method_pair = request_headers.find(":method"); - auto protocol_pair = request_headers.find(":protocol"); - auto authority_pair = request_headers.find(":authority"); - if (path_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :path"; - return CreateBackendErrorResponse("400", "Missing :path"); - } - if (scheme_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme"; - return CreateBackendErrorResponse("400", "Missing :scheme"); - } - if (method_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :method"; - return CreateBackendErrorResponse("400", "Missing :method"); - } - if (protocol_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol"; - return CreateBackendErrorResponse("400", "Missing :protocol"); - } - if (authority_pair == request_headers.end()) { - QUIC_DLOG(ERROR) << "MASQUE request is missing :authority"; - return CreateBackendErrorResponse("400", "Missing :authority"); - } - absl::string_view path = path_pair->second; - absl::string_view scheme = scheme_pair->second; - absl::string_view method = method_pair->second; - absl::string_view protocol = protocol_pair->second; - absl::string_view authority = authority_pair->second; - if (path.empty()) { - QUIC_DLOG(ERROR) << "MASQUE request with empty path"; - return CreateBackendErrorResponse("400", "Empty path"); - } - if (scheme.empty()) { - return CreateBackendErrorResponse("400", "Empty scheme"); - } - if (method != "CONNECT") { - QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\""; - return CreateBackendErrorResponse("400", "Bad method"); - } - if (protocol != "connect-udp") { - QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol - << "\""; - return CreateBackendErrorResponse("400", "Bad protocol"); - } - absl::optional<QuicDatagramStreamId> flow_id; - if (http_datagram_support() == HttpDatagramSupport::kDraft00) { - flow_id = SpdyUtils::ParseDatagramFlowIdHeader(request_headers); - if (!flow_id.has_value()) { - QUIC_DLOG(ERROR) - << "MASQUE request with bad or missing DatagramFlowId header"; - return CreateBackendErrorResponse( - "400", "Bad or missing DatagramFlowId header"); - } - } - // Extract target host and port from path using default template. - std::vector<absl::string_view> path_split = absl::StrSplit(path, '/'); - if (path_split.size() != 4 || !path_split[0].empty() || - path_split[1].empty() || path_split[2].empty() || - !path_split[3].empty()) { - QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\""; - return CreateBackendErrorResponse("400", "Bad path"); - } - absl::optional<std::string> host = quiche::AsciiUrlDecode(path_split[1]); - if (!host.has_value()) { - QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[1] << "\""; - return CreateBackendErrorResponse("500", "Failed to decode host"); - } - absl::optional<std::string> port = quiche::AsciiUrlDecode(path_split[2]); - if (!port.has_value()) { - QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[2] << "\""; - return CreateBackendErrorResponse("500", "Failed to decode port"); - } - - // Perform DNS resolution. - addrinfo hint = {}; - hint.ai_protocol = IPPROTO_UDP; - - addrinfo* info_list = nullptr; - int result = getaddrinfo(host.value().c_str(), port.value().c_str(), &hint, - &info_list); - if (result != 0) { - QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": " - << gai_strerror(result); - return CreateBackendErrorResponse("500", "DNS resolution failed"); - } - - QUICHE_CHECK_NE(info_list, nullptr); - std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned( - info_list, freeaddrinfo); - QuicSocketAddress target_server_address(info_list->ai_addr, - info_list->ai_addrlen); - QUIC_DLOG(INFO) << "Got CONNECT_UDP request on stream ID " - << request_handler->stream_id() << " flow_id=" - << (flow_id.has_value() ? absl::StrCat(*flow_id) : "none") - << " target_server_address=\"" << target_server_address - << "\""; - - FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt()); - if (fd_wrapper.fd() == kQuicInvalidSocketFd) { - QUIC_DLOG(ERROR) << "Socket creation failed"; - return CreateBackendErrorResponse("500", "Socket creation failed"); - } - QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0); - if (target_server_address.host().IsIPv4()) { - empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0); - } - QuicUdpSocketApi socket_api; - if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) { - QUIC_DLOG(ERROR) << "Socket bind failed"; - return CreateBackendErrorResponse("500", "Socket bind failed"); - } - epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this); - - QuicSpdyStream* stream = static_cast<QuicSpdyStream*>( - GetActiveStream(request_handler->stream_id())); - if (stream == nullptr) { - QUIC_BUG(bad masque server stream type) - << "Unexpected stream type for stream ID " - << request_handler->stream_id(); - return CreateBackendErrorResponse("500", "Bad stream type"); - } - if (flow_id.has_value()) { - stream->RegisterHttp3DatagramFlowId(*flow_id); - } - connect_udp_server_states_.push_back(ConnectUdpServerState( - stream, target_server_address, fd_wrapper.extract_fd(), this)); - - if (http_datagram_support() == HttpDatagramSupport::kDraft00) { - // TODO(b/181256914) remove this when we drop support for - // draft-ietf-masque-h3-datagram-00 in favor of later drafts. - stream->RegisterHttp3DatagramVisitor(&connect_udp_server_states_.back()); - } - - spdy::Http2HeaderBlock response_headers; - response_headers[":status"] = "200"; - if (flow_id.has_value()) { - SpdyUtils::AddDatagramFlowIdHeader(&response_headers, *flow_id); - } - auto response = std::make_unique<QuicBackendResponse>(); - response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); - response->set_headers(std::move(response_headers)); - response->set_body(""); - - return response; + auto path_pair = request_headers.find(":path"); + auto scheme_pair = request_headers.find(":scheme"); + auto method_pair = request_headers.find(":method"); + auto protocol_pair = request_headers.find(":protocol"); + auto authority_pair = request_headers.find(":authority"); + if (path_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :path"; + return CreateBackendErrorResponse("400", "Missing :path"); } - - QUIC_DLOG(INFO) << "MasqueServerSession handling MASQUE request"; - - if (masque_path == "init") { - if (masque_initialized_) { - QUIC_DLOG(ERROR) << "Got second MASQUE init request"; - return nullptr; - } - masque_initialized_ = true; - } else if (masque_path == "unregister") { - QuicConnectionId connection_id(request_body.data(), request_body.length()); - QUIC_DLOG(INFO) << "Received MASQUE request to unregister " - << connection_id; - owner_->UnregisterClientConnectionId(connection_id); - compression_engine_.UnregisterClientConnectionId(connection_id); - } else { - if (!masque_initialized_) { - QUIC_DLOG(ERROR) << "Got MASQUE request before init"; - return nullptr; + if (scheme_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme"; + return CreateBackendErrorResponse("400", "Missing :scheme"); + } + if (method_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :method"; + return CreateBackendErrorResponse("400", "Missing :method"); + } + if (protocol_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol"; + return CreateBackendErrorResponse("400", "Missing :protocol"); + } + if (authority_pair == request_headers.end()) { + QUIC_DLOG(ERROR) << "MASQUE request is missing :authority"; + return CreateBackendErrorResponse("400", "Missing :authority"); + } + absl::string_view path = path_pair->second; + absl::string_view scheme = scheme_pair->second; + absl::string_view method = method_pair->second; + absl::string_view protocol = protocol_pair->second; + absl::string_view authority = authority_pair->second; + if (path.empty()) { + QUIC_DLOG(ERROR) << "MASQUE request with empty path"; + return CreateBackendErrorResponse("400", "Empty path"); + } + if (scheme.empty()) { + return CreateBackendErrorResponse("400", "Empty scheme"); + } + if (method != "CONNECT") { + QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\""; + return CreateBackendErrorResponse("400", "Bad method"); + } + if (protocol != "connect-udp") { + QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol + << "\""; + return CreateBackendErrorResponse("400", "Bad protocol"); + } + absl::optional<QuicDatagramStreamId> flow_id; + if (http_datagram_support() == HttpDatagramSupport::kDraft00) { + flow_id = SpdyUtils::ParseDatagramFlowIdHeader(request_headers); + if (!flow_id.has_value()) { + QUIC_DLOG(ERROR) + << "MASQUE request with bad or missing DatagramFlowId header"; + return CreateBackendErrorResponse("400", + "Bad or missing DatagramFlowId header"); } } + // Extract target host and port from path using default template. + std::vector<absl::string_view> path_split = absl::StrSplit(path, '/'); + if (path_split.size() != 4 || !path_split[0].empty() || + path_split[1].empty() || path_split[2].empty() || + !path_split[3].empty()) { + QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\""; + return CreateBackendErrorResponse("400", "Bad path"); + } + absl::optional<std::string> host = quiche::AsciiUrlDecode(path_split[1]); + if (!host.has_value()) { + QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[1] << "\""; + return CreateBackendErrorResponse("500", "Failed to decode host"); + } + absl::optional<std::string> port = quiche::AsciiUrlDecode(path_split[2]); + if (!port.has_value()) { + QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[2] << "\""; + return CreateBackendErrorResponse("500", "Failed to decode port"); + } - // TODO(dschinazi) implement binary protocol sent in response body. - const std::string response_body = ""; + // Perform DNS resolution. + addrinfo hint = {}; + hint.ai_protocol = IPPROTO_UDP; + + addrinfo* info_list = nullptr; + int result = getaddrinfo(host.value().c_str(), port.value().c_str(), &hint, + &info_list); + if (result != 0 || info_list == nullptr) { + QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": " + << gai_strerror(result); + return CreateBackendErrorResponse("500", "DNS resolution failed"); + } + + std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(info_list, + freeaddrinfo); + QuicSocketAddress target_server_address(info_list->ai_addr, + info_list->ai_addrlen); + QUIC_DLOG(INFO) << "Got CONNECT_UDP request on stream ID " + << request_handler->stream_id() << " flow_id=" + << (flow_id.has_value() ? absl::StrCat(*flow_id) : "none") + << " target_server_address=\"" << target_server_address + << "\""; + + FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt()); + if (fd_wrapper.fd() == kQuicInvalidSocketFd) { + QUIC_DLOG(ERROR) << "Socket creation failed"; + return CreateBackendErrorResponse("500", "Socket creation failed"); + } + QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0); + if (target_server_address.host().IsIPv4()) { + empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0); + } + QuicUdpSocketApi socket_api; + if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) { + QUIC_DLOG(ERROR) << "Socket bind failed"; + return CreateBackendErrorResponse("500", "Socket bind failed"); + } + epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this); + + QuicSpdyStream* stream = + static_cast<QuicSpdyStream*>(GetActiveStream(request_handler->stream_id())); + if (stream == nullptr) { + QUIC_BUG(bad masque server stream type) + << "Unexpected stream type for stream ID " + << request_handler->stream_id(); + return CreateBackendErrorResponse("500", "Bad stream type"); + } + if (flow_id.has_value()) { + stream->RegisterHttp3DatagramFlowId(*flow_id); + } + connect_udp_server_states_.push_back(ConnectUdpServerState( + stream, target_server_address, fd_wrapper.extract_fd(), this)); + + if (http_datagram_support() == HttpDatagramSupport::kDraft00) { + // TODO(b/181256914) remove this when we drop support for + // draft-ietf-masque-h3-datagram-00 in favor of later drafts. + stream->RegisterHttp3DatagramVisitor(&connect_udp_server_states_.back()); + } + spdy::Http2HeaderBlock response_headers; response_headers[":status"] = "200"; + if (flow_id.has_value()) { + SpdyUtils::AddDatagramFlowIdHeader(&response_headers, *flow_id); + } auto response = std::make_unique<QuicBackendResponse>(); - response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE); + response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); response->set_headers(std::move(response_headers)); - response->set_body(response_body); + response->set_body(""); return response; } -void MasqueServerSession::HandlePacketFromServer( - const ReceivedPacketInfo& packet_info) { - QUIC_DVLOG(1) << "MasqueServerSession received " << packet_info; - if (masque_mode_ == MasqueMode::kLegacy) { - compression_engine_.CompressAndSendPacket( - packet_info.packet.AsStringPiece(), - packet_info.destination_connection_id, packet_info.source_connection_id, - packet_info.peer_address); - return; - } - QUIC_LOG(ERROR) << "Ignoring packet from server in " << masque_mode_ - << " mode"; -} - void MasqueServerSession::OnRegistration(QuicEpollServer* /*eps*/, QuicUdpSocketFd fd, int event_mask) { QUIC_DVLOG(1) << "OnRegistration " << fd << " event_mask " << event_mask;
diff --git a/quiche/quic/masque/masque_server_session.h b/quiche/quic/masque/masque_server_session.h index 09aedb9..a2ae75d 100644 --- a/quiche/quic/masque/masque_server_session.h +++ b/quiche/quic/masque/masque_server_session.h
@@ -7,7 +7,6 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_udp_socket.h" -#include "quiche/quic/masque/masque_compression_engine.h" #include "quiche/quic/masque/masque_server_backend.h" #include "quiche/quic/masque/masque_utils.h" #include "quiche/quic/platform/api/quic_epoll.h" @@ -22,25 +21,10 @@ public MasqueServerBackend::BackendClient, public QuicEpollCallbackInterface { public: - // Interface meant to be implemented by owner of this MasqueServerSession - // instance. - class QUIC_NO_EXPORT Visitor { - public: - virtual ~Visitor() {} - // Register a client connection ID as being handled by this session. - virtual void RegisterClientConnectionId( - QuicConnectionId client_connection_id, - MasqueServerSession* masque_server_session) = 0; - - // Unregister a client connection ID. - virtual void UnregisterClientConnectionId( - QuicConnectionId client_connection_id) = 0; - }; - explicit MasqueServerSession( MasqueMode masque_mode, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - QuicConnection* connection, QuicSession::Visitor* visitor, Visitor* owner, + QuicConnection* connection, QuicSession::Visitor* visitor, QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper, const QuicCryptoServerConfig* crypto_config, QuicCompressedCertsCache* compressed_certs_cache, @@ -51,7 +35,6 @@ MasqueServerSession& operator=(const MasqueServerSession&) = delete; // From QuicSession. - void OnMessageReceived(absl::string_view message) override; void OnMessageAcked(QuicMessageId message_id, QuicTime receive_timestamp) override; void OnMessageLost(QuicMessageId message_id) override; @@ -61,9 +44,7 @@ // From MasqueServerBackend::BackendClient. std::unique_ptr<QuicBackendResponse> HandleMasqueRequest( - const std::string& masque_path, const spdy::Http2HeaderBlock& request_headers, - const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) override; // From QuicEpollCallbackInterface. @@ -75,9 +56,6 @@ void OnShutdown(QuicEpollServer* eps, QuicUdpSocketFd fd) override; std::string Name() const override; - // Handle packet for client, meant to be called by MasqueDispatcher. - void HandlePacketFromServer(const ReceivedPacketInfo& packet_info); - QuicEpollServer* epoll_server() const { return epoll_server_; } private: @@ -124,9 +102,7 @@ } MasqueServerBackend* masque_server_backend_; // Unowned. - Visitor* owner_; // Unowned. QuicEpollServer* epoll_server_; // Unowned. - MasqueCompressionEngine compression_engine_; MasqueMode masque_mode_; std::list<ConnectUdpServerState> connect_udp_server_states_; bool masque_initialized_ = false;
diff --git a/quiche/quic/masque/masque_utils.cc b/quiche/quic/masque/masque_utils.cc index b440bd1..d09fc49 100644 --- a/quiche/quic/masque/masque_utils.cc +++ b/quiche/quic/masque/masque_utils.cc
@@ -30,8 +30,6 @@ switch (masque_mode) { case MasqueMode::kInvalid: return "Invalid"; - case MasqueMode::kLegacy: - return "Legacy"; case MasqueMode::kOpen: return "Open"; }
diff --git a/quiche/quic/masque/masque_utils.h b/quiche/quic/masque/masque_utils.h index 652bf35..12faae0 100644 --- a/quiche/quic/masque/masque_utils.h +++ b/quiche/quic/masque/masque_utils.h
@@ -26,10 +26,6 @@ // Mode that MASQUE is operating in. enum class MasqueMode : uint8_t { kInvalid = 0, // Should never be used. - kLegacy = 1, // Legacy mode uses the legacy MASQUE protocol as documented in - // <https://tools.ietf.org/html/draft-schinazi-masque-protocol>. That version - // of MASQUE uses a custom application-protocol over HTTP/3, and also allows - // unauthenticated clients. kOpen = 2, // Open mode uses the MASQUE HTTP CONNECT-UDP method as documented // in <https://tools.ietf.org/html/draft-ietf-masque-connect-udp>. This mode // allows unauthenticated clients (a more restricted mode will be added to