| // 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_CLIENT_SESSION_H_ |
| #define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ |
| |
| #include <string> |
| |
| #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_utils.h" |
| #include "quiche/quic/platform/api/quic_export.h" |
| #include "quiche/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 { |
| public: |
| // Interface meant to be implemented by the owner of the |
| // MasqueClientSession instance. |
| class QUIC_NO_EXPORT Owner { |
| public: |
| virtual ~Owner() {} |
| |
| // Notifies the owner that a settings frame has been received. |
| virtual void OnSettingsReceived() = 0; |
| }; |
| |
| // Interface meant to be implemented by client sessions encapsulated inside |
| // CONNECT-UDP, i.e. the end-to-end QUIC client sessions that run inside |
| // CONNECT-UDP encapsulation. |
| class QUIC_NO_EXPORT EncapsulatedClientSession { |
| public: |
| virtual ~EncapsulatedClientSession() {} |
| |
| // Process UDP packet that was just decapsulated. |packet| contains the UDP |
| // payload. |
| 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; |
| }; |
| |
| // Interface meant to be implemented by client sessions encapsulated inside |
| // CONNECT-IP, i.e. the end-to-end QUIC client sessions that run inside |
| // CONNECT-IP encapsulation. |
| class QUIC_NO_EXPORT EncapsulatedIpSession { |
| public: |
| virtual ~EncapsulatedIpSession() {} |
| |
| // Process packet that was just decapsulated. |packet| contains the IP |
| // header and payload. |
| virtual void ProcessIpPacket(absl::string_view packet) = 0; |
| |
| // Close the encapsulated connection. |
| virtual void CloseIpSession(const std::string& details) = 0; |
| |
| virtual bool OnAddressAssignCapsule( |
| const AddressAssignCapsule& capsule) = 0; |
| virtual bool OnAddressRequestCapsule( |
| const AddressRequestCapsule& capsule) = 0; |
| virtual bool OnRouteAdvertisementCapsule( |
| const RouteAdvertisementCapsule& capsule) = 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 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 UDP packet. |packet| contains the UDP payload. |
| void SendPacket(absl::string_view packet, |
| const QuicSocketAddress& target_server_address, |
| EncapsulatedClientSession* encapsulated_client_session); |
| |
| // Send encapsulated IP packet. |packet| contains the IP header and payload. |
| void SendIpPacket(absl::string_view packet, |
| EncapsulatedIpSession* encapsulated_ip_session); |
| |
| // Close CONNECT-UDP stream tied to this encapsulated client session. |
| void CloseConnectUdpStream( |
| EncapsulatedClientSession* encapsulated_client_session); |
| |
| // Close CONNECT-IP stream tied to this encapsulated client session. |
| void CloseConnectIpStream(EncapsulatedIpSession* encapsulated_ip_session); |
| |
| private: |
| // State that the MasqueClientSession keeps for each CONNECT-UDP request. |
| class QUIC_NO_EXPORT ConnectUdpClientState |
| : public QuicSpdyStream::Http3DatagramVisitor { |
| public: |
| // |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, |
| const QuicSocketAddress& target_server_address); |
| |
| ~ConnectUdpClientState(); |
| |
| // Disallow copy but allow move. |
| ConnectUdpClientState(const ConnectUdpClientState&) = delete; |
| ConnectUdpClientState(ConnectUdpClientState&&); |
| ConnectUdpClientState& operator=(const ConnectUdpClientState&) = delete; |
| ConnectUdpClientState& operator=(ConnectUdpClientState&&); |
| |
| QuicSpdyClientStream* stream() const { return stream_; } |
| EncapsulatedClientSession* encapsulated_client_session() const { |
| return encapsulated_client_session_; |
| } |
| const QuicSocketAddress& target_server_address() const { |
| return target_server_address_; |
| } |
| |
| // From QuicSpdyStream::Http3DatagramVisitor. |
| void OnHttp3Datagram(QuicStreamId stream_id, |
| absl::string_view payload) override; |
| |
| private: |
| QuicSpdyClientStream* stream_; // Unowned. |
| EncapsulatedClientSession* encapsulated_client_session_; // Unowned. |
| MasqueClientSession* masque_session_; // Unowned. |
| QuicSocketAddress target_server_address_; |
| }; |
| |
| // State that the MasqueClientSession keeps for each CONNECT-IP request. |
| class QUIC_NO_EXPORT ConnectIpClientState |
| : public QuicSpdyStream::Http3DatagramVisitor, |
| public QuicSpdyStream::ConnectIpVisitor { |
| public: |
| // |stream| and |encapsulated_client_session| must be valid for the lifetime |
| // of the ConnectUdpClientState. |
| explicit ConnectIpClientState( |
| QuicSpdyClientStream* stream, |
| EncapsulatedIpSession* encapsulated_ip_session, |
| MasqueClientSession* masque_session); |
| |
| ~ConnectIpClientState(); |
| |
| // Disallow copy but allow move. |
| ConnectIpClientState(const ConnectIpClientState&) = delete; |
| ConnectIpClientState(ConnectIpClientState&&); |
| ConnectIpClientState& operator=(const ConnectIpClientState&) = delete; |
| ConnectIpClientState& operator=(ConnectIpClientState&&); |
| |
| QuicSpdyClientStream* stream() const { return stream_; } |
| EncapsulatedIpSession* encapsulated_ip_session() const { |
| return encapsulated_ip_session_; |
| } |
| |
| // From QuicSpdyStream::Http3DatagramVisitor. |
| void OnHttp3Datagram(QuicStreamId stream_id, |
| absl::string_view payload) override; |
| |
| // From QuicSpdyStream::ConnectIpVisitor. |
| bool OnAddressAssignCapsule(const AddressAssignCapsule& capsule) override; |
| bool OnAddressRequestCapsule(const AddressRequestCapsule& capsule) override; |
| bool OnRouteAdvertisementCapsule( |
| const RouteAdvertisementCapsule& capsule) override; |
| void OnHeadersWritten() override; |
| |
| private: |
| QuicSpdyClientStream* stream_; // Unowned. |
| EncapsulatedIpSession* encapsulated_ip_session_; // Unowned. |
| MasqueClientSession* masque_session_; // Unowned. |
| }; |
| |
| HttpDatagramSupport LocalHttpDatagramSupport() override { |
| return HttpDatagramSupport::kRfc; |
| } |
| |
| const ConnectUdpClientState* GetOrCreateConnectUdpClientState( |
| const QuicSocketAddress& target_server_address, |
| EncapsulatedClientSession* encapsulated_client_session); |
| |
| const ConnectIpClientState* GetOrCreateConnectIpClientState( |
| EncapsulatedIpSession* encapsulated_ip_session); |
| |
| MasqueMode masque_mode_; |
| std::string uri_template_; |
| std::list<ConnectUdpClientState> connect_udp_client_states_; |
| std::list<ConnectIpClientState> connect_ip_client_states_; |
| Owner* owner_; // Unowned; |
| }; |
| |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ |