xref: /aosp_15_r20/external/cronet/net/quic/quic_proxy_datagram_client_socket.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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