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 // Called to enable/disable cleaning up idle sockets. When enabled, 286 // idle sockets that have been around for longer than a period defined 287 // by kCleanupInterval are cleaned up using a timer. Otherwise they are 288 // closed next time client makes a request. This may reduce network 289 // activity and power consumption. 290 static bool cleanup_timer_enabled(); 291 static bool set_cleanup_timer_enabled(bool enabled); 292 293 // Closes all idle sockets if |force| is true. Else, only closes idle 294 // sockets that timed out or can't be reused. Made public for testing. 295 void CleanupIdleSockets(bool force); 296 297 // See ClientSocketPool::GetInfoAsValue for documentation on this function. 298 DictionaryValue* GetInfoAsValue(const std::string& name, 299 const std::string& type) const; 300 ConnectionTimeout()301 base::TimeDelta ConnectionTimeout() const { 302 return connect_job_factory_->ConnectionTimeout(); 303 } 304 305 static bool connect_backup_jobs_enabled(); 306 static bool set_connect_backup_jobs_enabled(bool enabled); 307 308 void EnableConnectBackupJobs(); 309 310 // ConnectJob::Delegate methods: 311 virtual void OnConnectJobComplete(int result, ConnectJob* job); 312 313 // NetworkChangeNotifier::IPAddressObserver methods: 314 virtual void OnIPAddressChanged(); 315 316 private: 317 friend class base::RefCounted<ClientSocketPoolBaseHelper>; 318 319 // Entry for a persistent socket which became idle at time |start_time|. 320 struct IdleSocket { IdleSocketIdleSocket321 IdleSocket() : socket(NULL) {} 322 323 // An idle socket should be removed if it can't be reused, or has been idle 324 // for too long. |now| is the current time value (TimeTicks::Now()). 325 // |timeout| is the length of time to wait before timing out an idle socket. 326 // 327 // An idle socket can't be reused if it is disconnected or has received 328 // data unexpectedly (hence no longer idle). The unread data would be 329 // mistaken for the beginning of the next response if we were to reuse the 330 // socket for a new request. 331 bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const; 332 333 ClientSocket* socket; 334 base::TimeTicks start_time; 335 }; 336 337 typedef std::deque<const Request* > RequestQueue; 338 typedef std::map<const ClientSocketHandle*, const Request*> RequestMap; 339 340 // A Group is allocated per group_name when there are idle sockets or pending 341 // requests. Otherwise, the Group object is removed from the map. 342 // |active_socket_count| tracks the number of sockets held by clients. 343 class Group { 344 public: 345 Group(); 346 ~Group(); 347 IsEmpty()348 bool IsEmpty() const { 349 return active_socket_count_ == 0 && idle_sockets_.empty() && 350 jobs_.empty() && pending_requests_.empty(); 351 } 352 HasAvailableSocketSlot(int max_sockets_per_group)353 bool HasAvailableSocketSlot(int max_sockets_per_group) const { 354 return NumActiveSocketSlots() < max_sockets_per_group; 355 } 356 NumActiveSocketSlots()357 int NumActiveSocketSlots() const { 358 return active_socket_count_ + static_cast<int>(jobs_.size()) + 359 static_cast<int>(idle_sockets_.size()); 360 } 361 IsStalled(int max_sockets_per_group)362 bool IsStalled(int max_sockets_per_group) const { 363 return HasAvailableSocketSlot(max_sockets_per_group) && 364 pending_requests_.size() > jobs_.size(); 365 } 366 TopPendingPriority()367 RequestPriority TopPendingPriority() const { 368 return pending_requests_.front()->priority(); 369 } 370 HasBackupJob()371 bool HasBackupJob() const { return !method_factory_.empty(); } 372 CleanupBackupJob()373 void CleanupBackupJob() { 374 method_factory_.RevokeAll(); 375 } 376 377 // Set a timer to create a backup socket if it takes too long to create one. 378 void StartBackupSocketTimer(const std::string& group_name, 379 ClientSocketPoolBaseHelper* pool); 380 381 // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so, 382 // uses it. Returns true on success. Otherwise, returns false. 383 bool TryToUsePreconnectConnectJob(); 384 AddJob(ConnectJob * job)385 void AddJob(ConnectJob* job) { jobs_.insert(job); } RemoveJob(ConnectJob * job)386 void RemoveJob(ConnectJob* job) { jobs_.erase(job); } 387 void RemoveAllJobs(); 388 IncrementActiveSocketCount()389 void IncrementActiveSocketCount() { active_socket_count_++; } DecrementActiveSocketCount()390 void DecrementActiveSocketCount() { active_socket_count_--; } 391 jobs()392 const std::set<ConnectJob*>& jobs() const { return jobs_; } idle_sockets()393 const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; } pending_requests()394 const RequestQueue& pending_requests() const { return pending_requests_; } active_socket_count()395 int active_socket_count() const { return active_socket_count_; } mutable_pending_requests()396 RequestQueue* mutable_pending_requests() { return &pending_requests_; } mutable_idle_sockets()397 std::list<IdleSocket>* mutable_idle_sockets() { return &idle_sockets_; } 398 399 private: 400 // Called when the backup socket timer fires. 401 void OnBackupSocketTimerFired( 402 std::string group_name, 403 ClientSocketPoolBaseHelper* pool); 404 405 std::list<IdleSocket> idle_sockets_; 406 std::set<ConnectJob*> jobs_; 407 RequestQueue pending_requests_; 408 int active_socket_count_; // number of active sockets used by clients 409 // A factory to pin the backup_job tasks. 410 ScopedRunnableMethodFactory<Group> method_factory_; 411 }; 412 413 typedef std::map<std::string, Group*> GroupMap; 414 415 typedef std::set<ConnectJob*> ConnectJobSet; 416 417 struct CallbackResultPair { CallbackResultPairCallbackResultPair418 CallbackResultPair() : callback(NULL), result(OK) {} CallbackResultPairCallbackResultPair419 CallbackResultPair(CompletionCallback* callback_in, int result_in) 420 : callback(callback_in), result(result_in) {} 421 422 CompletionCallback* callback; 423 int result; 424 }; 425 426 typedef std::map<const ClientSocketHandle*, CallbackResultPair> 427 PendingCallbackMap; 428 429 static void InsertRequestIntoQueue(const Request* r, 430 RequestQueue* pending_requests); 431 static const Request* RemoveRequestFromQueue(const RequestQueue::iterator& it, 432 Group* group); 433 434 Group* GetOrCreateGroup(const std::string& group_name); 435 void RemoveGroup(const std::string& group_name); 436 void RemoveGroup(GroupMap::iterator it); 437 438 // Called when the number of idle sockets changes. 439 void IncrementIdleCount(); 440 void DecrementIdleCount(); 441 442 // Start cleanup timer for idle sockets. 443 void StartIdleSocketTimer(); 444 445 // Scans the group map for groups which have an available socket slot and 446 // at least one pending request. Returns true if any groups are stalled, and 447 // if so, fills |group| and |group_name| with data of the stalled group 448 // having highest priority. 449 bool FindTopStalledGroup(Group** group, std::string* group_name); 450 451 // Called when timer_ fires. This method scans the idle sockets removing 452 // sockets that timed out or can't be reused. OnCleanupTimerFired()453 void OnCleanupTimerFired() { 454 CleanupIdleSockets(false); 455 } 456 457 // Removes |job| from |connect_job_set_|. Also updates |group| if non-NULL. 458 void RemoveConnectJob(ConnectJob* job, Group* group); 459 460 // Tries to see if we can handle any more requests for |group|. 461 void OnAvailableSocketSlot(const std::string& group_name, Group* group); 462 463 // Process a pending socket request for a group. 464 void ProcessPendingRequest(const std::string& group_name, Group* group); 465 466 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. 467 void HandOutSocket(ClientSocket* socket, 468 bool reused, 469 ClientSocketHandle* handle, 470 base::TimeDelta time_idle, 471 Group* group, 472 const BoundNetLog& net_log); 473 474 // Adds |socket| to the list of idle sockets for |group|. 475 void AddIdleSocket(ClientSocket* socket, Group* group); 476 477 // Iterates through |group_map_|, canceling all ConnectJobs and deleting 478 // groups if they are no longer needed. 479 void CancelAllConnectJobs(); 480 481 // Iterates through |group_map_|, posting ERR_ABORTED callbacks for all 482 // requests, and then deleting groups if they are no longer needed. 483 void AbortAllRequests(); 484 485 // Returns true if we can't create any more sockets due to the total limit. 486 bool ReachedMaxSocketsLimit() const; 487 488 // This is the internal implementation of RequestSocket(). It differs in that 489 // it does not handle logging into NetLog of the queueing status of 490 // |request|. 491 int RequestSocketInternal(const std::string& group_name, 492 const Request* request); 493 494 // Assigns an idle socket for the group to the request. 495 // Returns |true| if an idle socket is available, false otherwise. 496 bool AssignIdleSocketToGroup(const Request* request, Group* group); 497 498 static void LogBoundConnectJobToRequest( 499 const NetLog::Source& connect_job_source, const Request* request); 500 501 // Closes one idle socket. Picks the first one encountered. 502 // TODO(willchan): Consider a better algorithm for doing this. Perhaps we 503 // should keep an ordered list of idle sockets, and close them in order. 504 // Requires maintaining more state. It's not clear if it's worth it since 505 // I'm not sure if we hit this situation often. 506 void CloseOneIdleSocket(); 507 508 // Same as CloseOneIdleSocket() except it won't close an idle socket in 509 // |group|. If |group| is NULL, it is ignored. Returns true if it closed a 510 // socket. 511 bool CloseOneIdleSocketExceptInGroup(const Group* group); 512 513 // Checks if there are stalled socket groups that should be notified 514 // for possible wakeup. 515 void CheckForStalledSocketGroups(); 516 517 // Posts a task to call InvokeUserCallback() on the next iteration through the 518 // current message loop. Inserts |callback| into |pending_callback_map_|, 519 // keyed by |handle|. 520 void InvokeUserCallbackLater( 521 ClientSocketHandle* handle, CompletionCallback* callback, int rv); 522 523 // Invokes the user callback for |handle|. By the time this task has run, 524 // it's possible that the request has been cancelled, so |handle| may not 525 // exist in |pending_callback_map_|. We look up the callback and result code 526 // in |pending_callback_map_|. 527 void InvokeUserCallback(ClientSocketHandle* handle); 528 529 GroupMap group_map_; 530 531 // Map of the ClientSocketHandles for which we have a pending Task to invoke a 532 // callback. This is necessary since, before we invoke said callback, it's 533 // possible that the request is cancelled. 534 PendingCallbackMap pending_callback_map_; 535 536 // Timer used to periodically prune idle sockets that timed out or can't be 537 // reused. 538 base::RepeatingTimer<ClientSocketPoolBaseHelper> timer_; 539 540 // The total number of idle sockets in the system. 541 int idle_socket_count_; 542 543 // Number of connecting sockets across all groups. 544 int connecting_socket_count_; 545 546 // Number of connected sockets we handed out across all groups. 547 int handed_out_socket_count_; 548 549 // The maximum total number of sockets. See ReachedMaxSocketsLimit. 550 const int max_sockets_; 551 552 // The maximum number of sockets kept per group. 553 const int max_sockets_per_group_; 554 555 // Whether to use timer to cleanup idle sockets. 556 bool use_cleanup_timer_; 557 558 // The time to wait until closing idle sockets. 559 const base::TimeDelta unused_idle_socket_timeout_; 560 const base::TimeDelta used_idle_socket_timeout_; 561 562 const scoped_ptr<ConnectJobFactory> connect_job_factory_; 563 564 // TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool 565 bool connect_backup_jobs_enabled_; 566 567 // A unique id for the pool. It gets incremented every time we Flush() the 568 // pool. This is so that when sockets get released back to the pool, we can 569 // make sure that they are discarded rather than reused. 570 int pool_generation_number_; 571 572 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; 573 574 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); 575 }; 576 577 } // namespace internal 578 579 // The maximum duration, in seconds, to keep used idle persistent sockets alive. 580 static const int kUsedIdleSocketTimeout = 300; // 5 minutes 581 582 template <typename SocketParams> 583 class ClientSocketPoolBase { 584 public: 585 class Request : public internal::ClientSocketPoolBaseHelper::Request { 586 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)587 Request(ClientSocketHandle* handle, 588 CompletionCallback* callback, 589 RequestPriority priority, 590 internal::ClientSocketPoolBaseHelper::Flags flags, 591 bool ignore_limits, 592 const scoped_refptr<SocketParams>& params, 593 const BoundNetLog& net_log 594 #ifdef ANDROID 595 , bool valid_uid, int calling_uid 596 #endif 597 ) 598 : internal::ClientSocketPoolBaseHelper::Request( 599 handle, callback, priority, ignore_limits, 600 flags, net_log 601 #ifdef ANDROID 602 , valid_uid, calling_uid 603 #endif 604 ), 605 params_(params) {} 606 params()607 const scoped_refptr<SocketParams>& params() const { return params_; } 608 609 private: 610 const scoped_refptr<SocketParams> params_; 611 }; 612 613 class ConnectJobFactory { 614 public: ConnectJobFactory()615 ConnectJobFactory() {} ~ConnectJobFactory()616 virtual ~ConnectJobFactory() {} 617 618 virtual ConnectJob* NewConnectJob( 619 const std::string& group_name, 620 const Request& request, 621 ConnectJob::Delegate* delegate) const = 0; 622 623 virtual base::TimeDelta ConnectionTimeout() const = 0; 624 625 private: 626 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); 627 }; 628 629 // |max_sockets| is the maximum number of sockets to be maintained by this 630 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of 631 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how 632 // long to leave an unused idle socket open before closing it. 633 // |used_idle_socket_timeout| specifies how long to leave a previously used 634 // 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)635 ClientSocketPoolBase( 636 int max_sockets, 637 int max_sockets_per_group, 638 ClientSocketPoolHistograms* histograms, 639 base::TimeDelta unused_idle_socket_timeout, 640 base::TimeDelta used_idle_socket_timeout, 641 ConnectJobFactory* connect_job_factory) 642 : histograms_(histograms), 643 helper_(max_sockets, max_sockets_per_group, 644 unused_idle_socket_timeout, used_idle_socket_timeout, 645 new ConnectJobFactoryAdaptor(connect_job_factory)) {} 646 ~ClientSocketPoolBase()647 virtual ~ClientSocketPoolBase() {} 648 649 // These member functions simply forward to ClientSocketPoolBaseHelper. 650 651 // RequestSocket bundles up the parameters into a Request and then forwards to 652 // ClientSocketPoolBaseHelper::RequestSocket(). RequestSocket(const std::string & group_name,const scoped_refptr<SocketParams> & params,RequestPriority priority,ClientSocketHandle * handle,CompletionCallback * callback,const BoundNetLog & net_log)653 int RequestSocket(const std::string& group_name, 654 const scoped_refptr<SocketParams>& params, 655 RequestPriority priority, 656 ClientSocketHandle* handle, 657 CompletionCallback* callback, 658 const BoundNetLog& net_log) { 659 #ifdef ANDROID 660 uid_t calling_uid = 0; 661 bool valid_uid = params->getUID(&calling_uid); 662 #endif 663 Request* request = 664 new Request(handle, callback, priority, 665 internal::ClientSocketPoolBaseHelper::NORMAL, 666 params->ignore_limits(), 667 params, net_log 668 #ifdef ANDROID 669 , valid_uid, calling_uid 670 #endif 671 ); 672 return helper_.RequestSocket(group_name, request); 673 } 674 675 // RequestSockets bundles up the parameters into a Request and then forwards 676 // to ClientSocketPoolBaseHelper::RequestSockets(). Note that it assigns the 677 // 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)678 void RequestSockets(const std::string& group_name, 679 const scoped_refptr<SocketParams>& params, 680 int num_sockets, 681 const BoundNetLog& net_log) { 682 #ifdef ANDROID 683 uid_t calling_uid = 0; 684 bool valid_uid = params->getUID(&calling_uid); 685 #endif 686 const Request request(NULL /* no handle */, 687 NULL /* no callback */, 688 LOWEST, 689 internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS, 690 params->ignore_limits(), 691 params, 692 net_log 693 #ifdef ANDROID 694 , valid_uid, calling_uid 695 #endif 696 ); 697 helper_.RequestSockets(group_name, request, num_sockets); 698 } 699 CancelRequest(const std::string & group_name,ClientSocketHandle * handle)700 void CancelRequest(const std::string& group_name, 701 ClientSocketHandle* handle) { 702 return helper_.CancelRequest(group_name, handle); 703 } 704 ReleaseSocket(const std::string & group_name,ClientSocket * socket,int id)705 void ReleaseSocket(const std::string& group_name, ClientSocket* socket, 706 int id) { 707 return helper_.ReleaseSocket(group_name, socket, id); 708 } 709 CloseIdleSockets()710 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } 711 idle_socket_count()712 int idle_socket_count() const { return helper_.idle_socket_count(); } 713 IdleSocketCountInGroup(const std::string & group_name)714 int IdleSocketCountInGroup(const std::string& group_name) const { 715 return helper_.IdleSocketCountInGroup(group_name); 716 } 717 GetLoadState(const std::string & group_name,const ClientSocketHandle * handle)718 LoadState GetLoadState(const std::string& group_name, 719 const ClientSocketHandle* handle) const { 720 return helper_.GetLoadState(group_name, handle); 721 } 722 OnConnectJobComplete(int result,ConnectJob * job)723 virtual void OnConnectJobComplete(int result, ConnectJob* job) { 724 return helper_.OnConnectJobComplete(result, job); 725 } 726 NumConnectJobsInGroup(const std::string & group_name)727 int NumConnectJobsInGroup(const std::string& group_name) const { 728 return helper_.NumConnectJobsInGroup(group_name); 729 } 730 NumActiveSocketsInGroup(const std::string & group_name)731 int NumActiveSocketsInGroup(const std::string& group_name) const { 732 return helper_.NumActiveSocketsInGroup(group_name); 733 } 734 HasGroup(const std::string & group_name)735 bool HasGroup(const std::string& group_name) const { 736 return helper_.HasGroup(group_name); 737 } 738 CleanupIdleSockets(bool force)739 void CleanupIdleSockets(bool force) { 740 return helper_.CleanupIdleSockets(force); 741 } 742 GetInfoAsValue(const std::string & name,const std::string & type)743 DictionaryValue* GetInfoAsValue(const std::string& name, 744 const std::string& type) const { 745 return helper_.GetInfoAsValue(name, type); 746 } 747 ConnectionTimeout()748 base::TimeDelta ConnectionTimeout() const { 749 return helper_.ConnectionTimeout(); 750 } 751 histograms()752 ClientSocketPoolHistograms* histograms() const { 753 return histograms_; 754 } 755 EnableConnectBackupJobs()756 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } 757 Flush()758 void Flush() { helper_.Flush(); } 759 760 private: 761 // This adaptor class exists to bridge the 762 // internal::ClientSocketPoolBaseHelper::ConnectJobFactory and 763 // ClientSocketPoolBase::ConnectJobFactory types, allowing clients to use the 764 // typesafe ClientSocketPoolBase::ConnectJobFactory, rather than having to 765 // static_cast themselves. 766 class ConnectJobFactoryAdaptor 767 : public internal::ClientSocketPoolBaseHelper::ConnectJobFactory { 768 public: 769 typedef typename ClientSocketPoolBase<SocketParams>::ConnectJobFactory 770 ConnectJobFactory; 771 ConnectJobFactoryAdaptor(ConnectJobFactory * connect_job_factory)772 explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory) 773 : connect_job_factory_(connect_job_factory) {} ~ConnectJobFactoryAdaptor()774 virtual ~ConnectJobFactoryAdaptor() {} 775 NewConnectJob(const std::string & group_name,const internal::ClientSocketPoolBaseHelper::Request & request,ConnectJob::Delegate * delegate)776 virtual ConnectJob* NewConnectJob( 777 const std::string& group_name, 778 const internal::ClientSocketPoolBaseHelper::Request& request, 779 ConnectJob::Delegate* delegate) const { 780 const Request* casted_request = static_cast<const Request*>(&request); 781 return connect_job_factory_->NewConnectJob( 782 group_name, *casted_request, delegate); 783 } 784 ConnectionTimeout()785 virtual base::TimeDelta ConnectionTimeout() const { 786 return connect_job_factory_->ConnectionTimeout(); 787 } 788 789 const scoped_ptr<ConnectJobFactory> connect_job_factory_; 790 }; 791 792 // Histograms for the pool 793 ClientSocketPoolHistograms* const histograms_; 794 internal::ClientSocketPoolBaseHelper helper_; 795 796 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); 797 }; 798 799 } // namespace net 800 801 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 802