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
285088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // Called to enable/disable cleaning up idle sockets. When enabled,
286088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // idle sockets that have been around for longer than a period defined
287088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // by kCleanupInterval are cleaned up using a timer. Otherwise they are
288088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // closed next time client makes a request. This may reduce network
289088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // activity and power consumption.
290088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  static bool cleanup_timer_enabled();
291088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  static bool set_cleanup_timer_enabled(bool enabled);
292088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Closes all idle sockets if |force| is true.  Else, only closes idle
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sockets that timed out or can't be reused.  Made public for testing.
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CleanupIdleSockets(bool force);
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See ClientSocketPool::GetInfoAsValue for documentation on this function.
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DictionaryValue* GetInfoAsValue(const std::string& name,
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  const std::string& type) const;
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::TimeDelta ConnectionTimeout() const {
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return connect_job_factory_->ConnectionTimeout();
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool connect_backup_jobs_enabled();
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool set_connect_backup_jobs_enabled(bool enabled);
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void EnableConnectBackupJobs();
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ConnectJob::Delegate methods:
31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OnConnectJobComplete(int result, ConnectJob* job);
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // NetworkChangeNotifier::IPAddressObserver methods:
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OnIPAddressChanged();
31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class base::RefCounted<ClientSocketPoolBaseHelper>;
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Entry for a persistent socket which became idle at time |start_time|.
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct IdleSocket {
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    IdleSocket() : socket(NULL) {}
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // An idle socket should be removed if it can't be reused, or has been idle
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // for too long. |now| is the current time value (TimeTicks::Now()).
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // |timeout| is the length of time to wait before timing out an idle socket.
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // An idle socket can't be reused if it is disconnected or has received
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // data unexpectedly (hence no longer idle).  The unread data would be
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // mistaken for the beginning of the next response if we were to reuse the
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // socket for a new request.
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ClientSocket* socket;
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::TimeTicks start_time;
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  typedef std::deque<const Request* > RequestQueue;
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // A Group is allocated per group_name when there are idle sockets or pending
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // requests.  Otherwise, the Group object is removed from the map.
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |active_socket_count| tracks the number of sockets held by clients.
3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  class Group {
3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick   public:
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Group();
3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ~Group();
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool IsEmpty() const {
3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return active_socket_count_ == 0 && idle_sockets_.empty() &&
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          jobs_.empty() && pending_requests_.empty();
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool HasAvailableSocketSlot(int max_sockets_per_group) const {
354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return NumActiveSocketSlots() < max_sockets_per_group;
355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int NumActiveSocketSlots() const {
358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return active_socket_count_ + static_cast<int>(jobs_.size()) +
359731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          static_cast<int>(idle_sockets_.size());
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool IsStalled(int max_sockets_per_group) const {
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return HasAvailableSocketSlot(max_sockets_per_group) &&
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          pending_requests_.size() > jobs_.size();
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RequestPriority TopPendingPriority() const {
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return pending_requests_.front()->priority();
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool HasBackupJob() const { return !method_factory_.empty(); }
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void CleanupBackupJob() {
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      method_factory_.RevokeAll();
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Set a timer to create a backup socket if it takes too long to create one.
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void StartBackupSocketTimer(const std::string& group_name,
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                ClientSocketPoolBaseHelper* pool);
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
381731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so,
382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // uses it.  Returns true on success.  Otherwise, returns false.
383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool TryToUsePreconnectConnectJob();
3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
385731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void AddJob(ConnectJob* job) { jobs_.insert(job); }
386731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void RemoveJob(ConnectJob* job) { jobs_.erase(job); }
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void RemoveAllJobs();
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void IncrementActiveSocketCount() { active_socket_count_++; }
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void DecrementActiveSocketCount() { active_socket_count_--; }
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::set<ConnectJob*>& jobs() const { return jobs_; }
393731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; }
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const RequestQueue& pending_requests() const { return pending_requests_; }
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int active_socket_count() const { return active_socket_count_; }
3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    RequestQueue* mutable_pending_requests() { return &pending_requests_; }
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; }
3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick   private:
400731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Called when the backup socket timer fires.
401731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void OnBackupSocketTimerFired(
402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        std::string group_name,
403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        ClientSocketPoolBaseHelper* pool);
404731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::list<IdleSocket> idle_sockets_;
406731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::set<ConnectJob*> jobs_;
4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    RequestQueue pending_requests_;
4083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int active_socket_count_;  // number of active sockets used by clients
4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // A factory to pin the backup_job tasks.
4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ScopedRunnableMethodFactory<Group> method_factory_;
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  typedef std::map<std::string, Group*> GroupMap;
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  typedef std::set<ConnectJob*> ConnectJobSet;
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct CallbackResultPair {
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CallbackResultPair() : callback(NULL), result(OK) {}
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CallbackResultPair(CompletionCallback* callback_in, int result_in)
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : callback(callback_in), result(result_in) {}
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CompletionCallback* callback;
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int result;
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::map<const ClientSocketHandle*, CallbackResultPair>
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PendingCallbackMap;
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void InsertRequestIntoQueue(const Request* r,
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     RequestQueue* pending_requests);
431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const Request* RemoveRequestFromQueue(const RequestQueue::iterator& it,
4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                               Group* group);
4333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Group* GetOrCreateGroup(const std::string& group_name);
4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void RemoveGroup(const std::string& group_name);
4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void RemoveGroup(GroupMap::iterator it);
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called when the number of idle sockets changes.
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void IncrementIdleCount();
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void DecrementIdleCount();
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
442088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // Start cleanup timer for idle sockets.
443088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  void StartIdleSocketTimer();
444088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Scans the group map for groups which have an available socket slot and
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // at least one pending request. Returns true if any groups are stalled, and
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // if so, fills |group| and |group_name| with data of the stalled group
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // having highest priority.
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool FindTopStalledGroup(Group** group, std::string* group_name);
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Called when timer_ fires.  This method scans the idle sockets removing
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sockets that timed out or can't be reused.
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnCleanupTimerFired() {
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CleanupIdleSockets(false);
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Removes |job| from |connect_job_set_|.  Also updates |group| if non-NULL.
458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void RemoveConnectJob(ConnectJob* job, Group* group);
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Tries to see if we can handle any more requests for |group|.
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnAvailableSocketSlot(const std::string& group_name, Group* group);
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Process a pending socket request for a group.
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ProcessPendingRequest(const std::string& group_name, Group* group);
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Assigns |socket| to |handle| and updates |group|'s counters appropriately.
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void HandOutSocket(ClientSocket* socket,
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     bool reused,
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     ClientSocketHandle* handle,
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     base::TimeDelta time_idle,
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     Group* group,
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     const BoundNetLog& net_log);
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Adds |socket| to the list of idle sockets for |group|.
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AddIdleSocket(ClientSocket* socket, Group* group);
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Iterates through |group_map_|, canceling all ConnectJobs and deleting
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // groups if they are no longer needed.
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CancelAllConnectJobs();
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Iterates through |group_map_|, posting ERR_ABORTED callbacks for all
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // requests, and then deleting groups if they are no longer needed.
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AbortAllRequests();
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if we can't create any more sockets due to the total limit.
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ReachedMaxSocketsLimit() const;
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is the internal implementation of RequestSocket().  It differs in that
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // it does not handle logging into NetLog of the queueing status of
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |request|.
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int RequestSocketInternal(const std::string& group_name,
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            const Request* request);
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Assigns an idle socket for the group to the request.
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns |true| if an idle socket is available, false otherwise.
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool AssignIdleSocketToGroup(const Request* request, Group* group);
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static void LogBoundConnectJobToRequest(
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const NetLog::Source& connect_job_source, const Request* request);
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Closes one idle socket.  Picks the first one encountered.
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(willchan): Consider a better algorithm for doing this.  Perhaps we
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should keep an ordered list of idle sockets, and close them in order.
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Requires maintaining more state.  It's not clear if it's worth it since
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // I'm not sure if we hit this situation often.
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CloseOneIdleSocket();
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
508201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Same as CloseOneIdleSocket() except it won't close an idle socket in
509201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // |group|.  If |group| is NULL, it is ignored.  Returns true if it closed a
510201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // socket.
511201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool CloseOneIdleSocketExceptInGroup(const Group* group);
512201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Checks if there are stalled socket groups that should be notified
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for possible wakeup.
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CheckForStalledSocketGroups();
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Posts a task to call InvokeUserCallback() on the next iteration through the
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // current message loop.  Inserts |callback| into |pending_callback_map_|,
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // keyed by |handle|.
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InvokeUserCallbackLater(
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ClientSocketHandle* handle, CompletionCallback* callback, int rv);
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Invokes the user callback for |handle|.  By the time this task has run,
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // it's possible that the request has been cancelled, so |handle| may not
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // exist in |pending_callback_map_|.  We look up the callback and result code
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in |pending_callback_map_|.
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InvokeUserCallback(ClientSocketHandle* handle);
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GroupMap group_map_;
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Map of the ClientSocketHandles for which we have a pending Task to invoke a
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // callback.  This is necessary since, before we invoke said callback, it's
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // possible that the request is cancelled.
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PendingCallbackMap pending_callback_map_;
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Timer used to periodically prune idle sockets that timed out or can't be
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // reused.
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_;
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The total number of idle sockets in the system.
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int idle_socket_count_;
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Number of connecting sockets across all groups.
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int connecting_socket_count_;
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Number of connected sockets we handed out across all groups.
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int handed_out_socket_count_;
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The maximum total number of sockets. See ReachedMaxSocketsLimit.
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int max_sockets_;
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The maximum number of sockets kept per group.
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int max_sockets_per_group_;
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
555088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  // Whether to use timer to cleanup idle sockets.
556088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun  bool use_cleanup_timer_;
557088da08b1e594e2e3cae7114394145e8268ab6c9Selim Gurun
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The time to wait until closing idle sockets.
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const base::TimeDelta unused_idle_socket_timeout_;
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const base::TimeDelta used_idle_socket_timeout_;
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const scoped_ptr<ConnectJobFactory> connect_job_factory_;
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool
5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool connect_backup_jobs_enabled_;
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A unique id for the pool.  It gets incremented every time we Flush() the
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // pool.  This is so that when sockets get released back to the pool, we can
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // make sure that they are discarded rather than reused.
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int pool_generation_number_;
5713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_;
5733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper);
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace internal
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The maximum duration, in seconds, to keep used idle persistent sockets alive.
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kUsedIdleSocketTimeout = 300;  // 5 minutes
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename SocketParams>
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ClientSocketPoolBase {
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class Request : public internal::ClientSocketPoolBaseHelper::Request {
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Request(ClientSocketHandle* handle,
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            CompletionCallback* callback,
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            RequestPriority priority,
590731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick            internal::ClientSocketPoolBaseHelper::Flags flags,
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            bool ignore_limits,
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            const scoped_refptr<SocketParams>& params,
593e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            const BoundNetLog& net_log
594e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
595e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma            , bool valid_uid, int calling_uid
596e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
597e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma           )
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        : internal::ClientSocketPoolBaseHelper::Request(
599e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              handle, callback, priority, ignore_limits,
600e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              flags, net_log
601e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
602e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              , valid_uid, calling_uid
603e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
604e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma              ),
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          params_(params) {}
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const scoped_refptr<SocketParams>& params() const { return params_; }
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
610731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const scoped_refptr<SocketParams> params_;
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class ConnectJobFactory {
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ConnectJobFactory() {}
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ~ConnectJobFactory() {}
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ConnectJob* NewConnectJob(
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const std::string& group_name,
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const Request& request,
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConnectJob::Delegate* delegate) const = 0;
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual base::TimeDelta ConnectionTimeout() const = 0;
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   private:
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |max_sockets| is the maximum number of sockets to be maintained by this
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ClientSocketPool.  |max_sockets_per_group| specifies the maximum number of
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sockets a "group" can have.  |unused_idle_socket_timeout| specifies how
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // long to leave an unused idle socket open before closing it.
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |used_idle_socket_timeout| specifies how long to leave a previously used
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // idle socket open before closing it.
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ClientSocketPoolBase(
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int max_sockets,
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int max_sockets_per_group,
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ClientSocketPoolHistograms* histograms,
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta unused_idle_socket_timeout,
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta used_idle_socket_timeout,
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConnectJobFactory* connect_job_factory)
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : histograms_(histograms),
6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        helper_(max_sockets, max_sockets_per_group,
6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                unused_idle_socket_timeout, used_idle_socket_timeout,
6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                new ConnectJobFactoryAdaptor(connect_job_factory)) {}
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual ~ClientSocketPoolBase() {}
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // These member functions simply forward to ClientSocketPoolBaseHelper.
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // RequestSocket bundles up the parameters into a Request and then forwards to
652731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // ClientSocketPoolBaseHelper::RequestSocket().
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int RequestSocket(const std::string& group_name,
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const scoped_refptr<SocketParams>& params,
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    RequestPriority priority,
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ClientSocketHandle* handle,
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    CompletionCallback* callback,
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const BoundNetLog& net_log) {
659e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
660e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    uid_t calling_uid = 0;
661e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    bool valid_uid = params->getUID(&calling_uid);
662e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
663731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Request* request =
664731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        new Request(handle, callback, priority,
665731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    internal::ClientSocketPoolBaseHelper::NORMAL,
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    params->ignore_limits(),
667e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                    params, net_log
668e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
669e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                    , valid_uid, calling_uid
670e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
671e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                    );
6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.RequestSocket(group_name, request);
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
675731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // RequestSockets bundles up the parameters into a Request and then forwards
676731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // to ClientSocketPoolBaseHelper::RequestSockets().  Note that it assigns the
677731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // priority to LOWEST and specifies the NO_IDLE_SOCKETS flag.
678731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void RequestSockets(const std::string& group_name,
679731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      const scoped_refptr<SocketParams>& params,
680731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      int num_sockets,
681731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                      const BoundNetLog& net_log) {
682e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
683e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    uid_t calling_uid = 0;
684e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    bool valid_uid = params->getUID(&calling_uid);
685e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
686731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const Request request(NULL /* no handle */,
687731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          NULL /* no callback */,
688731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          LOWEST,
689731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          params->ignore_limits(),
691731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          params,
692e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                          net_log
693e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
694e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                          , valid_uid, calling_uid
695e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
696e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                          );
697731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    helper_.RequestSockets(group_name, request, num_sockets);
698731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
699731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CancelRequest(const std::string& group_name,
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     ClientSocketHandle* handle) {
7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.CancelRequest(group_name, handle);
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ReleaseSocket(const std::string& group_name, ClientSocket* socket,
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     int id) {
7073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.ReleaseSocket(group_name, socket, id);
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void CloseIdleSockets() { return helper_.CloseIdleSockets(); }
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int idle_socket_count() const { return helper_.idle_socket_count(); }
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int IdleSocketCountInGroup(const std::string& group_name) const {
7153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.IdleSocketCountInGroup(group_name);
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LoadState GetLoadState(const std::string& group_name,
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         const ClientSocketHandle* handle) const {
7203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.GetLoadState(group_name, handle);
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void OnConnectJobComplete(int result, ConnectJob* job) {
7243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.OnConnectJobComplete(result, job);
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int NumConnectJobsInGroup(const std::string& group_name) const {
7283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.NumConnectJobsInGroup(group_name);
7293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
731731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int NumActiveSocketsInGroup(const std::string& group_name) const {
732731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return helper_.NumActiveSocketsInGroup(group_name);
733731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
734731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool HasGroup(const std::string& group_name) const {
7363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.HasGroup(group_name);
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void CleanupIdleSockets(bool force) {
7403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.CleanupIdleSockets(force);
7413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
7423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DictionaryValue* GetInfoAsValue(const std::string& name,
7443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  const std::string& type) const {
7453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.GetInfoAsValue(name, type);
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::TimeDelta ConnectionTimeout() const {
7493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return helper_.ConnectionTimeout();
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClientSocketPoolHistograms* histograms() const {
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return histograms_;
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); }
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Flush() { helper_.Flush(); }
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This adaptor class exists to bridge the
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // static_cast themselves.
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class ConnectJobFactoryAdaptor
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory {
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott   public:
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ConnectJobFactory;
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory)
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        : connect_job_factory_(connect_job_factory) {}
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ~ConnectJobFactoryAdaptor() {}
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    virtual ConnectJob* NewConnectJob(
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const std::string& group_name,
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        const internal::ClientSocketPoolBaseHelper::Request& request,
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConnectJob::Delegate* delegate) const {
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      const Request* casted_request = static_cast<const Request*>(&request);
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return connect_job_factory_->NewConnectJob(
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          group_name, *casted_request, delegate);
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual base::TimeDelta ConnectionTimeout() const {
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return connect_job_factory_->ConnectionTimeout();
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const scoped_ptr<ConnectJobFactory> connect_job_factory_;
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Histograms for the pool
7933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClientSocketPoolHistograms* const histograms_;
7943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  internal::ClientSocketPoolBaseHelper helper_;
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
802