client_socket_pool_base.h revision e14dcc5a172cad1c4716af7ab94121a73c0c698e
1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A ClientSocketPoolBase is used to restrict the number of sockets open at
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// a time.  It also maintains a list of idle persistent sockets for reuse.
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the core logic of (1) restricting the number of active (connected or
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// connecting) sockets per "group" (generally speaking, the hostname), (2)
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// maintaining a per-group list of idle, persistent sockets for reuse, and (3)
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// limiting the total number of active sockets in the system.
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ClientSocketPoolBase abstracts socket connection details behind ConnectJob,
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ConnectJobFactory, and SocketParams.  When a socket "slot" becomes available,
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the ClientSocketPoolBase will ask the ConnectJobFactory to create a
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ConnectJob with a SocketParams.  Subclasses of ClientSocketPool should
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// implement their socket specific connection by subclassing ConnectJob and
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// implementing ConnectJob::ConnectInternal().  They can control the parameters
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// passed to each new ConnectJob instance via their ConnectJobFactory subclass
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and templated SocketParams parameter.
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <deque>
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <list>
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <map>
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <set>
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h"
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h"
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h"
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/address_list.h"
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/completion_callback.h"
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/load_states.h"
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h"
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/network_change_notifier.h"
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/request_priority.h"
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/client_socket.h"
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/client_socket_pool.h"
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ClientSocketHandle;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ConnectJob provides an abstract interface for "connecting" a socket.
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The connection may involve host resolution, tcp connection, ssl connection,
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// etc.
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ConnectJob {
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class Delegate {
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Delegate() {}
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ~Delegate() {}
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Alerts the delegate that the connection completed.
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(Delegate);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A |timeout_duration| of 0 corresponds to no timeout.
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ConnectJob(const std::string& group_name,
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             base::TimeDelta timeout_duration,
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             Delegate* delegate,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const BoundNetLog& net_log);
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~ConnectJob();
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Accessors
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string& group_name() const { return group_name_; }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BoundNetLog& net_log() { return net_log_; }
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool is_preconnect() const { return preconnect_state_ != NOT_PRECONNECT; }
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool is_unused_preconnect() const {
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return preconnect_state_ == UNUSED_PRECONNECT;
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Initialized by the ClientSocketPoolBaseHelper.
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(willchan): Move most of the constructor arguments over here.  We
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // shouldn't give the ConnectJobFactory (subclasses) the ability to screw up
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // the initialization.
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void Initialize(bool is_preconnect);
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Releases |socket_| to the client.  On connection error, this should return
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // NULL.
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocket* ReleaseSocket() { return socket_.release(); }
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Begins connecting the socket.  Returns OK on success, ERR_IO_PENDING if it
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // cannot complete synchronously without blocking, or another net error code
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // on error.  In asynchronous completion, the ConnectJob will notify
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |delegate_| via OnConnectJobComplete.  In both asynchronous and synchronous
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // completion, ReleaseSocket() can be called to acquire the connected socket
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // if it succeeded.
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int Connect();
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Precondition: is_unused_preconnect() must be true.  Marks the job as a
103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // used preconnect job.
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void UseForNormalRequest();
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual LoadState GetLoadState() const = 0;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If Connect returns an error (or OnConnectJobComplete reports an error
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // result) this method will be called, allowing the pool to add
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // additional error state to the ClientSocketHandle (post late-binding).
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {}
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const BoundNetLog& net_log() const { return net_log_; }
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void set_socket(ClientSocket* socket);
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocket* socket() { return socket_.get(); }
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void NotifyDelegateOfCompletion(int rv);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ResetTimer(base::TimeDelta remainingTime);
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  enum PreconnectState {
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NOT_PRECONNECT,
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    UNUSED_PRECONNECT,
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    USED_PRECONNECT,
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual int ConnectInternal() = 0;
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void LogConnectStart();
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void LogConnectCompletion(int net_error);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Alerts the delegate that the ConnectJob has timed out.
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnTimeout();
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string group_name_;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const base::TimeDelta timeout_duration_;
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Timer to abort jobs that take too long.
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::OneShotTimer<ConnectJob> timer_;
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Delegate* delegate_;
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<ClientSocket> socket_;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog net_log_;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A ConnectJob is idle until Connect() has been called.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool idle_;
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PreconnectState preconnect_state_;
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(ConnectJob);
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace internal {
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ClientSocketPoolBaseHelper is an internal class that implements almost all
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the functionality from ClientSocketPoolBase without using templates.
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ClientSocketPoolBase adds templated definitions built on top of
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ClientSocketPoolBaseHelper.  This class is not for external use, please use
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ClientSocketPoolBase instead.
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ClientSocketPoolBaseHelper
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : public ConnectJob::Delegate,
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      public NetworkChangeNotifier::IPAddressObserver {
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  typedef uint32 Flags;
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Used to specify specific behavior for the ClientSocketPool.
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  enum Flag {
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NORMAL = 0,  // Normal behavior.
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    NO_IDLE_SOCKETS = 0x1,  // Do not return an idle socket. Create a new one.
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class Request {
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Request(ClientSocketHandle* handle,
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            CompletionCallback* callback,
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            RequestPriority priority,
17421ae586050b3022a662bfe7743553d462ae4ced8Kristian Monsen            bool ignore_limits,
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            Flags flags,
176e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            const BoundNetLog& net_log
177e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
178e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            , bool valid_uid, uid_t calling_uid
179e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
180e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            );
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual ~Request();
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ClientSocketHandle* handle() const { return handle_; }
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CompletionCallback* callback() const { return callback_; }
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RequestPriority priority() const { return priority_; }
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bool ignore_limits() const { return ignore_limits_; }
188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Flags flags() const { return flags_; }
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BoundNetLog& net_log() const { return net_log_; }
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ClientSocketHandle* const handle_;
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CompletionCallback* const callback_;
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const RequestPriority priority_;
19521ae586050b3022a662bfe7743553d462ae4ced8Kristian Monsen    bool ignore_limits_;
196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const Flags flags_;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BoundNetLog net_log_;
198e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
199e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    bool valid_uid_;
200e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    uid_t calling_uid_;
201e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(Request);
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class ConnectJobFactory {
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ConnectJobFactory() {}
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ~ConnectJobFactory() {}
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ConnectJob* NewConnectJob(
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const std::string& group_name,
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const Request& request,
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConnectJob::Delegate* delegate) const = 0;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual base::TimeDelta ConnectionTimeout() const = 0;
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocketPoolBaseHelper(
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int max_sockets,
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int max_sockets_per_group,
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta unused_idle_socket_timeout,
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta used_idle_socket_timeout,
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConnectJobFactory* connect_job_factory);
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ~ClientSocketPoolBaseHelper();
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::RequestSocket for documentation on this function.
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ClientSocketPoolBaseHelper takes ownership of |request|, which must be
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // heap allocated.
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int RequestSocket(const std::string& group_name, const Request* request);
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // See ClientSocketPool::RequestSocket for documentation on this function.
237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void RequestSockets(const std::string& group_name,
238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      const Request& request,
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      int num_sockets);
240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::CancelRequest for documentation on this function.
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CancelRequest(const std::string& group_name,
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     ClientSocketHandle* handle);
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::ReleaseSocket for documentation on this function.
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ReleaseSocket(const std::string& group_name,
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     ClientSocket* socket,
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     int id);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See ClientSocketPool::Flush for documentation on this function.
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Flush();
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::CloseIdleSockets for documentation on this function.
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CloseIdleSockets();
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::IdleSocketCount() for documentation on this function.
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int idle_socket_count() const {
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return idle_socket_count_;
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // function.
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int IdleSocketCountInGroup(const std::string& group_name) const;
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // See ClientSocketPool::GetLoadState() for documentation on this function.
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadState GetLoadState(const std::string& group_name,
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         const ClientSocketHandle* handle) const;
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int ConnectRetryIntervalMs() const {
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(mbelshe): Make this tuned dynamically based on measured RTT.
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //                For now, just use the max retry interval.
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ClientSocketPool::kMaxConnectRetryIntervalMs;
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int NumConnectJobsInGroup(const std::string& group_name) const {
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return group_map_.find(group_name)->second->jobs().size();
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
279731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int NumActiveSocketsInGroup(const std::string& group_name) const {
280731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return group_map_.find(group_name)->second->active_socket_count();
281731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
282731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool HasGroup(const std::string& group_name) const;
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Closes all idle sockets if |force| is true.  Else, only closes idle
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sockets that timed out or can't be reused.  Made public for testing.
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CleanupIdleSockets(bool force);
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See ClientSocketPool::GetInfoAsValue for documentation on this function.
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DictionaryValue* GetInfoAsValue(const std::string& name,
2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  const std::string& type) const;
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::TimeDelta ConnectionTimeout() const {
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return connect_job_factory_->ConnectionTimeout();
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool connect_backup_jobs_enabled();
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool set_connect_backup_jobs_enabled(bool enabled);
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void EnableConnectBackupJobs();
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ConnectJob::Delegate methods:
30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OnConnectJobComplete(int result, ConnectJob* job);
30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // NetworkChangeNotifier::IPAddressObserver methods:
30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OnIPAddressChanged();
30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class base::RefCounted<ClientSocketPoolBaseHelper>;
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Entry for a persistent socket which became idle at time |start_time|.
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct IdleSocket {
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    IdleSocket() : socket(NULL) {}
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // An idle socket should be removed if it can't be reused, or has been idle
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // for too long. |now| is the current time value (TimeTicks::Now()).
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // |timeout| is the length of time to wait before timing out an idle socket.
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // An idle socket can't be reused if it is disconnected or has received
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // data unexpectedly (hence no longer idle).  The unread data would be
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // mistaken for the beginning of the next response if we were to reuse the
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // socket for a new request.
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ClientSocket* socket;
32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::TimeTicks start_time;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  typedef std::deque<const Request* > RequestQueue;
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A Group is allocated per group_name when there are idle sockets or pending
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // requests.  Otherwise, the Group object is removed from the map.
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |active_socket_count| tracks the number of sockets held by clients.
3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  class Group {
3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick   public:
3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Group();
3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ~Group();
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool IsEmpty() const {
3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return active_socket_count_ == 0 && idle_sockets_.empty() &&
3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          jobs_.empty() && pending_requests_.empty();
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool HasAvailableSocketSlot(int max_sockets_per_group) const {
346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return NumActiveSocketSlots() < max_sockets_per_group;
347731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
348731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
349731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int NumActiveSocketSlots() const {
350731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return active_socket_count_ + static_cast<int>(jobs_.size()) +
351731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          static_cast<int>(idle_sockets_.size());
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool IsStalled(int max_sockets_per_group) const {
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return HasAvailableSocketSlot(max_sockets_per_group) &&
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          pending_requests_.size() > jobs_.size();
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RequestPriority TopPendingPriority() const {
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return pending_requests_.front()->priority();
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool HasBackupJob() const { return !method_factory_.empty(); }
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void CleanupBackupJob() {
3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      method_factory_.RevokeAll();
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Set a timer to create a backup socket if it takes too long to create one.
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void StartBackupSocketTimer(const std::string& group_name,
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                ClientSocketPoolBaseHelper* pool);
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so,
374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // uses it.  Returns true on success.  Otherwise, returns false.
375731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool TryToUsePreconnectConnectJob();
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
377731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void AddJob(ConnectJob* job) { jobs_.insert(job); }
378731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void RemoveJob(ConnectJob* job) { jobs_.erase(job); }
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void RemoveAllJobs();
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void IncrementActiveSocketCount() { active_socket_count_++; }
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void DecrementActiveSocketCount() { active_socket_count_--; }
3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::set<ConnectJob*>& jobs() const { return jobs_; }
385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; }
3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const RequestQueue& pending_requests() const { return pending_requests_; }
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int active_socket_count() const { return active_socket_count_; }
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    RequestQueue* mutable_pending_requests() { return &pending_requests_; }
389731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; }
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick   private:
392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Called when the backup socket timer fires.
393731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void OnBackupSocketTimerFired(
394731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        std::string group_name,
395731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        ClientSocketPoolBaseHelper* pool);
396731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::list<IdleSocket> idle_sockets_;
398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::set<ConnectJob*> jobs_;
3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    RequestQueue pending_requests_;
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int active_socket_count_;  // number of active sockets used by clients
4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // A factory to pin the backup_job tasks.
4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ScopedRunnableMethodFactory<Group> method_factory_;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  typedef std::map<std::string, Group*> GroupMap;
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  typedef std::set<ConnectJob*> ConnectJobSet;
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct CallbackResultPair {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CallbackResultPair() : callback(NULL), result(OK) {}
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CallbackResultPair(CompletionCallback* callback_in, int result_in)
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : callback(callback_in), result(result_in) {}
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CompletionCallback* callback;
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int result;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::map<const ClientSocketHandle*, CallbackResultPair>
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PendingCallbackMap;
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void InsertRequestIntoQueue(const Request* r,
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     RequestQueue* pending_requests);
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const Request* RemoveRequestFromQueue(const RequestQueue::iterator& it,
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                               Group* group);
4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Group* GetOrCreateGroup(const std::string& group_name);
4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void RemoveGroup(const std::string& group_name);
4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void RemoveGroup(GroupMap::iterator it);
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called when the number of idle sockets changes.
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void IncrementIdleCount();
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void DecrementIdleCount();
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Scans the group map for groups which have an available socket slot and
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // at least one pending request. Returns true if any groups are stalled, and
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // if so, fills |group| and |group_name| with data of the stalled group
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // having highest priority.
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool FindTopStalledGroup(Group** group, std::string* group_name);
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called when timer_ fires.  This method scans the idle sockets removing
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sockets that timed out or can't be reused.
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnCleanupTimerFired() {
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CleanupIdleSockets(false);
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Removes |job| from |connect_job_set_|.  Also updates |group| if non-NULL.
447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void RemoveConnectJob(ConnectJob* job, Group* group);
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Tries to see if we can handle any more requests for |group|.
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnAvailableSocketSlot(const std::string& group_name, Group* group);
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Process a pending socket request for a group.
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ProcessPendingRequest(const std::string& group_name, Group* group);
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Assigns |socket| to |handle| and updates |group|'s counters appropriately.
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void HandOutSocket(ClientSocket* socket,
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     bool reused,
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     ClientSocketHandle* handle,
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     base::TimeDelta time_idle,
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     Group* group,
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     const BoundNetLog& net_log);
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Adds |socket| to the list of idle sockets for |group|.
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AddIdleSocket(ClientSocket* socket, Group* group);
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Iterates through |group_map_|, canceling all ConnectJobs and deleting
4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // groups if they are no longer needed.
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CancelAllConnectJobs();
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Iterates through |group_map_|, posting ERR_ABORTED callbacks for all
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // requests, and then deleting groups if they are no longer needed.
4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AbortAllRequests();
4733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if we can't create any more sockets due to the total limit.
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ReachedMaxSocketsLimit() const;
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is the internal implementation of RequestSocket().  It differs in that
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // it does not handle logging into NetLog of the queueing status of
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |request|.
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int RequestSocketInternal(const std::string& group_name,
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            const Request* request);
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Assigns an idle socket for the group to the request.
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns |true| if an idle socket is available, false otherwise.
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool AssignIdleSocketToGroup(const Request* request, Group* group);
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static void LogBoundConnectJobToRequest(
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const NetLog::Source& connect_job_source, const Request* request);
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Closes one idle socket.  Picks the first one encountered.
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(willchan): Consider a better algorithm for doing this.  Perhaps we
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should keep an ordered list of idle sockets, and close them in order.
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Requires maintaining more state.  It's not clear if it's worth it since
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // I'm not sure if we hit this situation often.
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CloseOneIdleSocket();
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
497201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Same as CloseOneIdleSocket() except it won't close an idle socket in
498201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // |group|.  If |group| is NULL, it is ignored.  Returns true if it closed a
499201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // socket.
500201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool CloseOneIdleSocketExceptInGroup(const Group* group);
501201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Checks if there are stalled socket groups that should be notified
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for possible wakeup.
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CheckForStalledSocketGroups();
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Posts a task to call InvokeUserCallback() on the next iteration through the
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // current message loop.  Inserts |callback| into |pending_callback_map_|,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // keyed by |handle|.
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InvokeUserCallbackLater(
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ClientSocketHandle* handle, CompletionCallback* callback, int rv);
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Invokes the user callback for |handle|.  By the time this task has run,
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // it's possible that the request has been cancelled, so |handle| may not
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // exist in |pending_callback_map_|.  We look up the callback and result code
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in |pending_callback_map_|.
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InvokeUserCallback(ClientSocketHandle* handle);
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GroupMap group_map_;
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Map of the ClientSocketHandles for which we have a pending Task to invoke a
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // callback.  This is necessary since, before we invoke said callback, it's
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // possible that the request is cancelled.
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PendingCallbackMap pending_callback_map_;
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Timer used to periodically prune idle sockets that timed out or can't be
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // reused.
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_;
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The total number of idle sockets in the system.
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int idle_socket_count_;
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Number of connecting sockets across all groups.
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int connecting_socket_count_;
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Number of connected sockets we handed out across all groups.
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int handed_out_socket_count_;
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The maximum total number of sockets. See ReachedMaxSocketsLimit.
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int max_sockets_;
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The maximum number of sockets kept per group.
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int max_sockets_per_group_;
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The time to wait until closing idle sockets.
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const base::TimeDelta unused_idle_socket_timeout_;
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const base::TimeDelta used_idle_socket_timeout_;
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const scoped_ptr<ConnectJobFactory> connect_job_factory_;
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool
5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool connect_backup_jobs_enabled_;
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A unique id for the pool.  It gets incremented every time we Flush() the
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pool.  This is so that when sockets get released back to the pool, we can
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // make sure that they are discarded rather than reused.
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int pool_generation_number_;
5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_;
5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper);
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace internal
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The maximum duration, in seconds, to keep used idle persistent sockets alive.
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kUsedIdleSocketTimeout = 300;  // 5 minutes
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SocketParams>
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ClientSocketPoolBase {
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class Request : public internal::ClientSocketPoolBaseHelper::Request {
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Request(ClientSocketHandle* handle,
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            CompletionCallback* callback,
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            RequestPriority priority,
576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            internal::ClientSocketPoolBaseHelper::Flags flags,
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            bool ignore_limits,
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            const scoped_refptr<SocketParams>& params,
579e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            const BoundNetLog& net_log
580e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
581e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            , bool valid_uid, int calling_uid
582e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
583e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma           )
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        : internal::ClientSocketPoolBaseHelper::Request(
585e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              handle, callback, priority, ignore_limits,
586e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              flags, net_log
587e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
588e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              , valid_uid, calling_uid
589e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
590e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              ),
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          params_(params) {}
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const scoped_refptr<SocketParams>& params() const { return params_; }
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
596731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const scoped_refptr<SocketParams> params_;
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class ConnectJobFactory {
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ConnectJobFactory() {}
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ~ConnectJobFactory() {}
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ConnectJob* NewConnectJob(
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const std::string& group_name,
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const Request& request,
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConnectJob::Delegate* delegate) const = 0;
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual base::TimeDelta ConnectionTimeout() const = 0;
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |max_sockets| is the maximum number of sockets to be maintained by this
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ClientSocketPool.  |max_sockets_per_group| specifies the maximum number of
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sockets a "group" can have.  |unused_idle_socket_timeout| specifies how
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // long to leave an unused idle socket open before closing it.
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |used_idle_socket_timeout| specifies how long to leave a previously used
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // idle socket open before closing it.
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocketPoolBase(
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int max_sockets,
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int max_sockets_per_group,
6243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ClientSocketPoolHistograms* histograms,
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta unused_idle_socket_timeout,
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta used_idle_socket_timeout,
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConnectJobFactory* connect_job_factory)
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : histograms_(histograms),
6293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        helper_(max_sockets, max_sockets_per_group,
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                unused_idle_socket_timeout, used_idle_socket_timeout,
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                new ConnectJobFactoryAdaptor(connect_job_factory)) {}
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~ClientSocketPoolBase() {}
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // These member functions simply forward to ClientSocketPoolBaseHelper.
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // RequestSocket bundles up the parameters into a Request and then forwards to
638731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // ClientSocketPoolBaseHelper::RequestSocket().
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int RequestSocket(const std::string& group_name,
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const scoped_refptr<SocketParams>& params,
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    RequestPriority priority,
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ClientSocketHandle* handle,
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    CompletionCallback* callback,
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const BoundNetLog& net_log) {
645e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
646e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    uid_t calling_uid = 0;
647e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    bool valid_uid = params->getUID(&calling_uid);
648e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
649731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Request* request =
650731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        new Request(handle, callback, priority,
651731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    internal::ClientSocketPoolBaseHelper::NORMAL,
652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    params->ignore_limits(),
653e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                    params, net_log
654e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
655e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                    , valid_uid, calling_uid
656e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
657e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                    );
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.RequestSocket(group_name, request);
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
661731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // RequestSockets bundles up the parameters into a Request and then forwards
662731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // to ClientSocketPoolBaseHelper::RequestSockets().  Note that it assigns the
663731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // priority to LOWEST and specifies the NO_IDLE_SOCKETS flag.
664731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void RequestSockets(const std::string& group_name,
665731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      const scoped_refptr<SocketParams>& params,
666731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      int num_sockets,
667731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      const BoundNetLog& net_log) {
668e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
669e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    uid_t calling_uid = 0;
670e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    bool valid_uid = params->getUID(&calling_uid);
671e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
672731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const Request request(NULL /* no handle */,
673731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          NULL /* no callback */,
674731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          LOWEST,
675731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          params->ignore_limits(),
677731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          params,
678e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                          net_log
679e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
680e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                          , valid_uid, calling_uid
681e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
682e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                          );
683731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    helper_.RequestSockets(group_name, request, num_sockets);
684731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
685731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CancelRequest(const std::string& group_name,
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     ClientSocketHandle* handle) {
6883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.CancelRequest(group_name, handle);
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ReleaseSocket(const std::string& group_name, ClientSocket* socket,
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     int id) {
6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.ReleaseSocket(group_name, socket, id);
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void CloseIdleSockets() { return helper_.CloseIdleSockets(); }
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int idle_socket_count() const { return helper_.idle_socket_count(); }
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int IdleSocketCountInGroup(const std::string& group_name) const {
7013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.IdleSocketCountInGroup(group_name);
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadState GetLoadState(const std::string& group_name,
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         const ClientSocketHandle* handle) const {
7063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.GetLoadState(group_name, handle);
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void OnConnectJobComplete(int result, ConnectJob* job) {
7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.OnConnectJobComplete(result, job);
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int NumConnectJobsInGroup(const std::string& group_name) const {
7143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.NumConnectJobsInGroup(group_name);
7153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
7163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
717731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int NumActiveSocketsInGroup(const std::string& group_name) const {
718731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return helper_.NumActiveSocketsInGroup(group_name);
719731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
720731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool HasGroup(const std::string& group_name) const {
7223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.HasGroup(group_name);
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CleanupIdleSockets(bool force) {
7263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.CleanupIdleSockets(force);
7273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
7283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DictionaryValue* GetInfoAsValue(const std::string& name,
7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  const std::string& type) const {
7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.GetInfoAsValue(name, type);
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::TimeDelta ConnectionTimeout() const {
7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.ConnectionTimeout();
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClientSocketPoolHistograms* histograms() const {
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return histograms_;
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); }
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Flush() { helper_.Flush(); }
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This adaptor class exists to bridge the
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // static_cast themselves.
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class ConnectJobFactoryAdaptor
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory {
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ConnectJobFactory;
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory)
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        : connect_job_factory_(connect_job_factory) {}
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ~ConnectJobFactoryAdaptor() {}
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ConnectJob* NewConnectJob(
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const std::string& group_name,
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const internal::ClientSocketPoolBaseHelper::Request& request,
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConnectJob::Delegate* delegate) const {
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const Request* casted_request = static_cast<const Request*>(&request);
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return connect_job_factory_->NewConnectJob(
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          group_name, *casted_request, delegate);
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual base::TimeDelta ConnectionTimeout() const {
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return connect_job_factory_->ConnectionTimeout();
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const scoped_ptr<ConnectJobFactory> connect_job_factory_;
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Histograms for the pool
7793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClientSocketPoolHistograms* const histograms_;
7803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  internal::ClientSocketPoolBaseHelper helper_;
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
788