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