client_socket_pool.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. // Copyright (c) 2012 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. #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_H_
  5. #define NET_SOCKET_CLIENT_SOCKET_POOL_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/time/time.h"
  11. #include "base/values.h"
  12. #include "net/base/completion_once_callback.h"
  13. #include "net/base/load_states.h"
  14. #include "net/base/net_export.h"
  15. #include "net/base/network_isolation_key.h"
  16. #include "net/base/privacy_mode.h"
  17. #include "net/base/request_priority.h"
  18. #include "net/dns/host_resolver.h"
  19. #include "net/dns/public/secure_dns_policy.h"
  20. #include "net/http/http_request_info.h"
  21. #include "net/log/net_log_capture_mode.h"
  22. #include "net/socket/connect_job.h"
  23. #include "net/socket/socket_tag.h"
  24. #include "third_party/abseil-cpp/absl/types/optional.h"
  25. #include "url/scheme_host_port.h"
  26. namespace net {
  27. class ClientSocketHandle;
  28. class ConnectJobFactory;
  29. class HttpAuthController;
  30. class HttpResponseInfo;
  31. class NetLogWithSource;
  32. struct NetworkTrafficAnnotationTag;
  33. class ProxyServer;
  34. struct SSLConfig;
  35. class StreamSocket;
  36. // ClientSocketPools are layered. This defines an interface for lower level
  37. // socket pools to communicate with higher layer pools.
  38. class NET_EXPORT HigherLayeredPool {
  39. public:
  40. virtual ~HigherLayeredPool() = default;
  41. // Instructs the HigherLayeredPool to close an idle connection. Return true if
  42. // one was closed. Closing an idle connection will call into the lower layer
  43. // pool it came from, so must be careful of re-entrancy when using this.
  44. virtual bool CloseOneIdleConnection() = 0;
  45. };
  46. // ClientSocketPools are layered. This defines an interface for higher level
  47. // socket pools to communicate with lower layer pools.
  48. class NET_EXPORT LowerLayeredPool {
  49. public:
  50. virtual ~LowerLayeredPool() = default;
  51. // Returns true if a there is currently a request blocked on the per-pool
  52. // (not per-host) max socket limit, either in this pool, or one that it is
  53. // layered on top of.
  54. virtual bool IsStalled() const = 0;
  55. // Called to add or remove a higher layer pool on top of |this|. A higher
  56. // layer pool may be added at most once to |this|, and must be removed prior
  57. // to destruction of |this|.
  58. virtual void AddHigherLayeredPool(HigherLayeredPool* higher_pool) = 0;
  59. virtual void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) = 0;
  60. };
  61. // A ClientSocketPool is used to restrict the number of sockets open at a time.
  62. // It also maintains a list of idle persistent sockets.
  63. //
  64. // Subclasses must also have an inner class SocketParams which is
  65. // the type for the |params| argument in RequestSocket() and
  66. // RequestSockets() below.
  67. class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
  68. public:
  69. // Indicates whether or not a request for a socket should respect the
  70. // SocketPool's global and per-group socket limits.
  71. enum class RespectLimits { DISABLED, ENABLED };
  72. // ProxyAuthCallback is invoked when there is an auth challenge while
  73. // connecting to a tunnel. When |restart_with_auth_callback| is invoked, the
  74. // corresponding socket request is guaranteed not to be completed
  75. // synchronously, nor will the ProxyAuthCallback be invoked against
  76. // synchronously.
  77. typedef base::RepeatingCallback<void(
  78. const HttpResponseInfo& response,
  79. HttpAuthController* auth_controller,
  80. base::OnceClosure restart_with_auth_callback)>
  81. ProxyAuthCallback;
  82. // Group ID for a socket request. Requests with the same group ID are
  83. // considered indistinguishable.
  84. class NET_EXPORT GroupId {
  85. public:
  86. GroupId();
  87. GroupId(url::SchemeHostPort destination,
  88. PrivacyMode privacy_mode,
  89. NetworkIsolationKey network_isolation_key,
  90. SecureDnsPolicy secure_dns_policy);
  91. GroupId(const GroupId& group_id);
  92. ~GroupId();
  93. GroupId& operator=(const GroupId& group_id);
  94. GroupId& operator=(GroupId&& group_id);
  95. const url::SchemeHostPort& destination() const { return destination_; }
  96. PrivacyMode privacy_mode() const { return privacy_mode_; }
  97. const NetworkIsolationKey& network_isolation_key() const {
  98. return network_isolation_key_;
  99. }
  100. SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; }
  101. // Returns the group ID as a string, for logging.
  102. std::string ToString() const;
  103. bool operator==(const GroupId& other) const {
  104. return std::tie(destination_, privacy_mode_, network_isolation_key_,
  105. secure_dns_policy_) ==
  106. std::tie(other.destination_, other.privacy_mode_,
  107. other.network_isolation_key_, other.secure_dns_policy_);
  108. }
  109. bool operator<(const GroupId& other) const {
  110. return std::tie(destination_, privacy_mode_, network_isolation_key_,
  111. secure_dns_policy_) <
  112. std::tie(other.destination_, other.privacy_mode_,
  113. other.network_isolation_key_, other.secure_dns_policy_);
  114. }
  115. private:
  116. // The endpoint of the final destination (not the proxy).
  117. url::SchemeHostPort destination_;
  118. // If this request is for a privacy mode / uncredentialed connection.
  119. PrivacyMode privacy_mode_;
  120. // Used to separate requests made in different contexts.
  121. NetworkIsolationKey network_isolation_key_;
  122. // Controls the Secure DNS behavior to use when creating this socket.
  123. SecureDnsPolicy secure_dns_policy_;
  124. };
  125. // Parameters that, in combination with GroupId, proxy, websocket information,
  126. // and global state, are sufficient to create a ConnectJob.
  127. //
  128. // DO NOT ADD ANY FIELDS TO THIS CLASS.
  129. //
  130. // TODO(https://crbug.com/921369) In order to resolve longstanding issues
  131. // related to pooling distinguishable sockets together, remove this class
  132. // entirely.
  133. class NET_EXPORT_PRIVATE SocketParams
  134. : public base::RefCounted<SocketParams> {
  135. public:
  136. // For non-SSL requests / non-HTTPS proxies, the corresponding SSLConfig
  137. // argument may be nullptr.
  138. SocketParams(std::unique_ptr<SSLConfig> ssl_config_for_origin,
  139. std::unique_ptr<SSLConfig> ssl_config_for_proxy);
  140. SocketParams(const SocketParams&) = delete;
  141. SocketParams& operator=(const SocketParams&) = delete;
  142. // Creates a SocketParams object with none of the fields populated. This
  143. // works for the HTTP case only.
  144. static scoped_refptr<SocketParams> CreateForHttpForTesting();
  145. const SSLConfig* ssl_config_for_origin() const {
  146. return ssl_config_for_origin_.get();
  147. }
  148. const SSLConfig* ssl_config_for_proxy() const {
  149. return ssl_config_for_proxy_.get();
  150. }
  151. private:
  152. friend class base::RefCounted<SocketParams>;
  153. ~SocketParams();
  154. std::unique_ptr<SSLConfig> ssl_config_for_origin_;
  155. std::unique_ptr<SSLConfig> ssl_config_for_proxy_;
  156. };
  157. ClientSocketPool(const ClientSocketPool&) = delete;
  158. ClientSocketPool& operator=(const ClientSocketPool&) = delete;
  159. ~ClientSocketPool() override;
  160. // Requests a connected socket with a specified GroupId.
  161. //
  162. // There are five possible results from calling this function:
  163. // 1) RequestSocket returns OK and initializes |handle| with a reused socket.
  164. // 2) RequestSocket returns OK with a newly connected socket.
  165. // 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a
  166. // wait list until a socket is available to reuse or a new socket finishes
  167. // connecting. |priority| will determine the placement into the wait list.
  168. // 4) An error occurred early on, so RequestSocket returns an error code.
  169. // 5) A recoverable error occurred while setting up the socket. An error
  170. // code is returned, but the |handle| is initialized with the new socket.
  171. // The caller must recover from the error before using the connection, or
  172. // Disconnect the socket before releasing or resetting the |handle|.
  173. // The current recoverable errors are: the errors accepted by
  174. // IsCertificateError(err) and HTTPS_PROXY_TUNNEL_RESPONSE when reported by
  175. // HttpProxyClientSocketPool.
  176. //
  177. // If this function returns OK, then |handle| is initialized upon return.
  178. // The |handle|'s is_initialized method will return true in this case. If a
  179. // StreamSocket was reused, then ClientSocketPool will call
  180. // |handle|->set_reused(true). In either case, the socket will have been
  181. // allocated and will be connected. A client might want to know whether or
  182. // not the socket is reused in order to request a new socket if it encounters
  183. // an error with the reused socket.
  184. //
  185. // If ERR_IO_PENDING is returned, then the callback will be used to notify the
  186. // client of completion.
  187. //
  188. // Profiling information for the request is saved to |net_log| if non-NULL.
  189. //
  190. // If |respect_limits| is DISABLED, priority must be HIGHEST.
  191. //
  192. // |proxy_annotation_tag| is the annotation used for proxy-related reads and
  193. // writes, and may be nullopt if (and only if) no proxy is in use.
  194. //
  195. // |proxy_auth_callback| will be invoked each time an auth challenge is seen
  196. // while establishing a tunnel. It will be invoked asynchronously, once for
  197. // each auth challenge seen.
  198. virtual int RequestSocket(
  199. const GroupId& group_id,
  200. scoped_refptr<SocketParams> params,
  201. const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
  202. RequestPriority priority,
  203. const SocketTag& socket_tag,
  204. RespectLimits respect_limits,
  205. ClientSocketHandle* handle,
  206. CompletionOnceCallback callback,
  207. const ProxyAuthCallback& proxy_auth_callback,
  208. const NetLogWithSource& net_log) = 0;
  209. // RequestSockets is used to request that |num_sockets| be connected in the
  210. // connection group for |group_id|. If the connection group already has
  211. // |num_sockets| idle sockets / active sockets / currently connecting sockets,
  212. // then this function doesn't do anything and returns OK. Otherwise, it will
  213. // start up as many connections as necessary to reach |num_sockets| total
  214. // sockets for the group and returns ERR_IO_PENDING. And |callback| will be
  215. // called with OK when the connection tasks are finished.
  216. // It uses |params| to control how to connect the sockets. The
  217. // ClientSocketPool will assign a priority to the new connections, if any.
  218. // This priority will probably be lower than all others, since this method
  219. // is intended to make sure ahead of time that |num_sockets| sockets are
  220. // available to talk to a host.
  221. virtual int RequestSockets(
  222. const GroupId& group_id,
  223. scoped_refptr<SocketParams> params,
  224. const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
  225. int num_sockets,
  226. CompletionOnceCallback callback,
  227. const NetLogWithSource& net_log) = 0;
  228. // Called to change the priority of a RequestSocket call that returned
  229. // ERR_IO_PENDING and has not yet asynchronously completed. The same handle
  230. // parameter must be passed to this method as was passed to the
  231. // RequestSocket call being modified.
  232. // This function is a no-op if |priority| is the same as the current
  233. // request priority.
  234. virtual void SetPriority(const GroupId& group_id,
  235. ClientSocketHandle* handle,
  236. RequestPriority priority) = 0;
  237. // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The
  238. // same handle parameter must be passed to this method as was passed to the
  239. // RequestSocket call being cancelled. The associated callback is not run.
  240. // If |cancel_connect_job| is true, and there are more ConnectJobs than
  241. // requests, a ConnectJob will be canceled. If it's false, excess ConnectJobs
  242. // may be allowed to continue, just in case there are new requests to the same
  243. // endpoint.
  244. virtual void CancelRequest(const GroupId& group_id,
  245. ClientSocketHandle* handle,
  246. bool cancel_connect_job) = 0;
  247. // Called to release a socket once the socket is no longer needed. If the
  248. // socket still has an established connection, then it will be added to the
  249. // set of idle sockets to be used to satisfy future RequestSocket calls.
  250. // Otherwise, the StreamSocket is destroyed. |generation| is used to
  251. // differentiate between updated versions of the same pool instance. The
  252. // pool's generation will change when it flushes, so it can use this
  253. // |generation| to discard sockets with mismatched ids.
  254. virtual void ReleaseSocket(const GroupId& group_id,
  255. std::unique_ptr<StreamSocket> socket,
  256. int64_t generation) = 0;
  257. // This flushes all state from the ClientSocketPool. Pending socket requests
  258. // are failed with |error|, while |reason| is logged to the NetLog.
  259. //
  260. // Active sockets being held by ClientSocketPool clients will be discarded
  261. // when released back to the pool, though they will be closed with an error
  262. // about being of the wrong generation, rather than |net_log_reason_utf8|.
  263. virtual void FlushWithError(int error, const char* net_log_reason_utf8) = 0;
  264. // Called to close any idle connections held by the connection manager.
  265. // |reason| is logged to NetLog for debugging purposes.
  266. virtual void CloseIdleSockets(const char* net_log_reason_utf8) = 0;
  267. // Called to close any idle connections held by the connection manager.
  268. // |reason| is logged to NetLog for debugging purposes.
  269. virtual void CloseIdleSocketsInGroup(const GroupId& group_id,
  270. const char* net_log_reason_utf8) = 0;
  271. // The total number of idle sockets in the pool.
  272. virtual int IdleSocketCount() const = 0;
  273. // The total number of idle sockets in a connection group.
  274. virtual size_t IdleSocketCountInGroup(const GroupId& group_id) const = 0;
  275. // Determine the LoadState of a connecting ClientSocketHandle.
  276. virtual LoadState GetLoadState(const GroupId& group_id,
  277. const ClientSocketHandle* handle) const = 0;
  278. // Retrieves information on the current state of the pool as a
  279. // Value.
  280. // If |include_nested_pools| is true, the states of any nested
  281. // ClientSocketPools will be included.
  282. virtual base::Value GetInfoAsValue(const std::string& name,
  283. const std::string& type) const = 0;
  284. // Returns whether a connected (idle or handed out) or connecting socket
  285. // exists for the group. This method is not supported for WebSockets.
  286. virtual bool HasActiveSocket(const GroupId& group_id) const = 0;
  287. // Returns the maximum amount of time to wait before retrying a connect.
  288. static const int kMaxConnectRetryIntervalMs = 250;
  289. static base::TimeDelta used_idle_socket_timeout();
  290. static void set_used_idle_socket_timeout(base::TimeDelta timeout);
  291. protected:
  292. ClientSocketPool(bool is_for_websockets,
  293. const CommonConnectJobParams* common_connect_job_params,
  294. std::unique_ptr<ConnectJobFactory> connect_job_factory);
  295. void NetLogTcpClientSocketPoolRequestedSocket(const NetLogWithSource& net_log,
  296. const GroupId& group_id);
  297. // Utility method to log a GroupId with a NetLog event.
  298. static base::Value NetLogGroupIdParams(const GroupId& group_id);
  299. std::unique_ptr<ConnectJob> CreateConnectJob(
  300. GroupId group_id,
  301. scoped_refptr<SocketParams> socket_params,
  302. const ProxyServer& proxy_server,
  303. const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
  304. RequestPriority request_priority,
  305. SocketTag socket_tag,
  306. ConnectJob::Delegate* delegate);
  307. private:
  308. const bool is_for_websockets_;
  309. const raw_ptr<const CommonConnectJobParams> common_connect_job_params_;
  310. const std::unique_ptr<ConnectJobFactory> connect_job_factory_;
  311. };
  312. } // namespace net
  313. #endif // NET_SOCKET_CLIENT_SOCKET_POOL_H_