blob: f8af4afd0e962a069c1daab209db952e4491dcc1 [file] [log] [blame]
// 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 <string>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "quic/core/http/quic_spdy_client_session.h"
#include "quic/masque/masque_compression_engine.h"
#include "quic/masque/masque_utils.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_socket_address.h"
namespace quic {
// QUIC client session for connection to MASQUE proxy. This session establishes
// a connection to a MASQUE proxy and handles sending and receiving DATAGRAM
// frames for operation of the MASQUE protocol. Multiple end-to-end encapsulated
// sessions can then coexist inside this session. Once these are created, they
// need to be registered with this session.
class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
// Interface meant to be implemented by the owner of the
// MasqueClientSession instance.
class QUIC_NO_EXPORT Owner {
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;
// Interface meant to be implemented by encapsulated client sessions, i.e.
// the end-to-end QUIC client sessions that run inside MASQUE encapsulation.
class QUIC_NO_EXPORT EncapsulatedClientSession {
virtual ~EncapsulatedClientSession() {}
// Process packet that was just decapsulated.
virtual void ProcessPacket(absl::string_view packet,
QuicSocketAddress target_server_address) = 0;
// Close the encapsulated connection.
virtual void CloseConnection(
QuicErrorCode error,
const std::string& details,
ConnectionCloseBehavior connection_close_behavior) = 0;
// Takes ownership of |connection|, but not of |crypto_config| or
// |push_promise_index| or |owner|. All pointers must be non-null. Caller
// must ensure that |push_promise_index| and |owner| stay valid for the
// lifetime of the newly created MasqueClientSession.
MasqueClientSession(MasqueMode masque_mode, const std::string& uri_template,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection, const QuicServerId& server_id,
QuicCryptoClientConfig* crypto_config,
QuicClientPushPromiseIndex* push_promise_index,
Owner* owner);
// Disallow copy and assign.
MasqueClientSession(const MasqueClientSession&) = delete;
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;
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source) override;
void OnStreamClosed(QuicStreamId stream_id) override;
// From QuicSpdySession.
bool OnSettingsFrame(const SettingsFrame& frame) override;
// Send encapsulated packet.
void SendPacket(QuicConnectionId client_connection_id,
QuicConnectionId server_connection_id,
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,
EncapsulatedClientSession* encapsulated_client_session);
// State that the MasqueClientSession keeps for each CONNECT-UDP request.
class QUIC_NO_EXPORT ConnectUdpClientState
: public QuicSpdyStream::Http3DatagramRegistrationVisitor,
public QuicSpdyStream::Http3DatagramVisitor {
// |stream| and |encapsulated_client_session| must be valid for the lifetime
// of the ConnectUdpClientState.
explicit ConnectUdpClientState(
QuicSpdyClientStream* stream,
EncapsulatedClientSession* encapsulated_client_session,
MasqueClientSession* masque_session,
absl::optional<QuicDatagramContextId> context_id,
const QuicSocketAddress& target_server_address);
// Disallow copy but allow move.
ConnectUdpClientState(const ConnectUdpClientState&) = delete;
ConnectUdpClientState& operator=(const ConnectUdpClientState&) = delete;
ConnectUdpClientState& operator=(ConnectUdpClientState&&);
QuicSpdyClientStream* stream() const { return stream_; }
EncapsulatedClientSession* encapsulated_client_session() const {
return encapsulated_client_session_;
absl::optional<QuicDatagramContextId> context_id() const {
return context_id_;
const QuicSocketAddress& target_server_address() const {
return target_server_address_;
// From QuicSpdyStream::Http3DatagramVisitor.
void OnHttp3Datagram(QuicStreamId stream_id,
absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) override;
// From QuicSpdyStream::Http3DatagramRegistrationVisitor.
void OnContextReceived(QuicStreamId stream_id,
absl::optional<QuicDatagramContextId> context_id,
DatagramFormatType format_type,
absl::string_view format_additional_data) override;
void OnContextClosed(QuicStreamId stream_id,
absl::optional<QuicDatagramContextId> context_id,
ContextCloseCode close_code,
absl::string_view close_details) override;
QuicSpdyClientStream* stream_; // Unowned.
EncapsulatedClientSession* encapsulated_client_session_; // Unowned.
MasqueClientSession* masque_session_; // Unowned.
absl::optional<QuicDatagramContextId> context_id_;
QuicSocketAddress target_server_address_;
HttpDatagramSupport LocalHttpDatagramSupport() override {
return HttpDatagramSupport::kDraft00And04;
const ConnectUdpClientState* GetOrCreateConnectUdpClientState(
const QuicSocketAddress& target_server_address,
EncapsulatedClientSession* encapsulated_client_session);
MasqueMode masque_mode_;
std::string uri_template_;
std::list<ConnectUdpClientState> connect_udp_client_states_;
Owner* owner_; // Unowned;
MasqueCompressionEngine compression_engine_;
} // namespace quic