| OLD | NEW |
| (Empty) |
| 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 | |
| 5 #ifndef NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
| 6 #define NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
| 7 | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/memory/ref_counted.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/profiler/scoped_tracker.h" | |
| 14 #include "base/time/time.h" | |
| 15 #include "base/timer/timer.h" | |
| 16 #include "net/base/host_port_pair.h" | |
| 17 #include "net/dns/host_resolver.h" | |
| 18 #include "net/dns/single_request_host_resolver.h" | |
| 19 #include "net/socket/client_socket_pool.h" | |
| 20 #include "net/socket/client_socket_pool_base.h" | |
| 21 #include "net/socket/client_socket_pool_histograms.h" | |
| 22 | |
| 23 namespace net { | |
| 24 | |
| 25 class ClientSocketFactory; | |
| 26 | |
| 27 typedef base::Callback<int(const AddressList&, const BoundNetLog& net_log)> | |
| 28 OnHostResolutionCallback; | |
| 29 | |
| 30 class NET_EXPORT_PRIVATE TransportSocketParams | |
| 31 : public base::RefCounted<TransportSocketParams> { | |
| 32 public: | |
| 33 // CombineConnectAndWrite currently translates to using TCP FastOpen. | |
| 34 // TCP FastOpen should not be used if the first write to the socket may | |
| 35 // be non-idempotent, as the underlying socket could retransmit the data | |
| 36 // on failure of the first transmission. | |
| 37 // NOTE: Currently, COMBINE_CONNECT_AND_WRITE_DESIRED is used if the data in | |
| 38 // the write is known to be idempotent, and COMBINE_CONNECT_AND_WRITE_DEFAULT | |
| 39 // is used as a default for other cases (including non-idempotent writes). | |
| 40 enum CombineConnectAndWritePolicy { | |
| 41 COMBINE_CONNECT_AND_WRITE_DEFAULT, // Default policy, implemented in | |
| 42 // TransportSocketParams constructor. | |
| 43 COMBINE_CONNECT_AND_WRITE_DESIRED, // Combine if supported by socket. | |
| 44 COMBINE_CONNECT_AND_WRITE_PROHIBITED // Do not combine. | |
| 45 }; | |
| 46 | |
| 47 // |host_resolution_callback| will be invoked after the the hostname is | |
| 48 // resolved. If |host_resolution_callback| does not return OK, then the | |
| 49 // connection will be aborted with that value. |combine_connect_and_write| | |
| 50 // defines the policy for use of TCP FastOpen on this socket. | |
| 51 TransportSocketParams( | |
| 52 const HostPortPair& host_port_pair, | |
| 53 bool disable_resolver_cache, | |
| 54 bool ignore_limits, | |
| 55 const OnHostResolutionCallback& host_resolution_callback, | |
| 56 CombineConnectAndWritePolicy combine_connect_and_write); | |
| 57 | |
| 58 const HostResolver::RequestInfo& destination() const { return destination_; } | |
| 59 bool ignore_limits() const { return ignore_limits_; } | |
| 60 const OnHostResolutionCallback& host_resolution_callback() const { | |
| 61 return host_resolution_callback_; | |
| 62 } | |
| 63 | |
| 64 CombineConnectAndWritePolicy combine_connect_and_write() const { | |
| 65 return combine_connect_and_write_; | |
| 66 } | |
| 67 | |
| 68 private: | |
| 69 friend class base::RefCounted<TransportSocketParams>; | |
| 70 ~TransportSocketParams(); | |
| 71 | |
| 72 HostResolver::RequestInfo destination_; | |
| 73 bool ignore_limits_; | |
| 74 const OnHostResolutionCallback host_resolution_callback_; | |
| 75 CombineConnectAndWritePolicy combine_connect_and_write_; | |
| 76 | |
| 77 DISALLOW_COPY_AND_ASSIGN(TransportSocketParams); | |
| 78 }; | |
| 79 | |
| 80 // Common data and logic shared between TransportConnectJob and | |
| 81 // WebSocketTransportConnectJob. | |
| 82 class NET_EXPORT_PRIVATE TransportConnectJobHelper { | |
| 83 public: | |
| 84 enum State { | |
| 85 STATE_RESOLVE_HOST, | |
| 86 STATE_RESOLVE_HOST_COMPLETE, | |
| 87 STATE_TRANSPORT_CONNECT, | |
| 88 STATE_TRANSPORT_CONNECT_COMPLETE, | |
| 89 STATE_NONE, | |
| 90 }; | |
| 91 | |
| 92 // For recording the connection time in the appropriate bucket. | |
| 93 enum ConnectionLatencyHistogram { | |
| 94 CONNECTION_LATENCY_UNKNOWN, | |
| 95 CONNECTION_LATENCY_IPV4_WINS_RACE, | |
| 96 CONNECTION_LATENCY_IPV4_NO_RACE, | |
| 97 CONNECTION_LATENCY_IPV6_RACEABLE, | |
| 98 CONNECTION_LATENCY_IPV6_SOLO, | |
| 99 }; | |
| 100 | |
| 101 TransportConnectJobHelper(const scoped_refptr<TransportSocketParams>& params, | |
| 102 ClientSocketFactory* client_socket_factory, | |
| 103 HostResolver* host_resolver, | |
| 104 LoadTimingInfo::ConnectTiming* connect_timing); | |
| 105 ~TransportConnectJobHelper(); | |
| 106 | |
| 107 ClientSocketFactory* client_socket_factory() { | |
| 108 return client_socket_factory_; | |
| 109 } | |
| 110 | |
| 111 const AddressList& addresses() const { return addresses_; } | |
| 112 State next_state() const { return next_state_; } | |
| 113 void set_next_state(State next_state) { next_state_ = next_state; } | |
| 114 CompletionCallback on_io_complete() const { return on_io_complete_; } | |
| 115 const TransportSocketParams* params() { return params_.get(); } | |
| 116 | |
| 117 int DoResolveHost(RequestPriority priority, const BoundNetLog& net_log); | |
| 118 int DoResolveHostComplete(int result, const BoundNetLog& net_log); | |
| 119 | |
| 120 template <class T> | |
| 121 int DoConnectInternal(T* job); | |
| 122 | |
| 123 template <class T> | |
| 124 void SetOnIOComplete(T* job); | |
| 125 | |
| 126 template <class T> | |
| 127 void OnIOComplete(T* job, int result); | |
| 128 | |
| 129 // Record the histograms Net.DNS_Resolution_And_TCP_Connection_Latency2 and | |
| 130 // Net.TCP_Connection_Latency and return the connect duration. | |
| 131 base::TimeDelta HistogramDuration(ConnectionLatencyHistogram race_result); | |
| 132 | |
| 133 static const int kIPv6FallbackTimerInMs; | |
| 134 | |
| 135 private: | |
| 136 template <class T> | |
| 137 int DoLoop(T* job, int result); | |
| 138 | |
| 139 scoped_refptr<TransportSocketParams> params_; | |
| 140 ClientSocketFactory* const client_socket_factory_; | |
| 141 SingleRequestHostResolver resolver_; | |
| 142 AddressList addresses_; | |
| 143 State next_state_; | |
| 144 CompletionCallback on_io_complete_; | |
| 145 LoadTimingInfo::ConnectTiming* connect_timing_; | |
| 146 | |
| 147 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobHelper); | |
| 148 }; | |
| 149 | |
| 150 // TransportConnectJob handles the host resolution necessary for socket creation | |
| 151 // and the transport (likely TCP) connect. TransportConnectJob also has fallback | |
| 152 // logic for IPv6 connect() timeouts (which may happen due to networks / routers | |
| 153 // with broken IPv6 support). Those timeouts take 20s, so rather than make the | |
| 154 // user wait 20s for the timeout to fire, we use a fallback timer | |
| 155 // (kIPv6FallbackTimerInMs) and start a connect() to a IPv4 address if the timer | |
| 156 // fires. Then we race the IPv4 connect() against the IPv6 connect() (which has | |
| 157 // a headstart) and return the one that completes first to the socket pool. | |
| 158 class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob { | |
| 159 public: | |
| 160 TransportConnectJob(const std::string& group_name, | |
| 161 RequestPriority priority, | |
| 162 const scoped_refptr<TransportSocketParams>& params, | |
| 163 base::TimeDelta timeout_duration, | |
| 164 ClientSocketFactory* client_socket_factory, | |
| 165 HostResolver* host_resolver, | |
| 166 Delegate* delegate, | |
| 167 NetLog* net_log); | |
| 168 ~TransportConnectJob() override; | |
| 169 | |
| 170 // ConnectJob methods. | |
| 171 LoadState GetLoadState() const override; | |
| 172 | |
| 173 // Rolls |addrlist| forward until the first IPv4 address, if any. | |
| 174 // WARNING: this method should only be used to implement the prefer-IPv4 hack. | |
| 175 static void MakeAddressListStartWithIPv4(AddressList* addrlist); | |
| 176 | |
| 177 private: | |
| 178 enum ConnectInterval { | |
| 179 CONNECT_INTERVAL_LE_10MS, | |
| 180 CONNECT_INTERVAL_LE_20MS, | |
| 181 CONNECT_INTERVAL_GT_20MS, | |
| 182 }; | |
| 183 | |
| 184 friend class TransportConnectJobHelper; | |
| 185 | |
| 186 int DoResolveHost(); | |
| 187 int DoResolveHostComplete(int result); | |
| 188 int DoTransportConnect(); | |
| 189 int DoTransportConnectComplete(int result); | |
| 190 | |
| 191 // Not part of the state machine. | |
| 192 void DoIPv6FallbackTransportConnect(); | |
| 193 void DoIPv6FallbackTransportConnectComplete(int result); | |
| 194 | |
| 195 // Begins the host resolution and the TCP connect. Returns OK on success | |
| 196 // and ERR_IO_PENDING if it cannot immediately service the request. | |
| 197 // Otherwise, it returns a net error code. | |
| 198 int ConnectInternal() override; | |
| 199 | |
| 200 TransportConnectJobHelper helper_; | |
| 201 | |
| 202 scoped_ptr<StreamSocket> transport_socket_; | |
| 203 | |
| 204 scoped_ptr<StreamSocket> fallback_transport_socket_; | |
| 205 scoped_ptr<AddressList> fallback_addresses_; | |
| 206 base::TimeTicks fallback_connect_start_time_; | |
| 207 base::OneShotTimer<TransportConnectJob> fallback_timer_; | |
| 208 | |
| 209 // Track the interval between this connect and previous connect. | |
| 210 ConnectInterval interval_between_connects_; | |
| 211 | |
| 212 DISALLOW_COPY_AND_ASSIGN(TransportConnectJob); | |
| 213 }; | |
| 214 | |
| 215 class NET_EXPORT_PRIVATE TransportClientSocketPool : public ClientSocketPool { | |
| 216 public: | |
| 217 typedef TransportSocketParams SocketParams; | |
| 218 | |
| 219 TransportClientSocketPool( | |
| 220 int max_sockets, | |
| 221 int max_sockets_per_group, | |
| 222 ClientSocketPoolHistograms* histograms, | |
| 223 HostResolver* host_resolver, | |
| 224 ClientSocketFactory* client_socket_factory, | |
| 225 NetLog* net_log); | |
| 226 | |
| 227 ~TransportClientSocketPool() override; | |
| 228 | |
| 229 // ClientSocketPool implementation. | |
| 230 int RequestSocket(const std::string& group_name, | |
| 231 const void* resolve_info, | |
| 232 RequestPriority priority, | |
| 233 ClientSocketHandle* handle, | |
| 234 const CompletionCallback& callback, | |
| 235 const BoundNetLog& net_log) override; | |
| 236 void RequestSockets(const std::string& group_name, | |
| 237 const void* params, | |
| 238 int num_sockets, | |
| 239 const BoundNetLog& net_log) override; | |
| 240 void CancelRequest(const std::string& group_name, | |
| 241 ClientSocketHandle* handle) override; | |
| 242 void ReleaseSocket(const std::string& group_name, | |
| 243 scoped_ptr<StreamSocket> socket, | |
| 244 int id) override; | |
| 245 void FlushWithError(int error) override; | |
| 246 void CloseIdleSockets() override; | |
| 247 int IdleSocketCount() const override; | |
| 248 int IdleSocketCountInGroup(const std::string& group_name) const override; | |
| 249 LoadState GetLoadState(const std::string& group_name, | |
| 250 const ClientSocketHandle* handle) const override; | |
| 251 base::DictionaryValue* GetInfoAsValue( | |
| 252 const std::string& name, | |
| 253 const std::string& type, | |
| 254 bool include_nested_pools) const override; | |
| 255 base::TimeDelta ConnectionTimeout() const override; | |
| 256 ClientSocketPoolHistograms* histograms() const override; | |
| 257 | |
| 258 // HigherLayeredPool implementation. | |
| 259 bool IsStalled() const override; | |
| 260 void AddHigherLayeredPool(HigherLayeredPool* higher_pool) override; | |
| 261 void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) override; | |
| 262 | |
| 263 protected: | |
| 264 // Methods shared with WebSocketTransportClientSocketPool | |
| 265 void NetLogTcpClientSocketPoolRequestedSocket( | |
| 266 const BoundNetLog& net_log, | |
| 267 const scoped_refptr<TransportSocketParams>* casted_params); | |
| 268 | |
| 269 private: | |
| 270 typedef ClientSocketPoolBase<TransportSocketParams> PoolBase; | |
| 271 | |
| 272 class TransportConnectJobFactory | |
| 273 : public PoolBase::ConnectJobFactory { | |
| 274 public: | |
| 275 TransportConnectJobFactory(ClientSocketFactory* client_socket_factory, | |
| 276 HostResolver* host_resolver, | |
| 277 NetLog* net_log) | |
| 278 : client_socket_factory_(client_socket_factory), | |
| 279 host_resolver_(host_resolver), | |
| 280 net_log_(net_log) {} | |
| 281 | |
| 282 ~TransportConnectJobFactory() override {} | |
| 283 | |
| 284 // ClientSocketPoolBase::ConnectJobFactory methods. | |
| 285 | |
| 286 scoped_ptr<ConnectJob> NewConnectJob( | |
| 287 const std::string& group_name, | |
| 288 const PoolBase::Request& request, | |
| 289 ConnectJob::Delegate* delegate) const override; | |
| 290 | |
| 291 base::TimeDelta ConnectionTimeout() const override; | |
| 292 | |
| 293 private: | |
| 294 ClientSocketFactory* const client_socket_factory_; | |
| 295 HostResolver* const host_resolver_; | |
| 296 NetLog* net_log_; | |
| 297 | |
| 298 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobFactory); | |
| 299 }; | |
| 300 | |
| 301 PoolBase base_; | |
| 302 | |
| 303 DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPool); | |
| 304 }; | |
| 305 | |
| 306 template <class T> | |
| 307 int TransportConnectJobHelper::DoConnectInternal(T* job) { | |
| 308 next_state_ = STATE_RESOLVE_HOST; | |
| 309 return this->DoLoop(job, OK); | |
| 310 } | |
| 311 | |
| 312 template <class T> | |
| 313 void TransportConnectJobHelper::SetOnIOComplete(T* job) { | |
| 314 // These usages of base::Unretained() are safe because IO callbacks are | |
| 315 // guaranteed not to be called after the object is destroyed. | |
| 316 on_io_complete_ = base::Bind(&TransportConnectJobHelper::OnIOComplete<T>, | |
| 317 base::Unretained(this), | |
| 318 base::Unretained(job)); | |
| 319 } | |
| 320 | |
| 321 template <class T> | |
| 322 void TransportConnectJobHelper::OnIOComplete(T* job, int result) { | |
| 323 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 324 tracked_objects::ScopedTracker tracking_profile( | |
| 325 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 326 "436634 TransportConnectJobHelper::OnIOComplete")); | |
| 327 | |
| 328 result = this->DoLoop(job, result); | |
| 329 | |
| 330 // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. | |
| 331 tracked_objects::ScopedTracker tracking_profile1( | |
| 332 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 333 "436634 TransportConnectJobHelper::OnIOComplete1")); | |
| 334 | |
| 335 if (result != ERR_IO_PENDING) | |
| 336 job->NotifyDelegateOfCompletion(result); // Deletes |job| and |this| | |
| 337 } | |
| 338 | |
| 339 template <class T> | |
| 340 int TransportConnectJobHelper::DoLoop(T* job, int result) { | |
| 341 DCHECK_NE(next_state_, STATE_NONE); | |
| 342 | |
| 343 int rv = result; | |
| 344 do { | |
| 345 State state = next_state_; | |
| 346 next_state_ = STATE_NONE; | |
| 347 switch (state) { | |
| 348 case STATE_RESOLVE_HOST: | |
| 349 DCHECK_EQ(OK, rv); | |
| 350 rv = job->DoResolveHost(); | |
| 351 break; | |
| 352 case STATE_RESOLVE_HOST_COMPLETE: | |
| 353 rv = job->DoResolveHostComplete(rv); | |
| 354 break; | |
| 355 case STATE_TRANSPORT_CONNECT: | |
| 356 DCHECK_EQ(OK, rv); | |
| 357 rv = job->DoTransportConnect(); | |
| 358 break; | |
| 359 case STATE_TRANSPORT_CONNECT_COMPLETE: | |
| 360 rv = job->DoTransportConnectComplete(rv); | |
| 361 break; | |
| 362 default: | |
| 363 NOTREACHED(); | |
| 364 rv = ERR_FAILED; | |
| 365 break; | |
| 366 } | |
| 367 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
| 368 | |
| 369 return rv; | |
| 370 } | |
| 371 | |
| 372 } // namespace net | |
| 373 | |
| 374 #endif // NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
| OLD | NEW |