xref: /aosp_15_r20/external/cronet/net/socket/tcp_client_socket.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_SOCKET_TCP_CLIENT_SOCKET_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_SOCKET_TCP_CLIENT_SOCKET_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/power_monitor/power_observer.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h"
18*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/address_list.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/base/completion_once_callback.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_descriptor.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/socket/stream_socket.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/socket/tcp_socket.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/socket/transport_client_socket.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation.h"
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker // PowerMonitor doesn't get suspend mode signals on Android, so don't use it to
29*6777b538SAndroid Build Coastguard Worker // watch for suspend events.
30*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_ANDROID)
31*6777b538SAndroid Build Coastguard Worker // Define SOCKETS_OBSERVE_SUSPEND if sockets should watch for suspend events so
32*6777b538SAndroid Build Coastguard Worker // they can fail pending socket operations on suspend. Otherwise, connections
33*6777b538SAndroid Build Coastguard Worker // hang for varying lengths of time when leaving suspend mode before failing
34*6777b538SAndroid Build Coastguard Worker // with TCP keepalive errors (~1 minute on macOS 10.14, up to several minutes on
35*6777b538SAndroid Build Coastguard Worker // Windows 10 1803). Firefox doesn't seems to need this logic, for unclear
36*6777b538SAndroid Build Coastguard Worker // reasons (experimentally, it doesn't seem to be the differences in the keep
37*6777b538SAndroid Build Coastguard Worker // alive settings it sets TCP sockets).
38*6777b538SAndroid Build Coastguard Worker #define TCP_CLIENT_SOCKET_OBSERVES_SUSPEND
39*6777b538SAndroid Build Coastguard Worker #endif
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker namespace net {
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker class IPEndPoint;
44*6777b538SAndroid Build Coastguard Worker class NetLog;
45*6777b538SAndroid Build Coastguard Worker struct NetLogSource;
46*6777b538SAndroid Build Coastguard Worker class SocketPerformanceWatcher;
47*6777b538SAndroid Build Coastguard Worker class NetworkQualityEstimator;
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker // A client socket that uses TCP as the transport layer.
50*6777b538SAndroid Build Coastguard Worker class NET_EXPORT TCPClientSocket : public TransportClientSocket,
51*6777b538SAndroid Build Coastguard Worker                                    public base::PowerSuspendObserver {
52*6777b538SAndroid Build Coastguard Worker  public:
53*6777b538SAndroid Build Coastguard Worker   // The IP address(es) and port number to connect to. The TCP socket will try
54*6777b538SAndroid Build Coastguard Worker   // each IP address in the list until it succeeds in establishing a
55*6777b538SAndroid Build Coastguard Worker   // connection.
56*6777b538SAndroid Build Coastguard Worker   // If `network` is specified, the socket will be bound to it. All data traffic
57*6777b538SAndroid Build Coastguard Worker   // on the socket will be sent and received via `network`. Communication using
58*6777b538SAndroid Build Coastguard Worker   // this socket will fail if `network` disconnects.
59*6777b538SAndroid Build Coastguard Worker   TCPClientSocket(
60*6777b538SAndroid Build Coastguard Worker       const AddressList& addresses,
61*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
62*6777b538SAndroid Build Coastguard Worker       NetworkQualityEstimator* network_quality_estimator,
63*6777b538SAndroid Build Coastguard Worker       net::NetLog* net_log,
64*6777b538SAndroid Build Coastguard Worker       const net::NetLogSource& source,
65*6777b538SAndroid Build Coastguard Worker       handles::NetworkHandle network = handles::kInvalidNetworkHandle);
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker   // Adopts the given, connected socket and then acts as if Connect() had been
68*6777b538SAndroid Build Coastguard Worker   // called. This function is used by TCPServerSocket and for testing.
69*6777b538SAndroid Build Coastguard Worker   TCPClientSocket(std::unique_ptr<TCPSocket> connected_socket,
70*6777b538SAndroid Build Coastguard Worker                   const IPEndPoint& peer_address);
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker   // Adopts an unconnected TCPSocket. TCPSocket may be bound or unbound. This
73*6777b538SAndroid Build Coastguard Worker   // function is used by BrokeredTcpClientSocket.
74*6777b538SAndroid Build Coastguard Worker   TCPClientSocket(std::unique_ptr<TCPSocket> unconnected_socket,
75*6777b538SAndroid Build Coastguard Worker                   const AddressList& addresses,
76*6777b538SAndroid Build Coastguard Worker                   std::unique_ptr<IPEndPoint> bound_address,
77*6777b538SAndroid Build Coastguard Worker                   NetworkQualityEstimator* network_quality_estimator);
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker   // Creates a TCPClientSocket from a bound-but-not-connected socket.
80*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<TCPClientSocket> CreateFromBoundSocket(
81*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<TCPSocket> bound_socket,
82*6777b538SAndroid Build Coastguard Worker       const AddressList& addresses,
83*6777b538SAndroid Build Coastguard Worker       const IPEndPoint& bound_address,
84*6777b538SAndroid Build Coastguard Worker       NetworkQualityEstimator* network_quality_estimator);
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   TCPClientSocket(const TCPClientSocket&) = delete;
87*6777b538SAndroid Build Coastguard Worker   TCPClientSocket& operator=(const TCPClientSocket&) = delete;
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   ~TCPClientSocket() override;
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   // TransportClientSocket implementation.
92*6777b538SAndroid Build Coastguard Worker   int Bind(const IPEndPoint& address) override;
93*6777b538SAndroid Build Coastguard Worker   bool SetKeepAlive(bool enable, int delay) override;
94*6777b538SAndroid Build Coastguard Worker   bool SetNoDelay(bool no_delay) override;
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker   // StreamSocket implementation.
97*6777b538SAndroid Build Coastguard Worker   void SetBeforeConnectCallback(
98*6777b538SAndroid Build Coastguard Worker       const BeforeConnectCallback& before_connect_callback) override;
99*6777b538SAndroid Build Coastguard Worker   int Connect(CompletionOnceCallback callback) override;
100*6777b538SAndroid Build Coastguard Worker   void Disconnect() override;
101*6777b538SAndroid Build Coastguard Worker   bool IsConnected() const override;
102*6777b538SAndroid Build Coastguard Worker   bool IsConnectedAndIdle() const override;
103*6777b538SAndroid Build Coastguard Worker   int GetPeerAddress(IPEndPoint* address) const override;
104*6777b538SAndroid Build Coastguard Worker   int GetLocalAddress(IPEndPoint* address) const override;
105*6777b538SAndroid Build Coastguard Worker   const NetLogWithSource& NetLog() const override;
106*6777b538SAndroid Build Coastguard Worker   bool WasEverUsed() const override;
107*6777b538SAndroid Build Coastguard Worker   NextProto GetNegotiatedProtocol() const override;
108*6777b538SAndroid Build Coastguard Worker   bool GetSSLInfo(SSLInfo* ssl_info) override;
109*6777b538SAndroid Build Coastguard Worker   int64_t GetTotalReceivedBytes() const override;
110*6777b538SAndroid Build Coastguard Worker   void ApplySocketTag(const SocketTag& tag) override;
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   // Socket implementation.
113*6777b538SAndroid Build Coastguard Worker   // Multiple outstanding requests are not supported.
114*6777b538SAndroid Build Coastguard Worker   // Full duplex mode (reading and writing at the same time) is supported.
115*6777b538SAndroid Build Coastguard Worker   int Read(IOBuffer* buf,
116*6777b538SAndroid Build Coastguard Worker            int buf_len,
117*6777b538SAndroid Build Coastguard Worker            CompletionOnceCallback callback) override;
118*6777b538SAndroid Build Coastguard Worker   int ReadIfReady(IOBuffer* buf,
119*6777b538SAndroid Build Coastguard Worker                   int buf_len,
120*6777b538SAndroid Build Coastguard Worker                   CompletionOnceCallback callback) override;
121*6777b538SAndroid Build Coastguard Worker   int CancelReadIfReady() override;
122*6777b538SAndroid Build Coastguard Worker   int Write(IOBuffer* buf,
123*6777b538SAndroid Build Coastguard Worker             int buf_len,
124*6777b538SAndroid Build Coastguard Worker             CompletionOnceCallback callback,
125*6777b538SAndroid Build Coastguard Worker             const NetworkTrafficAnnotationTag& traffic_annotation) override;
126*6777b538SAndroid Build Coastguard Worker   int SetReceiveBufferSize(int32_t size) override;
127*6777b538SAndroid Build Coastguard Worker   int SetSendBufferSize(int32_t size) override;
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker   // Exposes the underlying socket descriptor for testing its state. Does not
130*6777b538SAndroid Build Coastguard Worker   // release ownership of the descriptor.
131*6777b538SAndroid Build Coastguard Worker   SocketDescriptor SocketDescriptorForTesting() const;
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker   // base::PowerSuspendObserver methods:
134*6777b538SAndroid Build Coastguard Worker   void OnSuspend() override;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker  private:
137*6777b538SAndroid Build Coastguard Worker   // State machine for connecting the socket.
138*6777b538SAndroid Build Coastguard Worker   enum ConnectState {
139*6777b538SAndroid Build Coastguard Worker     CONNECT_STATE_CONNECT,
140*6777b538SAndroid Build Coastguard Worker     CONNECT_STATE_CONNECT_COMPLETE,
141*6777b538SAndroid Build Coastguard Worker     CONNECT_STATE_NONE,
142*6777b538SAndroid Build Coastguard Worker   };
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   // Main constructor. `socket` must be non-null. `current_address_index` is the
145*6777b538SAndroid Build Coastguard Worker   // address index in `addresses` of the server `socket` is connected to, or -1
146*6777b538SAndroid Build Coastguard Worker   // if not connected. `bind_address`, if present, is the address `socket` is
147*6777b538SAndroid Build Coastguard Worker   // bound to. `network` is the network the socket is required to be bound to,
148*6777b538SAndroid Build Coastguard Worker   // or handles::kInvalidNetworkHandle if no binding is required.
149*6777b538SAndroid Build Coastguard Worker   TCPClientSocket(std::unique_ptr<TCPSocket> socket,
150*6777b538SAndroid Build Coastguard Worker                   const AddressList& addresses,
151*6777b538SAndroid Build Coastguard Worker                   int current_address_index,
152*6777b538SAndroid Build Coastguard Worker                   std::unique_ptr<IPEndPoint> bind_address,
153*6777b538SAndroid Build Coastguard Worker                   NetworkQualityEstimator* network_quality_estimator,
154*6777b538SAndroid Build Coastguard Worker                   handles::NetworkHandle network);
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker   // A helper method shared by Read() and ReadIfReady(). If |read_if_ready| is
157*6777b538SAndroid Build Coastguard Worker   // set to true, ReadIfReady() will be used instead of Read().
158*6777b538SAndroid Build Coastguard Worker   int ReadCommon(IOBuffer* buf,
159*6777b538SAndroid Build Coastguard Worker                  int buf_len,
160*6777b538SAndroid Build Coastguard Worker                  const CompletionOnceCallback callback,
161*6777b538SAndroid Build Coastguard Worker                  bool read_if_ready);
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   // State machine used by Connect().
164*6777b538SAndroid Build Coastguard Worker   int DoConnectLoop(int result);
165*6777b538SAndroid Build Coastguard Worker   int DoConnect();
166*6777b538SAndroid Build Coastguard Worker   int DoConnectComplete(int result);
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker   void OnConnectAttemptTimeout();
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker   // Calls the connect method of |socket_|. Used in tests, to ensure a socket
171*6777b538SAndroid Build Coastguard Worker   // never connects.
172*6777b538SAndroid Build Coastguard Worker   virtual int ConnectInternal(const IPEndPoint& endpoint);
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker   // Helper used by Disconnect(), which disconnects minus resetting
175*6777b538SAndroid Build Coastguard Worker   // current_address_index_ and bind_address_.
176*6777b538SAndroid Build Coastguard Worker   void DoDisconnect();
177*6777b538SAndroid Build Coastguard Worker 
178*6777b538SAndroid Build Coastguard Worker   void DidCompleteConnect(int result);
179*6777b538SAndroid Build Coastguard Worker   void DidCompleteRead(int result);
180*6777b538SAndroid Build Coastguard Worker   void DidCompleteWrite(int result);
181*6777b538SAndroid Build Coastguard Worker   void DidCompleteReadWrite(CompletionOnceCallback callback, int result);
182*6777b538SAndroid Build Coastguard Worker 
183*6777b538SAndroid Build Coastguard Worker   int OpenSocket(AddressFamily family);
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   // Emits histograms for TCP metrics, at the time the socket is
186*6777b538SAndroid Build Coastguard Worker   // disconnected.
187*6777b538SAndroid Build Coastguard Worker   void EmitTCPMetricsHistogramsOnDisconnect();
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   // Emits histograms for the TCP connect attempt that just completed with
190*6777b538SAndroid Build Coastguard Worker   // |result|.
191*6777b538SAndroid Build Coastguard Worker   void EmitConnectAttemptHistograms(int result);
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker   // Gets the timeout to use for the next TCP connect attempt. This is an
194*6777b538SAndroid Build Coastguard Worker   // experimentally controlled value based on the estimated transport round
195*6777b538SAndroid Build Coastguard Worker   // trip time. If no timeout is to be enforced, returns
196*6777b538SAndroid Build Coastguard Worker   // base::TimeDelta::Max().
197*6777b538SAndroid Build Coastguard Worker   base::TimeDelta GetConnectAttemptTimeout();
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<TCPSocket> socket_;
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker   // Local IP address and port we are bound to. Set to NULL if Bind()
202*6777b538SAndroid Build Coastguard Worker   // wasn't called (in that case OS chooses address/port).
203*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<IPEndPoint> bind_address_;
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   // The list of addresses we should try in order to establish a connection.
206*6777b538SAndroid Build Coastguard Worker   AddressList addresses_;
207*6777b538SAndroid Build Coastguard Worker 
208*6777b538SAndroid Build Coastguard Worker   // Where we are in above list. Set to -1 if uninitialized.
209*6777b538SAndroid Build Coastguard Worker   int current_address_index_;
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker   // External callbacks; called when corresponding operations are complete.
212*6777b538SAndroid Build Coastguard Worker   // Cleared when no such operation is pending.
213*6777b538SAndroid Build Coastguard Worker   CompletionOnceCallback connect_callback_;
214*6777b538SAndroid Build Coastguard Worker   CompletionOnceCallback read_callback_;
215*6777b538SAndroid Build Coastguard Worker   CompletionOnceCallback write_callback_;
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker   // The next state for the Connect() state machine.
218*6777b538SAndroid Build Coastguard Worker   ConnectState next_connect_state_ = CONNECT_STATE_NONE;
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker   // This socket was previously disconnected and has not been re-connected.
221*6777b538SAndroid Build Coastguard Worker   bool previously_disconnected_ = false;
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker   // Total number of bytes received by the socket.
224*6777b538SAndroid Build Coastguard Worker   int64_t total_received_bytes_ = 0;
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker   BeforeConnectCallback before_connect_callback_;
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker   bool was_ever_used_ = false;
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   // Set to true if the socket was disconnected due to entering suspend mode.
231*6777b538SAndroid Build Coastguard Worker   // Once set, read/write operations return ERR_NETWORK_IO_SUSPENDED, until
232*6777b538SAndroid Build Coastguard Worker   // Connect() or Disconnect() is called.
233*6777b538SAndroid Build Coastguard Worker   bool was_disconnected_on_suspend_ = false;
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker   // The time when the latest connect attempt was started.
236*6777b538SAndroid Build Coastguard Worker   std::optional<base::TimeTicks> start_connect_attempt_;
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker   // The NetworkQualityEstimator for the context this socket is associated with.
239*6777b538SAndroid Build Coastguard Worker   // Can be nullptr.
240*6777b538SAndroid Build Coastguard Worker   raw_ptr<NetworkQualityEstimator> network_quality_estimator_;
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker   base::OneShotTimer connect_attempt_timer_;
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker   handles::NetworkHandle network_;
245*6777b538SAndroid Build Coastguard Worker 
246*6777b538SAndroid Build Coastguard Worker   base::WeakPtrFactory<TCPClientSocket> weak_ptr_factory_{this};
247*6777b538SAndroid Build Coastguard Worker };
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker }  // namespace net
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker #endif  // NET_SOCKET_TCP_CLIENT_SOCKET_H_
252