Home | History | Annotate | Download | only in socket
      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