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