1 // Copyright 2012 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_SOCKET_CLIENT_SOCKET_HANDLE_H_ 6 #define NET_SOCKET_CLIENT_SOCKET_HANDLE_H_ 7 8 #include <memory> 9 #include <utility> 10 11 #include "base/check.h" 12 #include "base/functional/bind.h" 13 #include "base/memory/raw_ptr.h" 14 #include "base/memory/scoped_refptr.h" 15 #include "base/time/time.h" 16 #include "net/base/ip_endpoint.h" 17 #include "net/base/load_states.h" 18 #include "net/base/load_timing_info.h" 19 #include "net/base/net_errors.h" 20 #include "net/base/net_export.h" 21 #include "net/base/request_priority.h" 22 #include "net/dns/public/resolve_error_info.h" 23 #include "net/log/net_log_source.h" 24 #include "net/log/net_log_with_source.h" 25 #include "net/socket/client_socket_pool.h" 26 #include "net/socket/connection_attempts.h" 27 #include "net/socket/stream_socket.h" 28 #include "net/ssl/ssl_cert_request_info.h" 29 #include "third_party/abseil-cpp/absl/types/optional.h" 30 31 namespace net { 32 33 class ConnectJob; 34 struct NetworkTrafficAnnotationTag; 35 class SocketTag; 36 37 // A container for a StreamSocket. 38 // 39 // The handle's |group_id| uniquely identifies the origin and type of the 40 // connection. It is used by the ClientSocketPool to group similar connected 41 // client socket objects. 42 // 43 class NET_EXPORT ClientSocketHandle { 44 public: 45 enum SocketReuseType { 46 UNUSED = 0, // unused socket that just finished connecting 47 UNUSED_IDLE, // unused socket that has been idle for awhile 48 REUSED_IDLE, // previously used socket 49 NUM_TYPES, 50 }; 51 52 ClientSocketHandle(); 53 54 ClientSocketHandle(const ClientSocketHandle&) = delete; 55 ClientSocketHandle& operator=(const ClientSocketHandle&) = delete; 56 57 ~ClientSocketHandle(); 58 59 // Initializes a ClientSocketHandle object, which involves talking to the 60 // ClientSocketPool to obtain a connected socket, possibly reusing one. This 61 // method returns either OK or ERR_IO_PENDING. On ERR_IO_PENDING, |priority| 62 // is used to determine the placement in ClientSocketPool's wait list. 63 // If |respect_limits| is DISABLED, will bypass the wait list, but |priority| 64 // must also be HIGHEST, if set. 65 // 66 // If this method succeeds, then the socket member will be set to an existing 67 // connected socket if an existing connected socket was available to reuse, 68 // otherwise it will be set to a new connected socket. Consumers can then 69 // call is_reused() to see if the socket was reused. If not reusing an 70 // existing socket, ClientSocketPool may need to establish a new 71 // connection using |socket_params|. 72 // 73 // This method returns ERR_IO_PENDING if it cannot complete synchronously, in 74 // which case the consumer will be notified of completion via |callback|. 75 // 76 // If the pool was not able to reuse an existing socket, the new socket 77 // may report a recoverable error. In this case, the return value will 78 // indicate an error and the socket member will be set. If it is determined 79 // that the error is not recoverable, the Disconnect method should be used 80 // on the socket, so that it does not get reused. 81 // 82 // A non-recoverable error may set additional state in the ClientSocketHandle 83 // to allow the caller to determine what went wrong. 84 // 85 // Init may be called multiple times. 86 // 87 // Profiling information for the request is saved to |net_log| if non-NULL. 88 int Init( 89 const ClientSocketPool::GroupId& group_id, 90 scoped_refptr<ClientSocketPool::SocketParams> socket_params, 91 const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag, 92 RequestPriority priority, 93 const SocketTag& socket_tag, 94 ClientSocketPool::RespectLimits respect_limits, 95 CompletionOnceCallback callback, 96 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback, 97 ClientSocketPool* pool, 98 const NetLogWithSource& net_log); 99 100 // Changes the priority of the ClientSocketHandle to the passed value. 101 // This function is a no-op if |priority| is the same as the current 102 // priority, of if Init() has not been called since the last time 103 // the ClientSocketHandle was reset. 104 void SetPriority(RequestPriority priority); 105 106 // An initialized handle can be reset, which causes it to return to the 107 // un-initialized state. This releases the underlying socket, which in the 108 // case of a socket that still has an established connection, indicates that 109 // the socket may be kept alive for use by a subsequent ClientSocketHandle. 110 // 111 // NOTE: To prevent the socket from being kept alive, be sure to call its 112 // Disconnect method. This will result in the ClientSocketPool deleting the 113 // StreamSocket. 114 void Reset(); 115 116 // Like Reset(), but also closes the socket (if there is one) and cancels any 117 // pending attempt to establish a connection, if the connection attempt is 118 // still ongoing. 119 void ResetAndCloseSocket(); 120 121 // Used after Init() is called, but before the ClientSocketPool has 122 // initialized the ClientSocketHandle. 123 LoadState GetLoadState() const; 124 125 bool IsPoolStalled() const; 126 127 // Adds a higher layered pool on top of the socket pool that |socket_| belongs 128 // to. At most one higher layered pool can be added to a 129 // ClientSocketHandle at a time. On destruction or reset, automatically 130 // removes the higher pool if RemoveHigherLayeredPool has not been called. 131 void AddHigherLayeredPool(HigherLayeredPool* higher_pool); 132 133 // Removes a higher layered pool from the socket pool that |socket_| belongs 134 // to. |higher_pool| must have been added by the above function. 135 void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool); 136 137 // Closes idle sockets that are in the same group with |this|. 138 void CloseIdleSocketsInGroup(const char* net_log_reason_utf8); 139 140 // Returns true when Init() has completed successfully. is_initialized()141 bool is_initialized() const { return is_initialized_; } 142 143 // Sets the portion of LoadTimingInfo related to connection establishment, and 144 // the socket id. |is_reused| is needed because the handle may not have full 145 // reuse information. |load_timing_info| must have all default values when 146 // called. Returns false and makes no changes to |load_timing_info| when 147 // |socket_| is NULL. 148 bool GetLoadTimingInfo(bool is_reused, 149 LoadTimingInfo* load_timing_info) const; 150 151 // Used by ClientSocketPool to initialize the ClientSocketHandle. 152 // 153 // SetSocket() may also be used if this handle is used as simply for 154 // socket storage (e.g., http://crbug.com/37810). 155 void SetSocket(std::unique_ptr<StreamSocket> s); 156 157 // Populates several fields of |this| with error-related information from the 158 // provided completed ConnectJob. Should only be called on ConnectJob failure. 159 void SetAdditionalErrorState(ConnectJob* connect_job); 160 set_reuse_type(SocketReuseType reuse_type)161 void set_reuse_type(SocketReuseType reuse_type) { reuse_type_ = reuse_type; } set_idle_time(base::TimeDelta idle_time)162 void set_idle_time(base::TimeDelta idle_time) { idle_time_ = idle_time; } set_group_generation(int64_t group_generation)163 void set_group_generation(int64_t group_generation) { 164 group_generation_ = group_generation; 165 } set_is_ssl_error(bool is_ssl_error)166 void set_is_ssl_error(bool is_ssl_error) { is_ssl_error_ = is_ssl_error; } set_ssl_cert_request_info(scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info)167 void set_ssl_cert_request_info( 168 scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info) { 169 ssl_cert_request_info_ = std::move(ssl_cert_request_info); 170 } set_connection_attempts(const ConnectionAttempts & attempts)171 void set_connection_attempts(const ConnectionAttempts& attempts) { 172 connection_attempts_ = attempts; 173 } resolve_error_info()174 ResolveErrorInfo resolve_error_info() const { return resolve_error_info_; } 175 176 // Only valid if there is no |socket_|. is_ssl_error()177 bool is_ssl_error() const { 178 DCHECK(!socket_); 179 return is_ssl_error_; 180 } 181 182 // On an ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, the |cert_request_info| field 183 // is set. ssl_cert_request_info()184 scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info() const { 185 return ssl_cert_request_info_; 186 } 187 188 // If the connection failed, returns the connection attempts made. connection_attempts()189 const ConnectionAttempts& connection_attempts() { 190 return connection_attempts_; 191 } 192 socket()193 StreamSocket* socket() { return socket_.get(); } 194 195 // SetSocket() must be called with a new socket before this handle 196 // is destroyed if is_initialized() is true. 197 std::unique_ptr<StreamSocket> PassSocket(); 198 199 // These may only be used if is_initialized() is true. group_id()200 const ClientSocketPool::GroupId& group_id() const { return group_id_; } group_generation()201 int64_t group_generation() const { return group_generation_; } is_reused()202 bool is_reused() const { return reuse_type_ == REUSED_IDLE; } idle_time()203 base::TimeDelta idle_time() const { return idle_time_; } reuse_type()204 SocketReuseType reuse_type() const { return reuse_type_; } connect_timing()205 const LoadTimingInfo::ConnectTiming& connect_timing() const { 206 return connect_timing_; 207 } set_connect_timing(const LoadTimingInfo::ConnectTiming & connect_timing)208 void set_connect_timing(const LoadTimingInfo::ConnectTiming& connect_timing) { 209 connect_timing_ = connect_timing; 210 } 211 212 private: 213 // Called on asynchronous completion of an Init() request. 214 void OnIOComplete(int result); 215 216 // Called on completion (both asynchronous & synchronous) of an Init() 217 // request. 218 void HandleInitCompletion(int result); 219 220 // Resets the state of the ClientSocketHandle. |cancel| indicates whether or 221 // not to try to cancel the request with the ClientSocketPool. Does not 222 // reset the supplemental error state. |cancel_connect_job| indicates whether 223 // a pending ConnectJob, if there is one in the SocketPool, should be 224 // cancelled in addition to cancelling the request. It may only be true if 225 // |cancel| is also true. 226 void ResetInternal(bool cancel, bool cancel_connect_job); 227 228 // Resets the supplemental error state. 229 void ResetErrorState(); 230 231 bool is_initialized_ = false; 232 raw_ptr<ClientSocketPool> pool_ = nullptr; 233 raw_ptr<HigherLayeredPool> higher_pool_ = nullptr; 234 std::unique_ptr<StreamSocket> socket_; 235 ClientSocketPool::GroupId group_id_; 236 SocketReuseType reuse_type_ = ClientSocketHandle::UNUSED; 237 CompletionOnceCallback callback_; 238 base::TimeDelta idle_time_; 239 // See ClientSocketPool::ReleaseSocket() for an explanation. 240 int64_t group_generation_ = -1; 241 ResolveErrorInfo resolve_error_info_; 242 bool is_ssl_error_ = false; 243 scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_; 244 std::vector<ConnectionAttempt> connection_attempts_; 245 246 NetLogSource requesting_source_; 247 248 // Timing information is set when a connection is successfully established. 249 LoadTimingInfo::ConnectTiming connect_timing_; 250 }; 251 252 } // namespace net 253 254 #endif // NET_SOCKET_CLIENT_SOCKET_HANDLE_H_ 255