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/time/time.h" 14 #include "base/timer/timer.h" 15 #include "net/base/host_port_pair.h" 16 #include "net/dns/host_resolver.h" 17 #include "net/dns/single_request_host_resolver.h" 18 #include "net/socket/client_socket_pool.h" 19 #include "net/socket/client_socket_pool_base.h" 20 #include "net/socket/client_socket_pool_histograms.h" 21 22 namespace net { 23 24 class ClientSocketFactory; 25 26 typedef base::Callback<int(const AddressList&, const BoundNetLog& net_log)> 27 OnHostResolutionCallback; 28 29 class NET_EXPORT_PRIVATE TransportSocketParams 30 : public base::RefCounted<TransportSocketParams> { 31 public: 32 // |host_resolution_callback| will be invoked after the the hostname is 33 // resolved. If |host_resolution_callback| does not return OK, then the 34 // connection will be aborted with that value. 35 TransportSocketParams( 36 const HostPortPair& host_port_pair, 37 bool disable_resolver_cache, 38 bool ignore_limits, 39 const OnHostResolutionCallback& host_resolution_callback); 40 41 const HostResolver::RequestInfo& destination() const { return destination_; } 42 bool ignore_limits() const { return ignore_limits_; } 43 const OnHostResolutionCallback& host_resolution_callback() const { 44 return host_resolution_callback_; 45 } 46 47 private: 48 friend class base::RefCounted<TransportSocketParams>; 49 ~TransportSocketParams(); 50 51 HostResolver::RequestInfo destination_; 52 bool ignore_limits_; 53 const OnHostResolutionCallback host_resolution_callback_; 54 55 DISALLOW_COPY_AND_ASSIGN(TransportSocketParams); 56 }; 57 58 // TransportConnectJob handles the host resolution necessary for socket creation 59 // and the transport (likely TCP) connect. TransportConnectJob also has fallback 60 // logic for IPv6 connect() timeouts (which may happen due to networks / routers 61 // with broken IPv6 support). Those timeouts take 20s, so rather than make the 62 // user wait 20s for the timeout to fire, we use a fallback timer 63 // (kIPv6FallbackTimerInMs) and start a connect() to a IPv4 address if the timer 64 // fires. Then we race the IPv4 connect() against the IPv6 connect() (which has 65 // a headstart) and return the one that completes first to the socket pool. 66 class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob { 67 public: 68 TransportConnectJob(const std::string& group_name, 69 RequestPriority priority, 70 const scoped_refptr<TransportSocketParams>& params, 71 base::TimeDelta timeout_duration, 72 ClientSocketFactory* client_socket_factory, 73 HostResolver* host_resolver, 74 Delegate* delegate, 75 NetLog* net_log); 76 virtual ~TransportConnectJob(); 77 78 // ConnectJob methods. 79 virtual LoadState GetLoadState() const OVERRIDE; 80 81 // Rolls |addrlist| forward until the first IPv4 address, if any. 82 // WARNING: this method should only be used to implement the prefer-IPv4 hack. 83 static void MakeAddressListStartWithIPv4(AddressList* addrlist); 84 85 static const int kIPv6FallbackTimerInMs; 86 87 private: 88 enum State { 89 STATE_RESOLVE_HOST, 90 STATE_RESOLVE_HOST_COMPLETE, 91 STATE_TRANSPORT_CONNECT, 92 STATE_TRANSPORT_CONNECT_COMPLETE, 93 STATE_NONE, 94 }; 95 96 enum ConnectInterval { 97 CONNECT_INTERVAL_LE_10MS, 98 CONNECT_INTERVAL_LE_20MS, 99 CONNECT_INTERVAL_GT_20MS, 100 }; 101 102 void OnIOComplete(int result); 103 104 // Runs the state transition loop. 105 int DoLoop(int result); 106 107 int DoResolveHost(); 108 int DoResolveHostComplete(int result); 109 int DoTransportConnect(); 110 int DoTransportConnectComplete(int result); 111 112 // Not part of the state machine. 113 void DoIPv6FallbackTransportConnect(); 114 void DoIPv6FallbackTransportConnectComplete(int result); 115 116 // Begins the host resolution and the TCP connect. Returns OK on success 117 // and ERR_IO_PENDING if it cannot immediately service the request. 118 // Otherwise, it returns a net error code. 119 virtual int ConnectInternal() OVERRIDE; 120 121 scoped_refptr<TransportSocketParams> params_; 122 ClientSocketFactory* const client_socket_factory_; 123 SingleRequestHostResolver resolver_; 124 AddressList addresses_; 125 State next_state_; 126 127 scoped_ptr<StreamSocket> transport_socket_; 128 129 scoped_ptr<StreamSocket> fallback_transport_socket_; 130 scoped_ptr<AddressList> fallback_addresses_; 131 base::TimeTicks fallback_connect_start_time_; 132 base::OneShotTimer<TransportConnectJob> fallback_timer_; 133 134 // Track the interval between this connect and previous connect. 135 ConnectInterval interval_between_connects_; 136 137 DISALLOW_COPY_AND_ASSIGN(TransportConnectJob); 138 }; 139 140 class NET_EXPORT_PRIVATE TransportClientSocketPool : public ClientSocketPool { 141 public: 142 typedef TransportSocketParams SocketParams; 143 144 TransportClientSocketPool( 145 int max_sockets, 146 int max_sockets_per_group, 147 ClientSocketPoolHistograms* histograms, 148 HostResolver* host_resolver, 149 ClientSocketFactory* client_socket_factory, 150 NetLog* net_log); 151 152 virtual ~TransportClientSocketPool(); 153 154 // ClientSocketPool implementation. 155 virtual int RequestSocket(const std::string& group_name, 156 const void* resolve_info, 157 RequestPriority priority, 158 ClientSocketHandle* handle, 159 const CompletionCallback& callback, 160 const BoundNetLog& net_log) OVERRIDE; 161 virtual void RequestSockets(const std::string& group_name, 162 const void* params, 163 int num_sockets, 164 const BoundNetLog& net_log) OVERRIDE; 165 virtual void CancelRequest(const std::string& group_name, 166 ClientSocketHandle* handle) OVERRIDE; 167 virtual void ReleaseSocket(const std::string& group_name, 168 scoped_ptr<StreamSocket> socket, 169 int id) OVERRIDE; 170 virtual void FlushWithError(int error) OVERRIDE; 171 virtual void CloseIdleSockets() OVERRIDE; 172 virtual int IdleSocketCount() const OVERRIDE; 173 virtual int IdleSocketCountInGroup( 174 const std::string& group_name) const OVERRIDE; 175 virtual LoadState GetLoadState( 176 const std::string& group_name, 177 const ClientSocketHandle* handle) const OVERRIDE; 178 virtual base::DictionaryValue* GetInfoAsValue( 179 const std::string& name, 180 const std::string& type, 181 bool include_nested_pools) const OVERRIDE; 182 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE; 183 virtual ClientSocketPoolHistograms* histograms() const OVERRIDE; 184 185 // HigherLayeredPool implementation. 186 virtual bool IsStalled() const OVERRIDE; 187 virtual void AddHigherLayeredPool(HigherLayeredPool* higher_pool) OVERRIDE; 188 virtual void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) OVERRIDE; 189 190 private: 191 typedef ClientSocketPoolBase<TransportSocketParams> PoolBase; 192 193 class TransportConnectJobFactory 194 : public PoolBase::ConnectJobFactory { 195 public: 196 TransportConnectJobFactory(ClientSocketFactory* client_socket_factory, 197 HostResolver* host_resolver, 198 NetLog* net_log) 199 : client_socket_factory_(client_socket_factory), 200 host_resolver_(host_resolver), 201 net_log_(net_log) {} 202 203 virtual ~TransportConnectJobFactory() {} 204 205 // ClientSocketPoolBase::ConnectJobFactory methods. 206 207 virtual scoped_ptr<ConnectJob> NewConnectJob( 208 const std::string& group_name, 209 const PoolBase::Request& request, 210 ConnectJob::Delegate* delegate) const OVERRIDE; 211 212 virtual base::TimeDelta ConnectionTimeout() const OVERRIDE; 213 214 private: 215 ClientSocketFactory* const client_socket_factory_; 216 HostResolver* const host_resolver_; 217 NetLog* net_log_; 218 219 DISALLOW_COPY_AND_ASSIGN(TransportConnectJobFactory); 220 }; 221 222 PoolBase base_; 223 224 DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPool); 225 }; 226 227 } // namespace net 228 229 #endif // NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ 230