• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
destination()41   const HostResolver::RequestInfo& destination() const { return destination_; }
ignore_limits()42   bool ignore_limits() const { return ignore_limits_; }
host_resolution_callback()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:
TransportConnectJobFactory(ClientSocketFactory * client_socket_factory,HostResolver * host_resolver,NetLog * net_log)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 
~TransportConnectJobFactory()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