dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ |
| 6 | #define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ |
| 7 | |
vasilvv | 45a59fe | 2021-02-02 12:07:25 -0800 | [diff] [blame] | 8 | #include "absl/container/flat_hash_map.h" |
vasilvv | 3049b2b | 2020-10-08 08:18:31 -0700 | [diff] [blame] | 9 | #include "absl/strings/string_view.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 10 | #include "quic/core/http/quic_spdy_client_session.h" |
| 11 | #include "quic/masque/masque_compression_engine.h" |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 12 | #include "quic/masque/masque_utils.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 13 | #include "quic/platform/api/quic_export.h" |
| 14 | #include "quic/platform/api/quic_socket_address.h" |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 15 | |
| 16 | namespace quic { |
| 17 | |
| 18 | // QUIC client session for connection to MASQUE proxy. This session establishes |
| 19 | // a connection to a MASQUE proxy and handles sending and receiving DATAGRAM |
| 20 | // frames for operation of the MASQUE protocol. Multiple end-to-end encapsulated |
| 21 | // sessions can then coexist inside this session. Once these are created, they |
| 22 | // need to be registered with this session. |
| 23 | class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession { |
| 24 | public: |
| 25 | // Interface meant to be implemented by the owner of the |
| 26 | // MasqueClientSession instance. |
| 27 | class QUIC_NO_EXPORT Owner { |
| 28 | public: |
| 29 | virtual ~Owner() {} |
| 30 | |
| 31 | // Notifies the owner that the client connection ID is no longer in use. |
| 32 | virtual void UnregisterClientConnectionId( |
| 33 | QuicConnectionId client_connection_id) = 0; |
| 34 | }; |
| 35 | // Interface meant to be implemented by encapsulated client sessions, i.e. |
| 36 | // the end-to-end QUIC client sessions that run inside MASQUE encapsulation. |
| 37 | class QUIC_NO_EXPORT EncapsulatedClientSession { |
| 38 | public: |
| 39 | virtual ~EncapsulatedClientSession() {} |
| 40 | |
| 41 | // Process packet that was just decapsulated. |
vasilvv | 3049b2b | 2020-10-08 08:18:31 -0700 | [diff] [blame] | 42 | virtual void ProcessPacket(absl::string_view packet, |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 43 | QuicSocketAddress target_server_address) = 0; |
| 44 | |
| 45 | // Close the encapsulated connection. |
| 46 | virtual void CloseConnection( |
| 47 | QuicErrorCode error, |
| 48 | const std::string& details, |
| 49 | ConnectionCloseBehavior connection_close_behavior) = 0; |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 50 | }; |
| 51 | |
| 52 | // Takes ownership of |connection|, but not of |crypto_config| or |
| 53 | // |push_promise_index| or |owner|. All pointers must be non-null. Caller |
| 54 | // must ensure that |push_promise_index| and |owner| stay valid for the |
| 55 | // lifetime of the newly created MasqueClientSession. |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 56 | MasqueClientSession(MasqueMode masque_mode, |
| 57 | const QuicConfig& config, |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 58 | const ParsedQuicVersionVector& supported_versions, |
| 59 | QuicConnection* connection, |
| 60 | const QuicServerId& server_id, |
| 61 | QuicCryptoClientConfig* crypto_config, |
| 62 | QuicClientPushPromiseIndex* push_promise_index, |
| 63 | Owner* owner); |
| 64 | |
| 65 | // Disallow copy and assign. |
| 66 | MasqueClientSession(const MasqueClientSession&) = delete; |
| 67 | MasqueClientSession& operator=(const MasqueClientSession&) = delete; |
| 68 | |
| 69 | // From QuicSession. |
vasilvv | 3049b2b | 2020-10-08 08:18:31 -0700 | [diff] [blame] | 70 | void OnMessageReceived(absl::string_view message) override; |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 71 | void OnMessageAcked(QuicMessageId message_id, |
| 72 | QuicTime receive_timestamp) override; |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 73 | void OnMessageLost(QuicMessageId message_id) override; |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 74 | void OnConnectionClosed(const QuicConnectionCloseFrame& frame, |
| 75 | ConnectionCloseSource source) override; |
| 76 | void OnStreamClosed(QuicStreamId stream_id) override; |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 77 | |
| 78 | // Send encapsulated packet. |
| 79 | void SendPacket(QuicConnectionId client_connection_id, |
| 80 | QuicConnectionId server_connection_id, |
vasilvv | 3049b2b | 2020-10-08 08:18:31 -0700 | [diff] [blame] | 81 | absl::string_view packet, |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 82 | const QuicSocketAddress& target_server_address, |
| 83 | EncapsulatedClientSession* encapsulated_client_session); |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 84 | |
| 85 | // Register encapsulated client. This allows clients that are encapsulated |
| 86 | // within this MASQUE session to indicate they own a given client connection |
| 87 | // ID so incoming packets with that connection ID are routed back to them. |
| 88 | // Callers must not register a second different |encapsulated_client_session| |
| 89 | // with the same |client_connection_id|. Every call must be matched with a |
| 90 | // call to UnregisterConnectionId. |
| 91 | void RegisterConnectionId( |
| 92 | QuicConnectionId client_connection_id, |
| 93 | EncapsulatedClientSession* encapsulated_client_session); |
| 94 | |
| 95 | // Unregister encapsulated client. |client_connection_id| must match a |
| 96 | // value previously passed to RegisterConnectionId. |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 97 | void UnregisterConnectionId( |
| 98 | QuicConnectionId client_connection_id, |
| 99 | EncapsulatedClientSession* encapsulated_client_session); |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 100 | |
| 101 | private: |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 102 | // State that the MasqueClientSession keeps for each CONNECT-UDP request. |
dschinazi | 9ff30da | 2021-02-26 18:17:39 -0800 | [diff] [blame] | 103 | class QUIC_NO_EXPORT ConnectUdpClientState |
| 104 | : public QuicSpdySession::Http3DatagramVisitor { |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 105 | public: |
| 106 | // |stream| and |encapsulated_client_session| must be valid for the lifetime |
| 107 | // of the ConnectUdpClientState. |
| 108 | explicit ConnectUdpClientState( |
| 109 | QuicSpdyClientStream* stream, |
| 110 | EncapsulatedClientSession* encapsulated_client_session, |
dschinazi | 9ff30da | 2021-02-26 18:17:39 -0800 | [diff] [blame] | 111 | MasqueClientSession* masque_session, |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 112 | QuicDatagramFlowId flow_id, |
dschinazi | 9ff30da | 2021-02-26 18:17:39 -0800 | [diff] [blame] | 113 | const QuicSocketAddress& target_server_address); |
| 114 | |
| 115 | ~ConnectUdpClientState(); |
| 116 | |
| 117 | // Disallow copy but allow move. |
| 118 | ConnectUdpClientState(const ConnectUdpClientState&) = delete; |
| 119 | ConnectUdpClientState(ConnectUdpClientState&&); |
| 120 | ConnectUdpClientState& operator=(const ConnectUdpClientState&) = delete; |
| 121 | ConnectUdpClientState& operator=(ConnectUdpClientState&&); |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 122 | |
| 123 | QuicSpdyClientStream* stream() const { return stream_; } |
| 124 | EncapsulatedClientSession* encapsulated_client_session() const { |
| 125 | return encapsulated_client_session_; |
| 126 | } |
dschinazi | 9ff30da | 2021-02-26 18:17:39 -0800 | [diff] [blame] | 127 | QuicDatagramFlowId flow_id() const { |
| 128 | QUICHE_DCHECK(flow_id_.has_value()); |
| 129 | return *flow_id_; |
| 130 | } |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 131 | const QuicSocketAddress& target_server_address() const { |
| 132 | return target_server_address_; |
| 133 | } |
| 134 | |
dschinazi | 9ff30da | 2021-02-26 18:17:39 -0800 | [diff] [blame] | 135 | // From QuicSpdySession::Http3DatagramVisitor. |
| 136 | void OnHttp3Datagram(QuicDatagramFlowId flow_id, |
| 137 | absl::string_view payload) override; |
| 138 | |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 139 | private: |
| 140 | QuicSpdyClientStream* stream_; // Unowned. |
| 141 | EncapsulatedClientSession* encapsulated_client_session_; // Unowned. |
dschinazi | 9ff30da | 2021-02-26 18:17:39 -0800 | [diff] [blame] | 142 | MasqueClientSession* masque_session_; // Unowned. |
| 143 | absl::optional<QuicDatagramFlowId> flow_id_; |
dschinazi | da88cd1 | 2021-02-25 11:44:05 -0800 | [diff] [blame] | 144 | QuicSocketAddress target_server_address_; |
| 145 | }; |
| 146 | |
| 147 | const ConnectUdpClientState* GetOrCreateConnectUdpClientState( |
| 148 | const QuicSocketAddress& target_server_address, |
| 149 | EncapsulatedClientSession* encapsulated_client_session); |
| 150 | |
| 151 | MasqueMode masque_mode_; |
| 152 | std::list<ConnectUdpClientState> connect_udp_client_states_; |
vasilvv | 45a59fe | 2021-02-02 12:07:25 -0800 | [diff] [blame] | 153 | absl::flat_hash_map<QuicConnectionId, |
| 154 | EncapsulatedClientSession*, |
| 155 | QuicConnectionIdHash> |
dschinazi | 1c99fcf | 2019-12-13 11:54:22 -0800 | [diff] [blame] | 156 | client_connection_id_registrations_; |
| 157 | Owner* owner_; // Unowned; |
| 158 | MasqueCompressionEngine compression_engine_; |
| 159 | }; |
| 160 | |
| 161 | } // namespace quic |
| 162 | |
| 163 | #endif // QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_ |