1 // Copyright 2024 The Chromium Authors 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 NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ 6 #define NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ 7 8 #include <stdint.h> 9 10 #include <queue> 11 12 #include "net/base/ip_endpoint.h" 13 #include "net/base/net_export.h" 14 #include "net/log/net_log.h" 15 #include "net/log/net_log_with_source.h" 16 #include "net/quic/quic_chromium_client_session.h" 17 #include "net/quic/quic_chromium_client_stream.h" 18 #include "net/socket/datagram_client_socket.h" 19 #include "net/socket/udp_socket.h" 20 #include "net/spdy/spdy_http_utils.h" 21 #include "net/traffic_annotation/network_traffic_annotation.h" 22 #include "url/scheme_host_port.h" 23 24 namespace net { 25 26 class ProxyDelegate; 27 28 // A client socket that uses a QUIC proxy as the transport layer. 29 // 30 // Given that DatagramClientSocket class contains numerous methods tailored for 31 // UDP, many methods from DatagramClientSocket are left as stubs. 32 // ConnectViaStream is used to connect this socket over the provided QUIC stream 33 // to send and receive datagrams. 34 class NET_EXPORT_PRIVATE QuicProxyDatagramClientSocket 35 : public DatagramClientSocket, 36 public quic::QuicSpdyStream::Http3DatagramVisitor { 37 public: 38 // Initializes a QuicProxyDatagramClientSocket with the provided network 39 // log (source_net_log) and destination URL. The destination URL is 40 // derived from a URI Template containing the variables "target_host" 41 // and "target_port". These variables need to be prepopulated by the caller of 42 // this constructor. Datagrams will be sent to this target server. 43 // 44 // The `proxy_chain` describes the connection to the proxies over which 45 // this socket carries data, which thus must have at least one proxy. 46 QuicProxyDatagramClientSocket(const GURL& url, 47 const ProxyChain& proxy_chain, 48 const std::string& user_agent, 49 const NetLogWithSource& source_net_log, 50 ProxyDelegate* proxy_delegate); 51 52 QuicProxyDatagramClientSocket(const QuicProxyDatagramClientSocket&) = delete; 53 QuicProxyDatagramClientSocket& operator=( 54 const QuicProxyDatagramClientSocket&) = delete; 55 56 // On destruction Close() is called. 57 ~QuicProxyDatagramClientSocket() override; 58 59 // Connect this socket over the given QUIC stream, using the `url_` 60 // and local and proxy peer addresses. The socket has no true peer 61 // address since it is connected over a proxy and the proxy performs the 62 // hostname resolution. Instead `proxy_peer_address_` is the peer to which the 63 // underlying socket is connected. 64 // 65 // The passed stream is a connection to the last proxy in `proxy_chain`. 66 int ConnectViaStream(const IPEndPoint& local_address, 67 const IPEndPoint& proxy_peer_address, 68 std::unique_ptr<QuicChromiumClientStream::Handle> stream, 69 CompletionOnceCallback callback); 70 71 // DatagramClientSocket implementation. 72 int Connect(const IPEndPoint& address) override; 73 int ConnectUsingNetwork(handles::NetworkHandle network, 74 const IPEndPoint& address) override; 75 int ConnectUsingDefaultNetwork(const IPEndPoint& address) override; 76 int ConnectAsync(const IPEndPoint& address, 77 CompletionOnceCallback callback) override; 78 int ConnectUsingNetworkAsync(handles::NetworkHandle network, 79 const IPEndPoint& address, 80 CompletionOnceCallback callback) override; 81 int ConnectUsingDefaultNetworkAsync(const IPEndPoint& address, 82 CompletionOnceCallback callback) override; 83 handles::NetworkHandle GetBoundNetwork() const override; 84 void ApplySocketTag(const SocketTag& tag) override; 85 int SetMulticastInterface(uint32_t interface_index) override; 86 void SetIOSNetworkServiceType(int ios_network_service_type) override; 87 88 // DatagramSocket implementation. 89 void Close() override; 90 int GetPeerAddress(IPEndPoint* address) const override; 91 int GetLocalAddress(IPEndPoint* address) const override; 92 void UseNonBlockingIO() override; 93 int SetDoNotFragment() override; 94 int SetRecvTos() override; 95 int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) override; 96 void SetMsgConfirm(bool confirm) override; 97 const NetLogWithSource& NetLog() const override; 98 DscpAndEcn GetLastTos() const override; 99 100 // Socket implementation. 101 int Read(IOBuffer* buf, 102 int buf_len, 103 CompletionOnceCallback callback) override; 104 int Write(IOBuffer* buf, 105 int buf_len, 106 CompletionOnceCallback callback, 107 const NetworkTrafficAnnotationTag& traffic_annotation) override; 108 int SetReceiveBufferSize(int32_t size) override; 109 int SetSendBufferSize(int32_t size) override; 110 111 // Http3DatagramVisitor implementation. 112 void OnHttp3Datagram(quic::QuicStreamId stream_id, 113 absl::string_view payload) override; 114 void OnUnknownCapsule(quic::QuicStreamId stream_id, 115 const quiche::UnknownCapsule& capsule) override; 116 117 const HttpResponseInfo* GetConnectResponseInfo() const; 118 bool IsConnected() const; 119 GetDatagramsForTesting()120 const std::queue<std::string>& GetDatagramsForTesting() { return datagrams_; } 121 122 static constexpr char kMaxQueueSizeHistogram[] = 123 "Net.QuicProxyDatagramClientSocket.MaxQueueSizeReached"; 124 125 // Upper bound for datagrams in queue. 126 static constexpr size_t kMaxDatagramQueueSize = 16; 127 128 private: 129 enum State { 130 STATE_DISCONNECTED, 131 STATE_SEND_REQUEST, 132 STATE_SEND_REQUEST_COMPLETE, 133 STATE_READ_REPLY, 134 STATE_READ_REPLY_COMPLETE, 135 STATE_CONNECT_COMPLETE 136 }; 137 138 // Callback used during connecting 139 void OnIOComplete(int result); 140 141 // Callback for stream_->ReadInitialHeaders() 142 void OnReadResponseHeadersComplete(int result); 143 int ProcessResponseHeaders(const spdy::Http2HeaderBlock& headers); 144 145 int DoLoop(int last_io_result); 146 int DoSendRequest(); 147 int DoSendRequestComplete(int result); 148 int DoReadReply(); 149 int DoReadReplyComplete(int result); 150 151 // ProxyDelegate operates in terms of a full proxy chain and an 152 // index into that chain identifying the "current" proxy. Emulate 153 // this by simply using the current chain and indexing the last proxy in 154 // that chain. proxy_chain()155 const ProxyChain& proxy_chain() { return proxy_chain_; } proxy_chain_index()156 int proxy_chain_index() { return proxy_chain_.length() - 1; } 157 158 State next_state_ = STATE_DISCONNECTED; 159 160 // Stores the callback for Connect(). 161 CompletionOnceCallback connect_callback_; 162 // Stores the callback for Read(). 163 CompletionOnceCallback read_callback_; 164 // Stores the buffer pointer for Read(). 165 raw_ptr<IOBuffer> read_buf_ = nullptr; 166 // Stores the buffer length for Read(). 167 int read_buf_len_ = 0; 168 169 // Handle to the QUIC Stream that this sits on top of. 170 std::unique_ptr<QuicChromiumClientStream::Handle> stream_handle_; 171 172 // Queue for storing incoming datagrams received over QUIC. This queue acts as 173 // a buffer, allowing datagrams to be stored when received and processed 174 // asynchronously at a later time. 175 std::queue<std::string> datagrams_; 176 // Visitor on stream is registered to receive HTTP/3 datagrams. 177 bool datagram_visitor_registered_ = false; 178 179 // CONNECT request and response. 180 HttpRequestInfo request_; 181 HttpResponseInfo response_; 182 183 spdy::Http2HeaderBlock response_header_block_; 184 185 // Local address of socket. 186 IPEndPoint local_address_; 187 // The peer IP of sockets underlying connection. 188 IPEndPoint proxy_peer_address_; 189 190 // The URL generated from the expanded URI Template. 191 // This URI Template includes variables for "target_host" and "target_port", 192 // which have been replaced with their actual values to form the complete URL. 193 GURL url_; 194 195 // The proxy chain this socket represents: `stream_` is a connection to the 196 // last proxy in this chain. 197 const ProxyChain proxy_chain_; 198 199 // This delegate must outlive this proxy client socket. 200 const raw_ptr<ProxyDelegate> proxy_delegate_; 201 202 std::string user_agent_; 203 204 NetLogWithSource net_log_; 205 206 // The default weak pointer factory. 207 base::WeakPtrFactory<QuicProxyDatagramClientSocket> weak_factory_{this}; 208 }; 209 210 } // namespace net 211 212 #endif // NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ 213