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