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: 59 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 77 const std::string& group_name() const { return group_name_; } 78 const BoundNetLog& net_log() { return net_log_; } 79 bool is_preconnect() const { return preconnect_state_ != NOT_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. 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). 111 virtual void GetAdditionalErrorState(ClientSocketHandle* handle) {} 112 113 const BoundNetLog& net_log() const { return net_log_; } 114 115 protected: 116 void set_socket(ClientSocket* 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 184 ClientSocketHandle* handle() const { return handle_; } 185 CompletionCallback* callback() const { return callback_; } 186 RequestPriority priority() const { return priority_; } 187 bool ignore_limits() const { return ignore_limits_; } 188 Flags flags() const { return flags_; } 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: 208 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. 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 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 275 int NumConnectJobsInGroup(const std::string& group_name) const { 276 return group_map_.find(group_name)->second->jobs().size(); 277 } 278 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 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 { 313 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 340 bool IsEmpty() const { 341 return active_socket_count_ == 0 && idle_sockets_.empty() && 342 jobs_.empty() && pending_requests_.empty(); 343 } 344 345 bool HasAvailableSocketSlot(int max_sockets_per_group) const { 346 return NumActiveSocketSlots() < max_sockets_per_group; 347 } 348 349 int NumActiveSocketSlots() const { 350 return active_socket_count_ + static_cast<int>(jobs_.size()) + 351 static_cast<int>(idle_sockets_.size()); 352 } 353 354 bool IsStalled(int max_sockets_per_group) const { 355 return HasAvailableSocketSlot(max_sockets_per_group) && 356 pending_requests_.size() > jobs_.size(); 357 } 358 359 RequestPriority TopPendingPriority() const { 360 return pending_requests_.front()->priority(); 361 } 362 363 bool HasBackupJob() const { return !method_factory_.empty(); } 364 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 377 void AddJob(ConnectJob* job) { jobs_.insert(job); } 378 void RemoveJob(ConnectJob* job) { jobs_.erase(job); } 379 void RemoveAllJobs(); 380 381 void IncrementActiveSocketCount() { active_socket_count_++; } 382 void DecrementActiveSocketCount() { active_socket_count_--; } 383 384 const std::set<ConnectJob*>& jobs() const { return jobs_; } 385 const std::list<IdleSocket>& idle_sockets() const { return idle_sockets_; } 386 const RequestQueue& pending_requests() const { return pending_requests_; } 387 int active_socket_count() const { return active_socket_count_; } 388 RequestQueue* mutable_pending_requests() { return &pending_requests_; } 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 { 410 CallbackResultPair() : callback(NULL), result(OK) {} 411 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. 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: 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 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: 601 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. 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 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(). 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. 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 686 void CancelRequest(const std::string& group_name, 687 ClientSocketHandle* handle) { 688 return helper_.CancelRequest(group_name, handle); 689 } 690 691 void ReleaseSocket(const std::string& group_name, ClientSocket* socket, 692 int id) { 693 return helper_.ReleaseSocket(group_name, socket, id); 694 } 695 696 void CloseIdleSockets() { return helper_.CloseIdleSockets(); } 697 698 int idle_socket_count() const { return helper_.idle_socket_count(); } 699 700 int IdleSocketCountInGroup(const std::string& group_name) const { 701 return helper_.IdleSocketCountInGroup(group_name); 702 } 703 704 LoadState GetLoadState(const std::string& group_name, 705 const ClientSocketHandle* handle) const { 706 return helper_.GetLoadState(group_name, handle); 707 } 708 709 virtual void OnConnectJobComplete(int result, ConnectJob* job) { 710 return helper_.OnConnectJobComplete(result, job); 711 } 712 713 int NumConnectJobsInGroup(const std::string& group_name) const { 714 return helper_.NumConnectJobsInGroup(group_name); 715 } 716 717 int NumActiveSocketsInGroup(const std::string& group_name) const { 718 return helper_.NumActiveSocketsInGroup(group_name); 719 } 720 721 bool HasGroup(const std::string& group_name) const { 722 return helper_.HasGroup(group_name); 723 } 724 725 void CleanupIdleSockets(bool force) { 726 return helper_.CleanupIdleSockets(force); 727 } 728 729 DictionaryValue* GetInfoAsValue(const std::string& name, 730 const std::string& type) const { 731 return helper_.GetInfoAsValue(name, type); 732 } 733 734 base::TimeDelta ConnectionTimeout() const { 735 return helper_.ConnectionTimeout(); 736 } 737 738 ClientSocketPoolHistograms* histograms() const { 739 return histograms_; 740 } 741 742 void EnableConnectBackupJobs() { helper_.EnableConnectBackupJobs(); } 743 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 758 explicit ConnectJobFactoryAdaptor(ConnectJobFactory* connect_job_factory) 759 : connect_job_factory_(connect_job_factory) {} 760 virtual ~ConnectJobFactoryAdaptor() {} 761 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 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