1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // A ClientSocketPoolBase is used to restrict the number of sockets open at 6 // a time. It also maintains a list of idle persistent sockets for reuse. 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle 8 // the core logic of (1) restricting the number of active (connected or 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) 11 // limiting the total number of active sockets in the system. 12 // 13 // ClientSocketPoolBase abstracts socket connection details behind ConnectJob, 14 // ConnectJobFactory, and SocketParams. When a socket "slot" becomes available, 15 // the ClientSocketPoolBase will ask the ConnectJobFactory to create a 16 // ConnectJob with a SocketParams. Subclasses of ClientSocketPool should 17 // implement their socket specific connection by subclassing ConnectJob and 18 // implementing ConnectJob::ConnectInternal(). They can control the parameters 19 // passed to each new ConnectJob instance via their ConnectJobFactory subclass 20 // and templated SocketParams parameter. 21 // 22 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 24 25 #include <deque> 26 #include <list> 27 #include <map> 28 #include <set> 29 #include <string> 30 #include <vector> 31 32 #include "base/basictypes.h" 33 #include "base/memory/ref_counted.h" 34 #include "base/memory/scoped_ptr.h" 35 #include "base/memory/weak_ptr.h" 36 #include "base/time/time.h" 37 #include "base/timer/timer.h" 38 #include "net/base/address_list.h" 39 #include "net/base/completion_callback.h" 40 #include "net/base/load_states.h" 41 #include "net/base/load_timing_info.h" 42 #include "net/base/net_errors.h" 43 #include "net/base/net_export.h" 44 #include "net/base/net_log.h" 45 #include "net/base/network_change_notifier.h" 46 #include "net/base/request_priority.h" 47 #include "net/socket/client_socket_pool.h" 48 #include "net/socket/stream_socket.h" 49 50 namespace net { 51 52 class ClientSocketHandle; 53 54 // ConnectJob provides an abstract interface for "connecting" a socket. 55 // The connection may involve host resolution, tcp connection, ssl connection, 56 // etc. 57 class NET_EXPORT_PRIVATE ConnectJob { 58 public: 59 class NET_EXPORT_PRIVATE Delegate { 60 public: 61 Delegate() {} 62 virtual ~Delegate() {} 63 64 // Alerts the delegate that the connection completed. 65 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; 66 67 private: 68 DISALLOW_COPY_AND_ASSIGN(Delegate); 69 }; 70 71 // A |timeout_duration| of 0 corresponds to no timeout. 72 ConnectJob(const std::string& group_name, 73 base::TimeDelta timeout_duration, 74 Delegate* delegate, 75 const BoundNetLog& net_log); 76 virtual ~ConnectJob(); 77 78 // Accessors 79 const std::string& group_name() const { return group_name_; } 80 const BoundNetLog& net_log() { return net_log_; } 81 82 // Releases |socket_| to the client. On connection error, this should return 83 // NULL. 84 StreamSocket* ReleaseSocket() { return socket_.release(); } 85 86 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it 87 // cannot complete synchronously without blocking, or another net error code 88 // on error. In asynchronous completion, the ConnectJob will notify 89 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous 90 // completion, ReleaseSocket() can be called to acquire the connected socket 91 // if it succeeded. 92 int Connect(); 93 94 virtual LoadState GetLoadState() const = 0; 95 96 // If Connect returns an error (or OnConnectJobComplete reports an error 97 // result) this method will be called, allowing the pool to add 98 // additional error state to the ClientSocketHandle (post late-binding). 99 virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {} 100 101 const LoadTimingInfo::ConnectTiming& connect_timing() const { 102 return connect_timing_; 103 } 104 105 const BoundNetLog& net_log() const { return net_log_; } 106 107 protected: 108 void set_socket(StreamSocket* socket); 109 StreamSocket* socket() { return socket_.get(); } 110 void NotifyDelegateOfCompletion(int rv); 111 void ResetTimer(base::TimeDelta remainingTime); 112 113 // Connection establishment timing information. 114 LoadTimingInfo::ConnectTiming connect_timing_; 115 116 private: 117 virtual int ConnectInternal() = 0; 118 119 void LogConnectStart(); 120 void LogConnectCompletion(int net_error); 121 122 // Alerts the delegate that the ConnectJob has timed out. 123 void OnTimeout(); 124 125 const std::string group_name_; 126 const base::TimeDelta timeout_duration_; 127 // Timer to abort jobs that take too long. 128 base::OneShotTimer<ConnectJob> timer_; 129 Delegate* delegate_; 130 scoped_ptr<StreamSocket> socket_; 131 BoundNetLog net_log_; 132 // A ConnectJob is idle until Connect() has been called. 133 bool idle_; 134 135 DISALLOW_COPY_AND_ASSIGN(ConnectJob); 136 }; 137 138 namespace internal { 139 140 // ClientSocketPoolBaseHelper is an internal class that implements almost all 141 // the functionality from ClientSocketPoolBase without using templates. 142 // ClientSocketPoolBase adds templated definitions built on top of 143 // ClientSocketPoolBaseHelper. This class is not for external use, please use 144 // ClientSocketPoolBase instead. 145 class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper 146 : public ConnectJob::Delegate, 147 public NetworkChangeNotifier::IPAddressObserver { 148 public: 149 typedef uint32 Flags; 150 151 // Used to specify specific behavior for the ClientSocketPool. 152 enum Flag { 153 NORMAL = 0, // Normal behavior. 154 NO_IDLE_SOCKETS = 0x1, // Do not return an idle socket. Create a new one. 155 }; 156 157 class NET_EXPORT_PRIVATE Request { 158 public: 159 Request(ClientSocketHandle* handle, 160 const CompletionCallback& callback, 161 RequestPriority priority, 162 bool ignore_limits, 163 Flags flags, 164 const BoundNetLog& net_log); 165 166 virtual ~Request(); 167 168 ClientSocketHandle* handle() const { return handle_; } 169 const CompletionCallback& callback() const { return callback_; } 170 RequestPriority priority() const { return priority_; } 171 bool ignore_limits() const { return ignore_limits_; } 172 Flags flags() const { return flags_; } 173 const BoundNetLog& net_log() const { return net_log_; } 174 175 private: 176 ClientSocketHandle* const handle_; 177 CompletionCallback callback_; 178 const RequestPriority priority_; 179 bool ignore_limits_; 180 const Flags flags_; 181 BoundNetLog net_log_; 182 183 DISALLOW_COPY_AND_ASSIGN(Request); 184 }; 185 186 class ConnectJobFactory { 187 public: 188 ConnectJobFactory() {} 189 virtual ~ConnectJobFactory() {} 190 191 virtual ConnectJob* NewConnectJob( 192 const std::string& group_name, 193 const Request& request, 194 ConnectJob::Delegate* delegate) const = 0; 195 196 virtual base::TimeDelta ConnectionTimeout() const = 0; 197 198 private: 199 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); 200 }; 201 202 ClientSocketPoolBaseHelper( 203 int max_sockets, 204 int max_sockets_per_group, 205 base::TimeDelta unused_idle_socket_timeout, 206 base::TimeDelta used_idle_socket_timeout, 207 ConnectJobFactory* connect_job_factory); 208 209 virtual ~ClientSocketPoolBaseHelper(); 210 211 // Adds/Removes layered pools. It is expected in the destructor that no 212 // layered pools remain. 213 void AddLayeredPool(LayeredPool* pool); 214 void RemoveLayeredPool(LayeredPool* pool); 215 216 // See ClientSocketPool::RequestSocket for documentation on this function. 217 // ClientSocketPoolBaseHelper takes ownership of |request|, which must be 218 // heap allocated. 219 int RequestSocket(const std::string& group_name, const Request* request); 220 221 // See ClientSocketPool::RequestSocket for documentation on this function. 222 void RequestSockets(const std::string& group_name, 223 const Request& request, 224 int num_sockets); 225 226 // See ClientSocketPool::CancelRequest for documentation on this function. 227 void CancelRequest(const std::string& group_name, 228 ClientSocketHandle* handle); 229 230 // See ClientSocketPool::ReleaseSocket for documentation on this function. 231 void ReleaseSocket(const std::string& group_name, 232 StreamSocket* socket, 233 int id); 234 235 // See ClientSocketPool::FlushWithError for documentation on this function. 236 void FlushWithError(int error); 237 238 // See ClientSocketPool::IsStalled for documentation on this function. 239 bool IsStalled() const; 240 241 // See ClientSocketPool::CloseIdleSockets for documentation on this function. 242 void CloseIdleSockets(); 243 244 // See ClientSocketPool::IdleSocketCount() for documentation on this function. 245 int idle_socket_count() const { 246 return idle_socket_count_; 247 } 248 249 // See ClientSocketPool::IdleSocketCountInGroup() for documentation on this 250 // function. 251 int IdleSocketCountInGroup(const std::string& group_name) const; 252 253 // See ClientSocketPool::GetLoadState() for documentation on this function. 254 LoadState GetLoadState(const std::string& group_name, 255 const ClientSocketHandle* handle) const; 256 257 base::TimeDelta ConnectRetryInterval() const { 258 // TODO(mbelshe): Make this tuned dynamically based on measured RTT. 259 // For now, just use the max retry interval. 260 return base::TimeDelta::FromMilliseconds( 261 ClientSocketPool::kMaxConnectRetryIntervalMs); 262 } 263 264 int NumUnassignedConnectJobsInGroup(const std::string& group_name) const { 265 return group_map_.find(group_name)->second->unassigned_job_count(); 266 } 267 268 int NumConnectJobsInGroup(const std::string& group_name) const { 269 return group_map_.find(group_name)->second->jobs().size(); 270 } 271 272 int NumActiveSocketsInGroup(const std::string& group_name) const { 273 return group_map_.find(group_name)->second->active_socket_count(); 274 } 275 276 bool HasGroup(const std::string& group_name) const; 277 278 // Called to enable/disable cleaning up idle sockets. When enabled, 279 // idle sockets that have been around for longer than a period defined 280 // by kCleanupInterval are cleaned up using a timer. Otherwise they are 281 // closed next time client makes a request. This may reduce network 282 // activity and power consumption. 283 static bool cleanup_timer_enabled(); 284 static bool set_cleanup_timer_enabled(bool enabled); 285 286 // Closes all idle sockets if |force| is true. Else, only closes idle 287 // sockets that timed out or can't be reused. Made public for testing. 288 void CleanupIdleSockets(bool force); 289 290 // Closes one idle socket. Picks the first one encountered. 291 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we 292 // should keep an ordered list of idle sockets, and close them in order. 293 // Requires maintaining more state. It's not clear if it's worth it since 294 // I'm not sure if we hit this situation often. 295 bool CloseOneIdleSocket(); 296 297 // Checks layered pools to see if they can close an idle connection. 298 bool CloseOneIdleConnectionInLayeredPool(); 299 300 // See ClientSocketPool::GetInfoAsValue for documentation on this function. 301 base::DictionaryValue* GetInfoAsValue(const std::string& name, 302 const std::string& type) const; 303 304 base::TimeDelta ConnectionTimeout() const { 305 return connect_job_factory_->ConnectionTimeout(); 306 } 307 308 static bool connect_backup_jobs_enabled(); 309 static bool set_connect_backup_jobs_enabled(bool enabled); 310 311 void EnableConnectBackupJobs(); 312 313 // ConnectJob::Delegate methods: 314 virtual void OnConnectJobComplete(int result, ConnectJob* job) OVERRIDE; 315 316 // NetworkChangeNotifier::IPAddressObserver methods: 317 virtual void OnIPAddressChanged() OVERRIDE; 318 319 private: 320 friend class base::RefCounted<ClientSocketPoolBaseHelper>; 321 322 // Entry for a persistent socket which became idle at time |start_time|. 323 struct IdleSocket { 324 IdleSocket() : socket(NULL) {} 325 326 // An idle socket should be removed if it can't be reused, or has been idle 327 // for too long. |now| is the current time value (TimeTicks::Now()). 328 // |timeout| is the length of time to wait before timing out an idle socket. 329 // 330 // An idle socket can't be reused if it is disconnected or has received 331 // data unexpectedly (hence no longer idle). The unread data would be 332 // mistaken for the beginning of the next response if we were to reuse the 333 // socket for a new request. 334 bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const; 335 336 StreamSocket* socket; 337 base::TimeTicks start_time; 338 }; 339 340 typedef std::deque<const Request* > RequestQueue; 341 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; 342 343 // A Group is allocated per group_name when there are idle sockets or pending 344 // requests. Otherwise, the Group object is removed from the map. 345 // |active_socket_count| tracks the number of sockets held by clients. 346 class Group { 347 public: 348 Group(); 349 ~Group(); 350 351 bool IsEmpty() const { 352 return active_socket_count_ == 0 && idle_sockets_.empty() && 353 jobs_.empty() && pending_requests_.empty(); 354 } 355 356 bool HasAvailableSocketSlot(int max_sockets_per_group) const { 357 return NumActiveSocketSlots() < max_sockets_per_group; 358 } 359 360 int NumActiveSocketSlots() const { 361 return active_socket_count_ + static_cast<int>(jobs_.size()) + 362 static_cast<int>(idle_sockets_.size()); 363 } 364 365 bool IsStalledOnPoolMaxSockets(int max_sockets_per_group) const { 366 return HasAvailableSocketSlot(max_sockets_per_group) && 367 pending_requests_.size() > jobs_.size(); 368 } 369 370 RequestPriority TopPendingPriority() const { 371 return pending_requests_.front()->priority(); 372 } 373 374 bool HasBackupJob() const { return weak_factory_.HasWeakPtrs(); } 375 376 void CleanupBackupJob() { 377 weak_factory_.InvalidateWeakPtrs(); 378 } 379 380 // Set a timer to create a backup socket if it takes too long to create one. 381 void StartBackupSocketTimer(const std::string& group_name, 382 ClientSocketPoolBaseHelper* pool); 383 384 // If there's a ConnectJob that's never been assigned to Request, 385 // decrements |unassigned_job_count_| and returns true. 386 // Otherwise, returns false. 387 bool TryToUseUnassignedConnectJob(); 388 389 void AddJob(ConnectJob* job, bool is_preconnect); 390 void RemoveJob(ConnectJob* job); 391 void RemoveAllJobs(); 392 393 void IncrementActiveSocketCount() { active_socket_count_++; } 394 void DecrementActiveSocketCount() { active_socket_count_--; } 395 396 int unassigned_job_count() const { return unassigned_job_count_; } 397 const std::set<ConnectJob*>& jobs() const { return jobs_; } 398 const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; } 399 const RequestQueue& pending_requests() const { return pending_requests_; } 400 int active_socket_count() const { return active_socket_count_; } 401 RequestQueue* mutable_pending_requests() { return &pending_requests_; } 402 std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; } 403 404 private: 405 // Called when the backup socket timer fires. 406 void OnBackupSocketTimerFired( 407 std::string group_name, 408 ClientSocketPoolBaseHelper* pool); 409 410 // Checks that |unassigned_job_count_| does not execeed the number of 411 // ConnectJobs. 412 void SanityCheck(); 413 414 // Total number of ConnectJobs that have never been assigned to a Request. 415 // Since jobs use late binding to requests, which ConnectJobs have or have 416 // not been assigned to a request are not tracked. This is incremented on 417 // preconnect and decremented when a preconnect is assigned, or when there 418 // are fewer than |unassigned_job_count_| ConnectJobs. Not incremented 419 // when a request is cancelled. 420 size_t unassigned_job_count_; 421 422 std::list<IdleSocket> idle_sockets_; 423 std::set<ConnectJob*> jobs_; 424 RequestQueue pending_requests_; 425 int active_socket_count_; // number of active sockets used by clients 426 // A factory to pin the backup_job tasks. 427 base::WeakPtrFactory<Group> weak_factory_; 428 }; 429 430 typedef std::map<std::string, Group*> GroupMap; 431 432 typedef std::set<ConnectJob*> ConnectJobSet; 433 434 struct CallbackResultPair { 435 CallbackResultPair(); 436 CallbackResultPair(const CompletionCallback& callback_in, int result_in); 437 ~CallbackResultPair(); 438 439 CompletionCallback callback; 440 int result; 441 }; 442 443 typedef std::map<const ClientSocketHandle*, CallbackResultPair> 444 PendingCallbackMap; 445 446 // Inserts the request into the queue based on order they will receive 447 // sockets. Sockets which ignore the socket pool limits are first. Then 448 // requests are sorted by priority, with higher priorities closer to the 449 // front. Older requests are prioritized over requests of equal priority. 450 static void InsertRequestIntoQueue(const Request* r, 451 RequestQueue* pending_requests); 452 static const Request* RemoveRequestFromQueue(const RequestQueue::iterator& it, 453 Group* group); 454 455 Group* GetOrCreateGroup(const std::string& group_name); 456 void RemoveGroup(const std::string& group_name); 457 void RemoveGroup(GroupMap::iterator it); 458 459 // Called when the number of idle sockets changes. 460 void IncrementIdleCount(); 461 void DecrementIdleCount(); 462 463 // Start cleanup timer for idle sockets. 464 void StartIdleSocketTimer(); 465 466 // Scans the group map for groups which have an available socket slot and 467 // at least one pending request. Returns true if any groups are stalled, and 468 // if so (and if both |group| and |group_name| are not NULL), fills |group| 469 // and |group_name| with data of the stalled group having highest priority. 470 bool FindTopStalledGroup(Group** group, std::string* group_name) const; 471 472 // Called when timer_ fires. This method scans the idle sockets removing 473 // sockets that timed out or can't be reused. 474 void OnCleanupTimerFired() { 475 CleanupIdleSockets(false); 476 } 477 478 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. 479 void RemoveConnectJob(ConnectJob* job, Group* group); 480 481 // Tries to see if we can handle any more requests for |group|. 482 void OnAvailableSocketSlot(const std::string& group_name, Group* group); 483 484 // Process a pending socket request for a group. 485 void ProcessPendingRequest(const std::string& group_name, Group* group); 486 487 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. 488 void HandOutSocket(StreamSocket* socket, 489 bool reused, 490 const LoadTimingInfo::ConnectTiming& connect_timing, 491 ClientSocketHandle* handle, 492 base::TimeDelta time_idle, 493 Group* group, 494 const BoundNetLog& net_log); 495 496 // Adds |socket| to the list of idle sockets for |group|. 497 void AddIdleSocket(StreamSocket* socket, Group* group); 498 499 // Iterates through |group_map_|, canceling all ConnectJobs and deleting 500 // groups if they are no longer needed. 501 void CancelAllConnectJobs(); 502 503 // Iterates through |group_map_|, posting |error| callbacks for all 504 // requests, and then deleting groups if they are no longer needed. 505 void CancelAllRequestsWithError(int error); 506 507 // Returns true if we can't create any more sockets due to the total limit. 508 bool ReachedMaxSocketsLimit() const; 509 510 // This is the internal implementation of RequestSocket(). It differs in that 511 // it does not handle logging into NetLog of the queueing status of 512 // |request|. 513 int RequestSocketInternal(const std::string& group_name, 514 const Request* request); 515 516 // Assigns an idle socket for the group to the request. 517 // Returns |true| if an idle socket is available, false otherwise. 518 bool AssignIdleSocketToRequest(const Request* request, Group* group); 519 520 static void LogBoundConnectJobToRequest( 521 const NetLog::Source& connect_job_source, const Request* request); 522 523 // Same as CloseOneIdleSocket() except it won't close an idle socket in 524 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a 525 // socket. 526 bool CloseOneIdleSocketExceptInGroup(const Group* group); 527 528 // Checks if there are stalled socket groups that should be notified 529 // for possible wakeup. 530 void CheckForStalledSocketGroups(); 531 532 // Posts a task to call InvokeUserCallback() on the next iteration through the 533 // current message loop. Inserts |callback| into |pending_callback_map_|, 534 // keyed by |handle|. 535 void InvokeUserCallbackLater( 536 ClientSocketHandle* handle, const CompletionCallback& callback, int rv); 537 538 // Invokes the user callback for |handle|. By the time this task has run, 539 // it's possible that the request has been cancelled, so |handle| may not 540 // exist in |pending_callback_map_|. We look up the callback and result code 541 // in |pending_callback_map_|. 542 void InvokeUserCallback(ClientSocketHandle* handle); 543 544 // Tries to close idle sockets in a higher level socket pool as long as this 545 // this pool is stalled. 546 void TryToCloseSocketsInLayeredPools(); 547 548 GroupMap group_map_; 549 550 // Map of the ClientSocketHandles for which we have a pending Task to invoke a 551 // callback. This is necessary since, before we invoke said callback, it's 552 // possible that the request is cancelled. 553 PendingCallbackMap pending_callback_map_; 554 555 // Timer used to periodically prune idle sockets that timed out or can't be 556 // reused. 557 base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_; 558 559 // The total number of idle sockets in the system. 560 int idle_socket_count_; 561 562 // Number of connecting sockets across all groups. 563 int connecting_socket_count_; 564 565 // Number of connected sockets we handed out across all groups. 566 int handed_out_socket_count_; 567 568 // The maximum total number of sockets. See ReachedMaxSocketsLimit. 569 const int max_sockets_; 570 571 // The maximum number of sockets kept per group. 572 const int max_sockets_per_group_; 573 574 // Whether to use timer to cleanup idle sockets. 575 bool use_cleanup_timer_; 576 577 // The time to wait until closing idle sockets. 578 const base::TimeDelta unused_idle_socket_timeout_; 579 const base::TimeDelta used_idle_socket_timeout_; 580 581 const scoped_ptr<ConnectJobFactory> connect_job_factory_; 582 583 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool 584 bool connect_backup_jobs_enabled_; 585 586 // A unique id for the pool. It gets incremented every time we 587 // FlushWithError() the pool. This is so that when sockets get released back 588 // to the pool, we can make sure that they are discarded rather than reused. 589 int pool_generation_number_; 590 591 std::set<LayeredPool*> higher_layer_pools_; 592 593 base::WeakPtrFactory<ClientSocketPoolBaseHelper> weak_factory_; 594 595 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); 596 }; 597 598 } // namespace internal 599 600 template <typename SocketParams> 601 class ClientSocketPoolBase { 602 public: 603 class Request : public internal::ClientSocketPoolBaseHelper::Request { 604 public: 605 Request(ClientSocketHandle* handle, 606 const CompletionCallback& callback, 607 RequestPriority priority, 608 internal::ClientSocketPoolBaseHelper::Flags flags, 609 bool ignore_limits, 610 const scoped_refptr<SocketParams>& params, 611 const BoundNetLog& net_log) 612 : internal::ClientSocketPoolBaseHelper::Request( 613 handle, callback, priority, ignore_limits, flags, net_log), 614 params_(params) {} 615 616 const scoped_refptr<SocketParams>& params() const { return params_; } 617 618 private: 619 const scoped_refptr<SocketParams> params_; 620 }; 621 622 class ConnectJobFactory { 623 public: 624 ConnectJobFactory() {} 625 virtual ~ConnectJobFactory() {} 626 627 virtual ConnectJob* NewConnectJob( 628 const std::string& group_name, 629 const Request& request, 630 ConnectJob::Delegate* delegate) const = 0; 631 632 virtual base::TimeDelta ConnectionTimeout() const = 0; 633 634 private: 635 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); 636 }; 637 638 // |max_sockets| is the maximum number of sockets to be maintained by this 639 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of 640 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how 641 // long to leave an unused idle socket open before closing it. 642 // |used_idle_socket_timeout| specifies how long to leave a previously used 643 // idle socket open before closing it. 644 ClientSocketPoolBase( 645 int max_sockets, 646 int max_sockets_per_group, 647 ClientSocketPoolHistograms* histograms, 648 base::TimeDelta unused_idle_socket_timeout, 649 base::TimeDelta used_idle_socket_timeout, 650 ConnectJobFactory* connect_job_factory) 651 : histograms_(histograms), 652 helper_(max_sockets, max_sockets_per_group, 653 unused_idle_socket_timeout, used_idle_socket_timeout, 654 new ConnectJobFactoryAdaptor(connect_job_factory)) {} 655 656 virtual ~ClientSocketPoolBase() {} 657 658 // These member functions simply forward to ClientSocketPoolBaseHelper. 659 void AddLayeredPool(LayeredPool* pool) { 660 helper_.AddLayeredPool(pool); 661 } 662 663 void RemoveLayeredPool(LayeredPool* pool) { 664 helper_.RemoveLayeredPool(pool); 665 } 666 667 // RequestSocket bundles up the parameters into a Request and then forwards to 668 // ClientSocketPoolBaseHelper::RequestSocket(). 669 int RequestSocket(const std::string& group_name, 670 const scoped_refptr<SocketParams>& params, 671 RequestPriority priority, 672 ClientSocketHandle* handle, 673 const CompletionCallback& callback, 674 const BoundNetLog& net_log) { 675 Request* request = 676 new Request(handle, callback, priority, 677 internal::ClientSocketPoolBaseHelper::NORMAL, 678 params->ignore_limits(), 679 params, net_log); 680 return helper_.RequestSocket(group_name, request); 681 } 682 683 // RequestSockets bundles up the parameters into a Request and then forwards 684 // to ClientSocketPoolBaseHelper::RequestSockets(). Note that it assigns the 685 // priority to DEFAULT_PRIORITY and specifies the NO_IDLE_SOCKETS flag. 686 void RequestSockets(const std::string& group_name, 687 const scoped_refptr<SocketParams>& params, 688 int num_sockets, 689 const BoundNetLog& net_log) { 690 const Request request(NULL /* no handle */, 691 CompletionCallback(), 692 DEFAULT_PRIORITY, 693 internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS, 694 params->ignore_limits(), 695 params, 696 net_log); 697 helper_.RequestSockets(group_name, request, num_sockets); 698 } 699 700 void CancelRequest(const std::string& group_name, 701 ClientSocketHandle* handle) { 702 return helper_.CancelRequest(group_name, handle); 703 } 704 705 void ReleaseSocket(const std::string& group_name, StreamSocket* socket, 706 int id) { 707 return helper_.ReleaseSocket(group_name, socket, id); 708 } 709 710 void FlushWithError(int error) { helper_.FlushWithError(error); } 711 712 bool IsStalled() const { return helper_.IsStalled(); } 713 714 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } 715 716 int idle_socket_count() const { return helper_.idle_socket_count(); } 717 718 int IdleSocketCountInGroup(const std::string& group_name) const { 719 return helper_.IdleSocketCountInGroup(group_name); 720 } 721 722 LoadState GetLoadState(const std::string& group_name, 723 const ClientSocketHandle* handle) const { 724 return helper_.GetLoadState(group_name, handle); 725 } 726 727 virtual void OnConnectJobComplete(int result, ConnectJob* job) { 728 return helper_.OnConnectJobComplete(result, job); 729 } 730 731 int NumUnassignedConnectJobsInGroup(const std::string& group_name) const { 732 return helper_.NumUnassignedConnectJobsInGroup(group_name); 733 } 734 735 int NumConnectJobsInGroup(const std::string& group_name) const { 736 return helper_.NumConnectJobsInGroup(group_name); 737 } 738 739 int NumActiveSocketsInGroup(const std::string& group_name) const { 740 return helper_.NumActiveSocketsInGroup(group_name); 741 } 742 743 bool HasGroup(const std::string& group_name) const { 744 return helper_.HasGroup(group_name); 745 } 746 747 void CleanupIdleSockets(bool force) { 748 return helper_.CleanupIdleSockets(force); 749 } 750 751 base::DictionaryValue* GetInfoAsValue(const std::string& name, 752 const std::string& type) const { 753 return helper_.GetInfoAsValue(name, type); 754 } 755 756 base::TimeDelta ConnectionTimeout() const { 757 return helper_.ConnectionTimeout(); 758 } 759 760 ClientSocketPoolHistograms* histograms() const { 761 return histograms_; 762 } 763 764 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } 765 766 bool CloseOneIdleSocket() { return helper_.CloseOneIdleSocket(); } 767 768 bool CloseOneIdleConnectionInLayeredPool() { 769 return helper_.CloseOneIdleConnectionInLayeredPool(); 770 } 771 772 private: 773 // This adaptor class exists to bridge the 774 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and 775 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the 776 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to 777 // static_cast themselves. 778 class ConnectJobFactoryAdaptor 779 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { 780 public: 781 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory 782 ConnectJobFactory; 783 784 explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory) 785 : connect_job_factory_(connect_job_factory) {} 786 virtual ~ConnectJobFactoryAdaptor() {} 787 788 virtual ConnectJob* NewConnectJob( 789 const std::string& group_name, 790 const internal::ClientSocketPoolBaseHelper::Request& request, 791 ConnectJob::Delegate* delegate) const { 792 const Request* casted_request = static_cast<const Request*>(&request); 793 return connect_job_factory_->NewConnectJob( 794 group_name, *casted_request, delegate); 795 } 796 797 virtual base::TimeDelta ConnectionTimeout() const { 798 return connect_job_factory_->ConnectionTimeout(); 799 } 800 801 const scoped_ptr<ConnectJobFactory> connect_job_factory_; 802 }; 803 804 // Histograms for the pool 805 ClientSocketPoolHistograms* const histograms_; 806 internal::ClientSocketPoolBaseHelper helper_; 807 808 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); 809 }; 810 811 } // namespace net 812 813 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 814