OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 20 matching lines...) Expand all Loading... |
31 #include "base/compiler_specific.h" | 31 #include "base/compiler_specific.h" |
32 #include "base/ref_counted.h" | 32 #include "base/ref_counted.h" |
33 #include "base/scoped_ptr.h" | 33 #include "base/scoped_ptr.h" |
34 #include "base/task.h" | 34 #include "base/task.h" |
35 #include "base/time.h" | 35 #include "base/time.h" |
36 #include "base/timer.h" | 36 #include "base/timer.h" |
37 #include "net/base/address_list.h" | 37 #include "net/base/address_list.h" |
38 #include "net/base/completion_callback.h" | 38 #include "net/base/completion_callback.h" |
39 #include "net/base/load_states.h" | 39 #include "net/base/load_states.h" |
40 #include "net/base/net_errors.h" | 40 #include "net/base/net_errors.h" |
| 41 #include "net/base/net_log.h" |
41 #include "net/base/network_change_notifier.h" | 42 #include "net/base/network_change_notifier.h" |
42 #include "net/base/request_priority.h" | 43 #include "net/base/request_priority.h" |
43 #include "net/socket/client_socket.h" | 44 #include "net/socket/client_socket.h" |
44 #include "net/socket/client_socket_pool.h" | 45 #include "net/socket/client_socket_pool.h" |
45 | 46 |
46 namespace net { | 47 namespace net { |
47 | 48 |
48 class ClientSocketHandle; | 49 class ClientSocketHandle; |
49 class LoadLog; | |
50 | 50 |
51 // ConnectJob provides an abstract interface for "connecting" a socket. | 51 // ConnectJob provides an abstract interface for "connecting" a socket. |
52 // The connection may involve host resolution, tcp connection, ssl connection, | 52 // The connection may involve host resolution, tcp connection, ssl connection, |
53 // etc. | 53 // etc. |
54 class ConnectJob { | 54 class ConnectJob { |
55 public: | 55 public: |
56 class Delegate { | 56 class Delegate { |
57 public: | 57 public: |
58 Delegate() {} | 58 Delegate() {} |
59 virtual ~Delegate() {} | 59 virtual ~Delegate() {} |
60 | 60 |
61 // Alerts the delegate that the connection completed. | 61 // Alerts the delegate that the connection completed. |
62 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; | 62 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; |
63 | 63 |
64 private: | 64 private: |
65 DISALLOW_COPY_AND_ASSIGN(Delegate); | 65 DISALLOW_COPY_AND_ASSIGN(Delegate); |
66 }; | 66 }; |
67 | 67 |
68 // A |timeout_duration| of 0 corresponds to no timeout. | 68 // A |timeout_duration| of 0 corresponds to no timeout. |
69 ConnectJob(const std::string& group_name, | 69 ConnectJob(const std::string& group_name, |
70 base::TimeDelta timeout_duration, | 70 base::TimeDelta timeout_duration, |
71 Delegate* delegate, | 71 Delegate* delegate, |
72 LoadLog* load_log); | 72 const BoundNetLog& net_log); |
73 virtual ~ConnectJob(); | 73 virtual ~ConnectJob(); |
74 | 74 |
75 // Accessors | 75 // Accessors |
76 const std::string& group_name() const { return group_name_; } | 76 const std::string& group_name() const { return group_name_; } |
77 LoadLog* load_log() { return load_log_; } | 77 const BoundNetLog& net_log() { return net_log_; } |
78 | 78 |
79 // Releases |socket_| to the client. On connection error, this should return | 79 // Releases |socket_| to the client. On connection error, this should return |
80 // NULL. | 80 // NULL. |
81 ClientSocket* ReleaseSocket() { return socket_.release(); } | 81 ClientSocket* ReleaseSocket() { return socket_.release(); } |
82 | 82 |
83 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it | 83 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it |
84 // cannot complete synchronously without blocking, or another net error code | 84 // cannot complete synchronously without blocking, or another net error code |
85 // on error. In asynchronous completion, the ConnectJob will notify | 85 // on error. In asynchronous completion, the ConnectJob will notify |
86 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous | 86 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous |
87 // completion, ReleaseSocket() can be called to acquire the connected socket | 87 // completion, ReleaseSocket() can be called to acquire the connected socket |
(...skipping 12 matching lines...) Expand all Loading... |
100 | 100 |
101 // Alerts the delegate that the ConnectJob has timed out. | 101 // Alerts the delegate that the ConnectJob has timed out. |
102 void OnTimeout(); | 102 void OnTimeout(); |
103 | 103 |
104 const std::string group_name_; | 104 const std::string group_name_; |
105 const base::TimeDelta timeout_duration_; | 105 const base::TimeDelta timeout_duration_; |
106 // Timer to abort jobs that take too long. | 106 // Timer to abort jobs that take too long. |
107 base::OneShotTimer<ConnectJob> timer_; | 107 base::OneShotTimer<ConnectJob> timer_; |
108 Delegate* delegate_; | 108 Delegate* delegate_; |
109 scoped_ptr<ClientSocket> socket_; | 109 scoped_ptr<ClientSocket> socket_; |
110 scoped_refptr<LoadLog> load_log_; | 110 BoundNetLog net_log_; |
111 | 111 |
112 DISALLOW_COPY_AND_ASSIGN(ConnectJob); | 112 DISALLOW_COPY_AND_ASSIGN(ConnectJob); |
113 }; | 113 }; |
114 | 114 |
115 namespace internal { | 115 namespace internal { |
116 | 116 |
117 // ClientSocketPoolBaseHelper is an internal class that implements almost all | 117 // ClientSocketPoolBaseHelper is an internal class that implements almost all |
118 // the functionality from ClientSocketPoolBase without using templates. | 118 // the functionality from ClientSocketPoolBase without using templates. |
119 // ClientSocketPoolBase adds templated definitions built on top of | 119 // ClientSocketPoolBase adds templated definitions built on top of |
120 // ClientSocketPoolBaseHelper. This class is not for external use, please use | 120 // ClientSocketPoolBaseHelper. This class is not for external use, please use |
121 // ClientSocketPoolBase instead. | 121 // ClientSocketPoolBase instead. |
122 class ClientSocketPoolBaseHelper | 122 class ClientSocketPoolBaseHelper |
123 : public base::RefCounted<ClientSocketPoolBaseHelper>, | 123 : public base::RefCounted<ClientSocketPoolBaseHelper>, |
124 public ConnectJob::Delegate, | 124 public ConnectJob::Delegate, |
125 public NetworkChangeNotifier::Observer { | 125 public NetworkChangeNotifier::Observer { |
126 public: | 126 public: |
127 class Request { | 127 class Request { |
128 public: | 128 public: |
129 Request(ClientSocketHandle* handle, | 129 Request(ClientSocketHandle* handle, |
130 CompletionCallback* callback, | 130 CompletionCallback* callback, |
131 RequestPriority priority, | 131 RequestPriority priority, |
132 LoadLog* load_log); | 132 const BoundNetLog& net_log); |
133 | 133 |
134 virtual ~Request(); | 134 virtual ~Request(); |
135 | 135 |
136 ClientSocketHandle* handle() const { return handle_; } | 136 ClientSocketHandle* handle() const { return handle_; } |
137 CompletionCallback* callback() const { return callback_; } | 137 CompletionCallback* callback() const { return callback_; } |
138 RequestPriority priority() const { return priority_; } | 138 RequestPriority priority() const { return priority_; } |
139 LoadLog* load_log() const { return load_log_.get(); } | 139 const BoundNetLog& net_log() const { return net_log_; } |
140 | 140 |
141 private: | 141 private: |
142 ClientSocketHandle* const handle_; | 142 ClientSocketHandle* const handle_; |
143 CompletionCallback* const callback_; | 143 CompletionCallback* const callback_; |
144 const RequestPriority priority_; | 144 const RequestPriority priority_; |
145 const scoped_refptr<LoadLog> load_log_; | 145 BoundNetLog net_log_; |
146 | 146 |
147 DISALLOW_COPY_AND_ASSIGN(Request); | 147 DISALLOW_COPY_AND_ASSIGN(Request); |
148 }; | 148 }; |
149 | 149 |
150 class ConnectJobFactory { | 150 class ConnectJobFactory { |
151 public: | 151 public: |
152 ConnectJobFactory() {} | 152 ConnectJobFactory() {} |
153 virtual ~ConnectJobFactory() {} | 153 virtual ~ConnectJobFactory() {} |
154 | 154 |
155 virtual ConnectJob* NewConnectJob( | 155 virtual ConnectJob* NewConnectJob( |
156 const std::string& group_name, | 156 const std::string& group_name, |
157 const Request& request, | 157 const Request& request, |
158 ConnectJob::Delegate* delegate, | 158 ConnectJob::Delegate* delegate, |
159 LoadLog* load_log) const = 0; | 159 const BoundNetLog& net_log) const = 0; |
160 | 160 |
161 private: | 161 private: |
162 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 162 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
163 }; | 163 }; |
164 | 164 |
165 ClientSocketPoolBaseHelper( | 165 ClientSocketPoolBaseHelper( |
166 int max_sockets, | 166 int max_sockets, |
167 int max_sockets_per_group, | 167 int max_sockets_per_group, |
168 base::TimeDelta unused_idle_socket_timeout, | 168 base::TimeDelta unused_idle_socket_timeout, |
169 base::TimeDelta used_idle_socket_timeout, | 169 base::TimeDelta used_idle_socket_timeout, |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 | 348 |
349 // Process a request from a group's pending_requests queue. | 349 // Process a request from a group's pending_requests queue. |
350 void ProcessPendingRequest(const std::string& group_name, Group* group); | 350 void ProcessPendingRequest(const std::string& group_name, Group* group); |
351 | 351 |
352 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. | 352 // Assigns |socket| to |handle| and updates |group|'s counters appropriately. |
353 void HandOutSocket(ClientSocket* socket, | 353 void HandOutSocket(ClientSocket* socket, |
354 bool reused, | 354 bool reused, |
355 ClientSocketHandle* handle, | 355 ClientSocketHandle* handle, |
356 base::TimeDelta time_idle, | 356 base::TimeDelta time_idle, |
357 Group* group, | 357 Group* group, |
358 LoadLog* load_log); | 358 const BoundNetLog& net_log); |
359 | 359 |
360 // Adds |socket| to the list of idle sockets for |group|. |used| indicates | 360 // Adds |socket| to the list of idle sockets for |group|. |used| indicates |
361 // whether or not the socket has previously been used. | 361 // whether or not the socket has previously been used. |
362 void AddIdleSocket(ClientSocket* socket, bool used, Group* group); | 362 void AddIdleSocket(ClientSocket* socket, bool used, Group* group); |
363 | 363 |
364 // Iterates through |connect_job_map_|, canceling all ConnectJobs. | 364 // Iterates through |connect_job_map_|, canceling all ConnectJobs. |
365 // Afterwards, it iterates through all groups and deletes them if they are no | 365 // Afterwards, it iterates through all groups and deletes them if they are no |
366 // longer needed. | 366 // longer needed. |
367 void CancelAllConnectJobs(); | 367 void CancelAllConnectJobs(); |
368 | 368 |
369 // Returns true if we can't create any more sockets due to the total limit. | 369 // Returns true if we can't create any more sockets due to the total limit. |
370 // TODO(phajdan.jr): Also take idle sockets into account. | 370 // TODO(phajdan.jr): Also take idle sockets into account. |
371 bool ReachedMaxSocketsLimit() const; | 371 bool ReachedMaxSocketsLimit() const; |
372 | 372 |
373 // This is the internal implementation of RequestSocket(). It differs in that | 373 // This is the internal implementation of RequestSocket(). It differs in that |
374 // it does not handle logging into LoadLog of the queueing status of | 374 // it does not handle logging into NetLog of the queueing status of |
375 // |request|. | 375 // |request|. |
376 int RequestSocketInternal(const std::string& group_name, | 376 int RequestSocketInternal(const std::string& group_name, |
377 const Request* request); | 377 const Request* request); |
378 | 378 |
379 // Set a timer to create a backup socket if it takes too long to create one. | 379 // Set a timer to create a backup socket if it takes too long to create one. |
380 void StartBackupSocketTimer(const std::string& group_name); | 380 void StartBackupSocketTimer(const std::string& group_name); |
381 | 381 |
382 // Called when the backup socket timer fires. | 382 // Called when the backup socket timer fires. |
383 void OnBackupSocketTimerFired(const std::string& group_name); | 383 void OnBackupSocketTimerFired(const std::string& group_name); |
384 | 384 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 | 443 |
444 template <typename SocketParams> | 444 template <typename SocketParams> |
445 class ClientSocketPoolBase { | 445 class ClientSocketPoolBase { |
446 public: | 446 public: |
447 class Request : public internal::ClientSocketPoolBaseHelper::Request { | 447 class Request : public internal::ClientSocketPoolBaseHelper::Request { |
448 public: | 448 public: |
449 Request(ClientSocketHandle* handle, | 449 Request(ClientSocketHandle* handle, |
450 CompletionCallback* callback, | 450 CompletionCallback* callback, |
451 RequestPriority priority, | 451 RequestPriority priority, |
452 const SocketParams& params, | 452 const SocketParams& params, |
453 LoadLog* load_log) | 453 const BoundNetLog& net_log) |
454 : internal::ClientSocketPoolBaseHelper::Request( | 454 : internal::ClientSocketPoolBaseHelper::Request( |
455 handle, callback, priority, load_log), | 455 handle, callback, priority, net_log), |
456 params_(params) {} | 456 params_(params) {} |
457 | 457 |
458 const SocketParams& params() const { return params_; } | 458 const SocketParams& params() const { return params_; } |
459 | 459 |
460 private: | 460 private: |
461 SocketParams params_; | 461 SocketParams params_; |
462 }; | 462 }; |
463 | 463 |
464 class ConnectJobFactory { | 464 class ConnectJobFactory { |
465 public: | 465 public: |
466 ConnectJobFactory() {} | 466 ConnectJobFactory() {} |
467 virtual ~ConnectJobFactory() {} | 467 virtual ~ConnectJobFactory() {} |
468 | 468 |
469 virtual ConnectJob* NewConnectJob( | 469 virtual ConnectJob* NewConnectJob( |
470 const std::string& group_name, | 470 const std::string& group_name, |
471 const Request& request, | 471 const Request& request, |
472 ConnectJob::Delegate* delegate, | 472 ConnectJob::Delegate* delegate, |
473 LoadLog* load_log) const = 0; | 473 const BoundNetLog& net_log) const = 0; |
474 | 474 |
475 private: | 475 private: |
476 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); | 476 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); |
477 }; | 477 }; |
478 | 478 |
479 // |max_sockets| is the maximum number of sockets to be maintained by this | 479 // |max_sockets| is the maximum number of sockets to be maintained by this |
480 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of | 480 // ClientSocketPool. |max_sockets_per_group| specifies the maximum number of |
481 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how | 481 // sockets a "group" can have. |unused_idle_socket_timeout| specifies how |
482 // long to leave an unused idle socket open before closing it. | 482 // long to leave an unused idle socket open before closing it. |
483 // |used_idle_socket_timeout| specifies how long to leave a previously used | 483 // |used_idle_socket_timeout| specifies how long to leave a previously used |
(...skipping 16 matching lines...) Expand all Loading... |
500 // These member functions simply forward to ClientSocketPoolBaseHelper. | 500 // These member functions simply forward to ClientSocketPoolBaseHelper. |
501 | 501 |
502 // RequestSocket bundles up the parameters into a Request and then forwards to | 502 // RequestSocket bundles up the parameters into a Request and then forwards to |
503 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory | 503 // ClientSocketPoolBaseHelper::RequestSocket(). Note that the memory |
504 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case. | 504 // ownership is transferred in the asynchronous (ERR_IO_PENDING) case. |
505 int RequestSocket(const std::string& group_name, | 505 int RequestSocket(const std::string& group_name, |
506 const SocketParams& params, | 506 const SocketParams& params, |
507 RequestPriority priority, | 507 RequestPriority priority, |
508 ClientSocketHandle* handle, | 508 ClientSocketHandle* handle, |
509 CompletionCallback* callback, | 509 CompletionCallback* callback, |
510 LoadLog* load_log) { | 510 const BoundNetLog& net_log) { |
511 scoped_ptr<Request> request( | 511 scoped_ptr<Request> request( |
512 new Request(handle, callback, priority, params, load_log)); | 512 new Request(handle, callback, priority, params, net_log)); |
513 int rv = helper_->RequestSocket(group_name, request.get()); | 513 int rv = helper_->RequestSocket(group_name, request.get()); |
514 if (rv == ERR_IO_PENDING) | 514 if (rv == ERR_IO_PENDING) |
515 request.release(); | 515 request.release(); |
516 return rv; | 516 return rv; |
517 } | 517 } |
518 | 518 |
519 void CancelRequest(const std::string& group_name, | 519 void CancelRequest(const std::string& group_name, |
520 const ClientSocketHandle* handle) { | 520 const ClientSocketHandle* handle) { |
521 return helper_->CancelRequest(group_name, handle); | 521 return helper_->CancelRequest(group_name, handle); |
522 } | 522 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 | 569 |
570 explicit ConnectJobFactoryAdaptor( | 570 explicit ConnectJobFactoryAdaptor( |
571 ConnectJobFactory* connect_job_factory) | 571 ConnectJobFactory* connect_job_factory) |
572 : connect_job_factory_(connect_job_factory) {} | 572 : connect_job_factory_(connect_job_factory) {} |
573 virtual ~ConnectJobFactoryAdaptor() {} | 573 virtual ~ConnectJobFactoryAdaptor() {} |
574 | 574 |
575 virtual ConnectJob* NewConnectJob( | 575 virtual ConnectJob* NewConnectJob( |
576 const std::string& group_name, | 576 const std::string& group_name, |
577 const internal::ClientSocketPoolBaseHelper::Request& request, | 577 const internal::ClientSocketPoolBaseHelper::Request& request, |
578 ConnectJob::Delegate* delegate, | 578 ConnectJob::Delegate* delegate, |
579 LoadLog* load_log) const { | 579 const BoundNetLog& net_log) const { |
580 const Request* casted_request = static_cast<const Request*>(&request); | 580 const Request* casted_request = static_cast<const Request*>(&request); |
581 return connect_job_factory_->NewConnectJob( | 581 return connect_job_factory_->NewConnectJob( |
582 group_name, *casted_request, delegate, load_log); | 582 group_name, *casted_request, delegate, net_log); |
583 } | 583 } |
584 | 584 |
585 const scoped_ptr<ConnectJobFactory> connect_job_factory_; | 585 const scoped_ptr<ConnectJobFactory> connect_job_factory_; |
586 }; | 586 }; |
587 | 587 |
588 // One might ask why ClientSocketPoolBaseHelper is also refcounted if its | 588 // One might ask why ClientSocketPoolBaseHelper is also refcounted if its |
589 // containing ClientSocketPool is already refcounted. The reason is because | 589 // containing ClientSocketPool is already refcounted. The reason is because |
590 // DoReleaseSocket() posts a task. If ClientSocketPool gets deleted between | 590 // DoReleaseSocket() posts a task. If ClientSocketPool gets deleted between |
591 // the posting of the task and the execution, then we'll hit the DCHECK that | 591 // the posting of the task and the execution, then we'll hit the DCHECK that |
592 // |ClientSocketPoolBaseHelper::group_map_| is empty. | 592 // |ClientSocketPoolBaseHelper::group_map_| is empty. |
593 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; | 593 scoped_refptr<internal::ClientSocketPoolBaseHelper> helper_; |
594 | 594 |
595 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); | 595 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); |
596 }; | 596 }; |
597 | 597 |
598 } // namespace net | 598 } // namespace net |
599 | 599 |
600 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ | 600 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ |
OLD | NEW |