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