| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // A ClientSocketPoolBase is used to restrict the number of sockets open at | 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. | 6 // a time. It also maintains a list of idle persistent sockets for reuse. |
| 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle | 7 // Subclasses of ClientSocketPool should compose ClientSocketPoolBase to handle |
| 8 // the core logic of (1) restricting the number of active (connected or | 8 // the core logic of (1) restricting the number of active (connected or |
| 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) | 9 // connecting) sockets per "group" (generally speaking, the hostname), (2) |
| 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) | 10 // maintaining a per-group list of idle, persistent sockets for reuse, and (3) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 23 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| 24 #pragma once | 24 #pragma once |
| 25 | 25 |
| 26 #include <deque> | 26 #include <deque> |
| 27 #include <list> | 27 #include <list> |
| 28 #include <map> | 28 #include <map> |
| 29 #include <set> | 29 #include <set> |
| 30 #include <string> | 30 #include <string> |
| 31 | 31 |
| 32 #include "base/basictypes.h" | 32 #include "base/basictypes.h" |
| 33 #include "base/prebind.h" |
| 33 #include "base/ref_counted.h" | 34 #include "base/ref_counted.h" |
| 34 #include "base/scoped_ptr.h" | 35 #include "base/scoped_ptr.h" |
| 35 #include "base/task.h" | 36 #include "base/task.h" |
| 36 #include "base/time.h" | 37 #include "base/time.h" |
| 37 #include "base/timer.h" | 38 #include "base/timer.h" |
| 38 #include "net/base/address_list.h" | 39 #include "net/base/address_list.h" |
| 39 #include "net/base/completion_callback.h" | 40 #include "net/base/completion_callback.h" |
| 40 #include "net/base/load_states.h" | 41 #include "net/base/load_states.h" |
| 41 #include "net/base/net_errors.h" | 42 #include "net/base/net_errors.h" |
| 42 #include "net/base/net_log.h" | 43 #include "net/base/net_log.h" |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 : public ConnectJob::Delegate, | 159 : public ConnectJob::Delegate, |
| 159 public NetworkChangeNotifier::Observer { | 160 public NetworkChangeNotifier::Observer { |
| 160 public: | 161 public: |
| 161 // Used to specify specific behavior for the ClientSocketPool. | 162 // Used to specify specific behavior for the ClientSocketPool. |
| 162 enum Flag { | 163 enum Flag { |
| 163 NORMAL = 0, // Normal behavior. | 164 NORMAL = 0, // Normal behavior. |
| 164 NO_IDLE_SOCKETS = 0x1, // Do not return an idle socket. Create a new one. | 165 NO_IDLE_SOCKETS = 0x1, // Do not return an idle socket. Create a new one. |
| 165 }; | 166 }; |
| 166 | 167 |
| 167 typedef uint32 Flags; | 168 typedef uint32 Flags; |
| 169 typedef base::Thunk<void(int)> Tr1CompletionCallback; |
| 168 | 170 |
| 169 class Request { | 171 class Request { |
| 170 public: | 172 public: |
| 171 Request(ClientSocketHandle* handle, | 173 Request(ClientSocketHandle* handle, |
| 172 CompletionCallback* callback, | 174 Tr1CompletionCallback callback, |
| 173 RequestPriority priority, | 175 RequestPriority priority, |
| 174 Flags flags, | 176 Flags flags, |
| 175 const BoundNetLog& net_log); | 177 const BoundNetLog& net_log); |
| 176 | 178 |
| 177 virtual ~Request(); | 179 virtual ~Request(); |
| 178 | 180 |
| 179 ClientSocketHandle* handle() const { return handle_; } | 181 ClientSocketHandle* handle() const { return handle_; } |
| 180 CompletionCallback* callback() const { return callback_; } | 182 Tr1CompletionCallback callback() const { return callback_; } |
| 181 RequestPriority priority() const { return priority_; } | 183 RequestPriority priority() const { return priority_; } |
| 182 Flags flags() const { return flags_; } | 184 Flags flags() const { return flags_; } |
| 183 const BoundNetLog& net_log() const { return net_log_; } | 185 const BoundNetLog& net_log() const { return net_log_; } |
| 184 | 186 |
| 185 private: | 187 private: |
| 186 ClientSocketHandle* const handle_; | 188 ClientSocketHandle* const handle_; |
| 187 CompletionCallback* const callback_; | 189 Tr1CompletionCallback const callback_; |
| 188 const RequestPriority priority_; | 190 const RequestPriority priority_; |
| 189 const Flags flags_; | 191 const Flags flags_; |
| 190 BoundNetLog net_log_; | 192 BoundNetLog net_log_; |
| 191 | 193 |
| 192 DISALLOW_COPY_AND_ASSIGN(Request); | 194 DISALLOW_COPY_AND_ASSIGN(Request); |
| 193 }; | 195 }; |
| 194 | 196 |
| 195 class ConnectJobFactory { | 197 class ConnectJobFactory { |
| 196 public: | 198 public: |
| 197 ConnectJobFactory() {} | 199 ConnectJobFactory() {} |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 | 341 |
| 340 bool IsStalled(int max_sockets_per_group) const { | 342 bool IsStalled(int max_sockets_per_group) const { |
| 341 return HasAvailableSocketSlot(max_sockets_per_group) && | 343 return HasAvailableSocketSlot(max_sockets_per_group) && |
| 342 pending_requests_.size() > jobs_.size(); | 344 pending_requests_.size() > jobs_.size(); |
| 343 } | 345 } |
| 344 | 346 |
| 345 RequestPriority TopPendingPriority() const { | 347 RequestPriority TopPendingPriority() const { |
| 346 return pending_requests_.front()->priority(); | 348 return pending_requests_.front()->priority(); |
| 347 } | 349 } |
| 348 | 350 |
| 349 bool HasBackupJob() const { return !method_factory_.empty(); } | 351 bool HasBackupJob() const { return !thunk_canceller_.empty(); } |
| 350 | 352 |
| 351 void CleanupBackupJob() { | 353 void CleanupBackupJob() { |
| 352 method_factory_.RevokeAll(); | 354 thunk_canceller_.RevokeAll(); |
| 353 } | 355 } |
| 354 | 356 |
| 355 // Set a timer to create a backup socket if it takes too long to create one. | 357 // Set a timer to create a backup socket if it takes too long to create one. |
| 356 void StartBackupSocketTimer(const std::string& group_name, | 358 void StartBackupSocketTimer(const std::string& group_name, |
| 357 ClientSocketPoolBaseHelper* pool); | 359 ClientSocketPoolBaseHelper* pool); |
| 358 | 360 |
| 359 // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so, | 361 // Searches |jobs_| to see if there's a preconnect ConnectJob, and if so, |
| 360 // uses it. Returns true on success. Otherwise, returns false. | 362 // uses it. Returns true on success. Otherwise, returns false. |
| 361 bool TryToUsePreconnectConnectJob(); | 363 bool TryToUsePreconnectConnectJob(); |
| 362 | 364 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 378 // Called when the backup socket timer fires. | 380 // Called when the backup socket timer fires. |
| 379 void OnBackupSocketTimerFired( | 381 void OnBackupSocketTimerFired( |
| 380 std::string group_name, | 382 std::string group_name, |
| 381 ClientSocketPoolBaseHelper* pool); | 383 ClientSocketPoolBaseHelper* pool); |
| 382 | 384 |
| 383 std::list<IdleSocket> idle_sockets_; | 385 std::list<IdleSocket> idle_sockets_; |
| 384 std::set<ConnectJob*> jobs_; | 386 std::set<ConnectJob*> jobs_; |
| 385 RequestQueue pending_requests_; | 387 RequestQueue pending_requests_; |
| 386 int active_socket_count_; // number of active sockets used by clients | 388 int active_socket_count_; // number of active sockets used by clients |
| 387 // A factory to pin the backup_job tasks. | 389 // A factory to pin the backup_job tasks. |
| 388 ScopedRunnableMethodFactory<Group> method_factory_; | 390 base::ThunkCanceller thunk_canceller_; |
| 389 }; | 391 }; |
| 390 | 392 |
| 391 typedef std::map<std::string, Group*> GroupMap; | 393 typedef std::map<std::string, Group*> GroupMap; |
| 392 | 394 |
| 393 typedef std::set<ConnectJob*> ConnectJobSet; | 395 typedef std::set<ConnectJob*> ConnectJobSet; |
| 394 | 396 |
| 395 struct CallbackResultPair { | 397 struct CallbackResultPair { |
| 396 CallbackResultPair() : callback(NULL), result(OK) {} | 398 CallbackResultPair() : callback(NULL), result(OK) {} |
| 397 CallbackResultPair(CompletionCallback* callback_in, int result_in) | 399 CallbackResultPair(Tr1CompletionCallback callback_in, int result_in) |
| 398 : callback(callback_in), result(result_in) {} | 400 : callback(callback_in), result(result_in) {} |
| 399 | 401 |
| 400 CompletionCallback* callback; | 402 Tr1CompletionCallback callback; |
| 401 int result; | 403 int result; |
| 402 }; | 404 }; |
| 403 | 405 |
| 404 typedef std::map<const ClientSocketHandle*, CallbackResultPair> | 406 typedef std::map<const ClientSocketHandle*, CallbackResultPair> |
| 405 PendingCallbackMap; | 407 PendingCallbackMap; |
| 406 | 408 |
| 407 static void InsertRequestIntoQueue(const Request* r, | 409 static void InsertRequestIntoQueue(const Request* r, |
| 408 RequestQueue* pending_requests); | 410 RequestQueue* pending_requests); |
| 409 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, | 411 static const Request* RemoveRequestFromQueue(RequestQueue::iterator it, |
| 410 Group* group); | 412 Group* group); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 bool CloseOneIdleSocketExceptInGroup(const Group* group); | 488 bool CloseOneIdleSocketExceptInGroup(const Group* group); |
| 487 | 489 |
| 488 // Checks if there are stalled socket groups that should be notified | 490 // Checks if there are stalled socket groups that should be notified |
| 489 // for possible wakeup. | 491 // for possible wakeup. |
| 490 void CheckForStalledSocketGroups(); | 492 void CheckForStalledSocketGroups(); |
| 491 | 493 |
| 492 // Posts a task to call InvokeUserCallback() on the next iteration through the | 494 // Posts a task to call InvokeUserCallback() on the next iteration through the |
| 493 // current message loop. Inserts |callback| into |pending_callback_map_|, | 495 // current message loop. Inserts |callback| into |pending_callback_map_|, |
| 494 // keyed by |handle|. | 496 // keyed by |handle|. |
| 495 void InvokeUserCallbackLater( | 497 void InvokeUserCallbackLater( |
| 496 ClientSocketHandle* handle, CompletionCallback* callback, int rv); | 498 ClientSocketHandle* handle, Tr1CompletionCallback callback, int rv); |
| 497 | 499 |
| 498 // Invokes the user callback for |handle|. By the time this task has run, | 500 // Invokes the user callback for |handle|. By the time this task has run, |
| 499 // it's possible that the request has been cancelled, so |handle| may not | 501 // it's possible that the request has been cancelled, so |handle| may not |
| 500 // exist in |pending_callback_map_|. We look up the callback and result code | 502 // exist in |pending_callback_map_|. We look up the callback and result code |
| 501 // in |pending_callback_map_|. | 503 // in |pending_callback_map_|. |
| 502 void InvokeUserCallback(ClientSocketHandle* handle); | 504 void InvokeUserCallback(ClientSocketHandle* handle); |
| 503 | 505 |
| 504 GroupMap group_map_; | 506 GroupMap group_map_; |
| 505 | 507 |
| 506 // Map of the ClientSocketHandles for which we have a pending Task to invoke a | 508 // Map of the ClientSocketHandles for which we have a pending Task to invoke a |
| (...skipping 27 matching lines...) Expand all Loading... |
| 534 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 536 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
| 535 | 537 |
| 536 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool | 538 // TODO(vandebo) Remove when backup jobs move to TCPClientSocketPool |
| 537 bool connect_backup_jobs_enabled_; | 539 bool connect_backup_jobs_enabled_; |
| 538 | 540 |
| 539 // A unique id for the pool. It gets incremented every time we Flush() the | 541 // A unique id for the pool. It gets incremented every time we Flush() the |
| 540 // pool. This is so that when sockets get released back to the pool, we can | 542 // pool. This is so that when sockets get released back to the pool, we can |
| 541 // make sure that they are discarded rather than reused. | 543 // make sure that they are discarded rather than reused. |
| 542 int pool_generation_number_; | 544 int pool_generation_number_; |
| 543 | 545 |
| 544 ScopedRunnableMethodFactory<ClientSocketPoolBaseHelper> method_factory_; | 546 base::ThunkCanceller thunk_canceller_; |
| 545 | 547 |
| 546 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); | 548 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBaseHelper); |
| 547 }; | 549 }; |
| 548 | 550 |
| 549 } // namespace internal | 551 } // namespace internal |
| 550 | 552 |
| 551 // The maximum duration, in seconds, to keep used idle persistent sockets alive. | 553 // The maximum duration, in seconds, to keep used idle persistent sockets alive. |
| 552 static const int kUsedIdleSocketTimeout = 300; // 5 minutes | 554 static const int kUsedIdleSocketTimeout = 300; // 5 minutes |
| 553 | 555 |
| 554 template <typename SocketParams> | 556 template <typename SocketParams> |
| 555 class ClientSocketPoolBase { | 557 class ClientSocketPoolBase { |
| 556 public: | 558 public: |
| 557 class Request : public internal::ClientSocketPoolBaseHelper::Request { | 559 class Request : public internal::ClientSocketPoolBaseHelper::Request { |
| 558 public: | 560 public: |
| 561 // Do a hacky type transition from the CompletionCallback to |
| 562 // Tr1CompletionCallback by binding the method. This is complicated |
| 563 // by the fact that the function we're wrapper has overloads which |
| 564 // screws up the type inference. This should not be an issue in most |
| 565 // of the our code since overloads are discouraged by the style guide. |
| 566 // |
| 567 // Also note that we don't need to keep a reference to the callback |
| 568 // because the API does not take ownership. One plus of Tr1 callback is |
| 569 // that there is no such ownership ambiguity. But the downside is |
| 570 // refcounting in the callback. |
| 571 static void RunCallback(CompletionCallback* c, int n) { |
| 572 c->Run(n); |
| 573 } |
| 574 |
| 559 Request(ClientSocketHandle* handle, | 575 Request(ClientSocketHandle* handle, |
| 560 CompletionCallback* callback, | 576 CompletionCallback* callback, |
| 561 RequestPriority priority, | 577 RequestPriority priority, |
| 562 internal::ClientSocketPoolBaseHelper::Flags flags, | 578 internal::ClientSocketPoolBaseHelper::Flags flags, |
| 563 const scoped_refptr<SocketParams>& params, | 579 const scoped_refptr<SocketParams>& params, |
| 564 const BoundNetLog& net_log) | 580 const BoundNetLog& net_log) |
| 565 : internal::ClientSocketPoolBaseHelper::Request( | 581 : internal::ClientSocketPoolBaseHelper::Request( |
| 566 handle, callback, priority, flags, net_log), | 582 handle, |
| 583 base::Prebind(&Request::RunCallback, callback), |
| 584 priority, |
| 585 flags, net_log), |
| 567 params_(params) {} | 586 params_(params) {} |
| 568 | 587 |
| 569 const scoped_refptr<SocketParams>& params() const { return params_; } | 588 const scoped_refptr<SocketParams>& params() const { return params_; } |
| 570 | 589 |
| 571 private: | 590 private: |
| 572 const scoped_refptr<SocketParams> params_; | 591 const scoped_refptr<SocketParams> params_; |
| 573 }; | 592 }; |
| 574 | 593 |
| 575 class ConnectJobFactory { | 594 class ConnectJobFactory { |
| 576 public: | 595 public: |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 // Histograms for the pool | 755 // Histograms for the pool |
| 737 ClientSocketPoolHistograms* const histograms_; | 756 ClientSocketPoolHistograms* const histograms_; |
| 738 internal::ClientSocketPoolBaseHelper helper_; | 757 internal::ClientSocketPoolBaseHelper helper_; |
| 739 | 758 |
| 740 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 759 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
| 741 }; | 760 }; |
| 742 | 761 |
| 743 } // namespace net | 762 } // namespace net |
| 744 | 763 |
| 745 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 764 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
| OLD | NEW |