1// Copyright (c) 2011 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#pragma once
8
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/time.h"
15#include "base/timer.h"
16#include "net/base/host_port_pair.h"
17#include "net/base/host_resolver.h"
18#include "net/socket/client_socket_pool_base.h"
19#include "net/socket/client_socket_pool_histograms.h"
20#include "net/socket/client_socket_pool.h"
21
22namespace net {
23
24class ClientSocketFactory;
25
26class TransportSocketParams : public base::RefCounted<TransportSocketParams> {
27 public:
28  TransportSocketParams(const HostPortPair& host_port_pair,
29                        RequestPriority priority,
30                        const GURL& referrer,
31                        bool disable_resolver_cache,
32                        bool ignore_limits);
33
34  const HostResolver::RequestInfo& destination() const { return destination_; }
35  bool ignore_limits() const { return ignore_limits_; }
36#ifdef ANDROID
37  // Gets the UID of the calling process
38  bool getUID(uid_t *uid) const;
39  void setUID(uid_t uid);
40#endif
41
42 private:
43  friend class base::RefCounted<TransportSocketParams>;
44  ~TransportSocketParams();
45
46  void Initialize(RequestPriority priority, const GURL& referrer,
47                  bool disable_resolver_cache);
48
49  HostResolver::RequestInfo destination_;
50  bool ignore_limits_;
51#ifdef ANDROID
52  // Gets the UID of the calling process
53  bool valid_uid_;
54  int calling_uid_;
55#endif
56  DISALLOW_COPY_AND_ASSIGN(TransportSocketParams);
57};
58
59// TransportConnectJob handles the host resolution necessary for socket creation
60// and the transport (likely TCP) connect. TransportConnectJob also has fallback
61// logic for IPv6 connect() timeouts (which may happen due to networks / routers
62// with broken IPv6 support). Those timeouts take 20s, so rather than make the
63// user wait 20s for the timeout to fire, we use a fallback timer
64// (kIPv6FallbackTimerInMs) and start a connect() to a IPv4 address if the timer
65// fires. Then we race the IPv4 connect() against the IPv6 connect() (which has
66// a headstart) and return the one that completes first to the socket pool.
67class TransportConnectJob : public ConnectJob {
68 public:
69  TransportConnectJob(const std::string& group_name,
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;
80
81  // Makes |addrlist| start with an IPv4 address if |addrlist| contains any
82  // IPv4 address.
83  //
84  // WARNING: this method should only be used to implement the prefer-IPv4
85  // hack.  It is a public method for the unit tests.
86  static void MakeAddrListStartWithIPv4(AddressList* addrlist);
87
88  static const int kIPv6FallbackTimerInMs;
89
90 private:
91  enum State {
92    STATE_RESOLVE_HOST,
93    STATE_RESOLVE_HOST_COMPLETE,
94    STATE_TRANSPORT_CONNECT,
95    STATE_TRANSPORT_CONNECT_COMPLETE,
96    STATE_NONE,
97  };
98
99  void OnIOComplete(int result);
100
101  // Runs the state transition loop.
102  int DoLoop(int result);
103
104  int DoResolveHost();
105  int DoResolveHostComplete(int result);
106  int DoTransportConnect();
107  int DoTransportConnectComplete(int result);
108
109  // Not part of the state machine.
110  void DoIPv6FallbackTransportConnect();
111  void DoIPv6FallbackTransportConnectComplete(int result);
112
113  // Begins the host resolution and the TCP connect.  Returns OK on success
114  // and ERR_IO_PENDING if it cannot immediately service the request.
115  // Otherwise, it returns a net error code.
116  virtual int ConnectInternal();
117
118  scoped_refptr<TransportSocketParams> params_;
119  ClientSocketFactory* const client_socket_factory_;
120  CompletionCallbackImpl<TransportConnectJob> callback_;
121  SingleRequestHostResolver resolver_;
122  AddressList addresses_;
123  State next_state_;
124
125  // The time Connect() was called.
126  base::TimeTicks start_time_;
127
128  // The time the connect was started (after DNS finished).
129  base::TimeTicks connect_start_time_;
130
131  scoped_ptr<ClientSocket> transport_socket_;
132
133  scoped_ptr<ClientSocket> fallback_transport_socket_;
134  scoped_ptr<AddressList> fallback_addresses_;
135  CompletionCallbackImpl<TransportConnectJob> fallback_callback_;
136  base::TimeTicks fallback_connect_start_time_;
137  base::OneShotTimer<TransportConnectJob> fallback_timer_;
138
139  DISALLOW_COPY_AND_ASSIGN(TransportConnectJob);
140};
141
142class TransportClientSocketPool : public ClientSocketPool {
143 public:
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 methods:
155
156  virtual int RequestSocket(const std::string& group_name,
157                            const void* resolve_info,
158                            RequestPriority priority,
159                            ClientSocketHandle* handle,
160                            CompletionCallback* callback,
161                            const BoundNetLog& net_log);
162
163  virtual void RequestSockets(const std::string& group_name,
164                              const void* params,
165                              int num_sockets,
166                              const BoundNetLog& net_log);
167
168  virtual void CancelRequest(const std::string& group_name,
169                             ClientSocketHandle* handle);
170
171  virtual void ReleaseSocket(const std::string& group_name,
172                             ClientSocket* socket,
173                             int id);
174
175  virtual void Flush();
176
177  virtual void CloseIdleSockets();
178
179  virtual int IdleSocketCount() const;
180
181  virtual int IdleSocketCountInGroup(const std::string& group_name) const;
182
183  virtual LoadState GetLoadState(const std::string& group_name,
184                                 const ClientSocketHandle* handle) const;
185
186  virtual DictionaryValue* GetInfoAsValue(const std::string& name,
187                                          const std::string& type,
188                                          bool include_nested_pools) const;
189
190  virtual base::TimeDelta ConnectionTimeout() const;
191
192  virtual ClientSocketPoolHistograms* histograms() const;
193
194 private:
195  typedef ClientSocketPoolBase<TransportSocketParams> PoolBase;
196
197  class TransportConnectJobFactory
198      : public PoolBase::ConnectJobFactory {
199   public:
200    TransportConnectJobFactory(ClientSocketFactory* client_socket_factory,
201                         HostResolver* host_resolver,
202                         NetLog* net_log)
203        : client_socket_factory_(client_socket_factory),
204          host_resolver_(host_resolver),
205          net_log_(net_log) {}
206
207    virtual ~TransportConnectJobFactory() {}
208
209    // ClientSocketPoolBase::ConnectJobFactory methods.
210
211    virtual ConnectJob* NewConnectJob(
212        const std::string& group_name,
213        const PoolBase::Request& request,
214        ConnectJob::Delegate* delegate) const;
215
216    virtual base::TimeDelta ConnectionTimeout() const;
217
218   private:
219    ClientSocketFactory* const client_socket_factory_;
220    HostResolver* const host_resolver_;
221    NetLog* net_log_;
222
223    DISALLOW_COPY_AND_ASSIGN(TransportConnectJobFactory);
224  };
225
226  PoolBase base_;
227
228  DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPool);
229};
230
231REGISTER_SOCKET_PARAMS_FOR_POOL(TransportClientSocketPool,
232                                TransportSocketParams);
233
234}  // namespace net
235
236#endif  // NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_
237