OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ | 5 #ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ |
6 #define NET_BASE_CLIENT_SOCKET_POOL_H_ | 6 #define NET_BASE_CLIENT_SOCKET_POOL_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <map> | 9 #include <map> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/ref_counted.h" | 12 #include "base/ref_counted.h" |
13 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
14 #include "base/timer.h" | 14 #include "base/timer.h" |
15 #include "net/base/address_list.h" | |
16 #include "net/base/completion_callback.h" | 15 #include "net/base/completion_callback.h" |
17 #include "net/base/host_resolver.h" | |
18 #include "net/base/load_states.h" | |
19 | 16 |
20 namespace net { | 17 namespace net { |
21 | 18 |
22 class ClientSocket; | 19 class ClientSocket; |
23 class ClientSocketFactory; | |
24 class ClientSocketHandle; | 20 class ClientSocketHandle; |
25 | 21 |
26 // A ClientSocketPool is used to restrict the number of sockets open at a time. | 22 // A ClientSocketPool is used to restrict the number of sockets open at a time. |
27 // It also maintains a list of idle persistent sockets. | 23 // It also maintains a list of idle persistent sockets. |
28 // | 24 // |
| 25 // The ClientSocketPool allocates scoped_ptr<ClientSocket> objects, but it is |
| 26 // not responsible for allocating the associated ClientSocket objects. The |
| 27 // consumer must do so if it gets a scoped_ptr<ClientSocket> with a null value. |
| 28 // |
29 class ClientSocketPool : public base::RefCounted<ClientSocketPool> { | 29 class ClientSocketPool : public base::RefCounted<ClientSocketPool> { |
30 public: | 30 public: |
31 ClientSocketPool(int max_sockets_per_group, | 31 explicit ClientSocketPool(int max_sockets_per_group); |
32 ClientSocketFactory* client_socket_factory); | |
33 | 32 |
34 // Requests a connected socket for a group_name. | 33 // Called to request a socket for the given handle. There are three possible |
35 // | 34 // results: 1) the handle will be initialized with a socket to reuse, 2) the |
36 // There are four possible results from calling this function: | 35 // handle will be initialized without a socket such that the consumer needs |
37 // 1) RequestSocket returns OK and initializes |handle| with a reused socket. | 36 // to supply a socket, or 3) the handle will be added to a wait list until a |
38 // 2) RequestSocket returns OK with a newly connected socket. | 37 // socket is available to reuse or the opportunity to create a new socket |
39 // 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a | 38 // arises. The completion callback is notified in the 3rd case. |priority| |
40 // wait list until a socket is available to reuse or a new socket finishes | 39 // will determine the placement into the wait list. |
41 // connecting. |priority| will determine the placement into the wait list. | |
42 // 4) An error occurred early on, so RequestSocket returns an error code. | |
43 // | 40 // |
44 // If this function returns OK, then |handle| is initialized upon return. | 41 // If this function returns OK, then |handle| is initialized upon return. |
45 // The |handle|'s is_initialized method will return true in this case. If a | 42 // The |handle|'s is_initialized method will return true in this case. If a |
46 // ClientSocket was reused, then ClientSocketPool will call | 43 // ClientSocket was reused, then |handle|'s socket member will be non-NULL. |
47 // |handle|->set_reused(true). In either case, the socket will have been | 44 // Otherwise, the consumer will need to supply |handle| with a socket by |
48 // allocated and will be connected. A client might want to know whether or | 45 // allocating a new ClientSocket object and calling the |handle|'s set_socket |
49 // not the socket is reused in order to know whether or not he needs to | 46 // method. |
50 // perform SSL connection or tunnel setup or to request a new socket if he | |
51 // encounters an error with the reused socket. | |
52 // | 47 // |
53 // If ERR_IO_PENDING is returned, then the callback will be used to notify the | 48 // If ERR_IO_PENDING is returned, then the completion callback will be called |
54 // client of completion. | 49 // when |handle| has been initialized. |
55 // | 50 // |
56 int RequestSocket(const std::string& group_name, | 51 int RequestSocket(ClientSocketHandle* handle, |
57 const std::string& host, | |
58 int port, | |
59 int priority, | 52 int priority, |
60 ClientSocketHandle* handle, | |
61 CompletionCallback* callback); | 53 CompletionCallback* callback); |
62 | 54 |
63 // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The | 55 // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The |
64 // same handle parameter must be passed to this method as was passed to the | 56 // same handle parameter must be passed to this method as was passed to the |
65 // RequestSocket call being cancelled. The associated CompletionCallback is | 57 // RequestSocket call being cancelled. The associated CompletionCallback is |
66 // not run. | 58 // not run. |
67 void CancelRequest(const std::string& group_name, | 59 void CancelRequest(ClientSocketHandle* handle); |
68 const ClientSocketHandle* handle); | |
69 | 60 |
70 // Called to release a socket once the socket is no longer needed. If the | 61 // Called to release the socket member of an initialized ClientSocketHandle |
71 // socket still has an established connection, then it will be added to the | 62 // once the socket is no longer needed. If the socket member is non-null and |
72 // set of idle sockets to be used to satisfy future RequestSocket calls. | 63 // still has an established connection, then it will be added to the idle set |
73 // Otherwise, the ClientSocket is destroyed. | 64 // of sockets to be used to satisfy future RequestSocket calls. Otherwise, |
74 void ReleaseSocket(const std::string& group_name, ClientSocket* socket); | 65 // the ClientSocket is destroyed. |
| 66 void ReleaseSocket(ClientSocketHandle* handle); |
75 | 67 |
76 // Called to close any idle connections held by the connection manager. | 68 // Called to close any idle connections held by the connection manager. |
77 void CloseIdleSockets(); | 69 void CloseIdleSockets(); |
78 | 70 |
79 // The total number of idle sockets in the pool. | 71 // The total number of idle sockets in the pool. |
80 int idle_socket_count() const { | 72 int idle_socket_count() const { |
81 return idle_socket_count_; | 73 return idle_socket_count_; |
82 } | 74 } |
83 | 75 |
84 // The total number of idle sockets in a connection group. | 76 // The total number of idle sockets in a connection group. |
85 int IdleSocketCountInGroup(const std::string& group_name) const; | 77 int IdleSocketCountInGroup(const std::string& group_name) const; |
86 | 78 |
87 // Determine the LoadState of a connecting ClientSocketHandle. | |
88 LoadState GetLoadState(const std::string& group_name, | |
89 const ClientSocketHandle* handle) const; | |
90 | |
91 private: | 79 private: |
92 friend class base::RefCounted<ClientSocketPool>; | 80 friend class base::RefCounted<ClientSocketPool>; |
93 | 81 |
| 82 typedef scoped_ptr<ClientSocket> ClientSocketPtr; |
| 83 |
94 // A Request is allocated per call to RequestSocket that results in | 84 // A Request is allocated per call to RequestSocket that results in |
95 // ERR_IO_PENDING. | 85 // ERR_IO_PENDING. |
96 struct Request { | 86 struct Request { |
97 ClientSocketHandle* handle; | 87 ClientSocketHandle* handle; |
98 CompletionCallback* callback; | 88 CompletionCallback* callback; |
99 int priority; | 89 int priority; |
100 std::string host; | |
101 int port; | |
102 LoadState load_state; | |
103 }; | 90 }; |
104 | 91 |
105 // Entry for a persistent socket which became idle at time |start_time|. | 92 // Entry for a persistent socket which became idle at time |start_time|. |
106 struct IdleSocket { | 93 struct IdleSocket { |
107 ClientSocket* socket; | 94 ClientSocketPtr* ptr; |
108 base::TimeTicks start_time; | 95 base::TimeTicks start_time; |
109 | 96 |
110 // An idle socket should be removed if it can't be reused, or has been idle | 97 // An idle socket should be removed if it can't be reused, or has been idle |
111 // for too long. |now| is the current time value (TimeTicks::Now()). | 98 // for too long. |now| is the current time value (TimeTicks::Now()). |
112 // | 99 // |
113 // An idle socket can't be reused if it is disconnected or has received | 100 // An idle socket can't be reused if it is disconnected or has received |
114 // data unexpectedly (hence no longer idle). The unread data would be | 101 // data unexpectedly (hence no longer idle). The unread data would be |
115 // mistaken for the beginning of the next response if we were to reuse the | 102 // mistaken for the beginning of the next response if we were to reuse the |
116 // socket for a new request. | 103 // socket for a new request. |
117 bool ShouldCleanup(base::TimeTicks now) const; | 104 bool ShouldCleanup(base::TimeTicks now) const; |
118 }; | 105 }; |
119 | 106 |
120 typedef std::deque<Request> RequestQueue; | 107 typedef std::deque<Request> RequestQueue; |
121 typedef std::map<const ClientSocketHandle*, Request> RequestMap; | |
122 | 108 |
123 // A Group is allocated per group_name when there are idle sockets or pending | 109 // A Group is allocated per group_name when there are idle sockets or pending |
124 // requests. Otherwise, the Group object is removed from the map. | 110 // requests. Otherwise, the Group object is removed from the map. |
125 struct Group { | 111 struct Group { |
126 Group() : active_socket_count(0) {} | 112 Group() : active_socket_count(0) {} |
127 std::deque<IdleSocket> idle_sockets; | 113 std::deque<IdleSocket> idle_sockets; |
128 RequestQueue pending_requests; | 114 RequestQueue pending_requests; |
129 RequestMap connecting_requests; | |
130 int active_socket_count; | 115 int active_socket_count; |
131 }; | 116 }; |
132 | 117 |
133 typedef std::map<std::string, Group> GroupMap; | 118 typedef std::map<std::string, Group> GroupMap; |
134 | 119 |
135 // ConnectingSocket handles the host resolution necessary for socket creation | |
136 // and the Connect(). | |
137 class ConnectingSocket { | |
138 public: | |
139 enum State { | |
140 STATE_RESOLVE_HOST, | |
141 STATE_CONNECT | |
142 }; | |
143 | |
144 ConnectingSocket(const std::string& group_name, | |
145 const ClientSocketHandle* handle, | |
146 ClientSocketFactory* client_socket_factory, | |
147 ClientSocketPool* pool); | |
148 ~ConnectingSocket(); | |
149 | |
150 // Begins the host resolution and the TCP connect. Returns OK on success, | |
151 // in which case |callback| is not called. On pending IO, Connect returns | |
152 // ERR_IO_PENDING and runs |callback| on completion. | |
153 int Connect(const std::string& host, | |
154 int port, | |
155 CompletionCallback* callback); | |
156 | |
157 // If Connect() returns OK, ClientSocketPool may invoke this method to get | |
158 // the ConnectingSocket to release |socket_| to be set into the | |
159 // ClientSocketHandle immediately. | |
160 ClientSocket* ReleaseSocket(); | |
161 | |
162 private: | |
163 void OnIOComplete(int result); | |
164 | |
165 const std::string group_name_; | |
166 const ClientSocketHandle* const handle_; | |
167 ClientSocketFactory* const client_socket_factory_; | |
168 CompletionCallbackImpl<ConnectingSocket> callback_; | |
169 scoped_ptr<ClientSocket> socket_; | |
170 scoped_refptr<ClientSocketPool> pool_; | |
171 HostResolver resolver_; | |
172 AddressList addresses_; | |
173 | |
174 // The time the Connect() method was called (if it got called). | |
175 base::Time connect_start_time_; | |
176 | |
177 DISALLOW_COPY_AND_ASSIGN(ConnectingSocket); | |
178 }; | |
179 | |
180 ~ClientSocketPool(); | 120 ~ClientSocketPool(); |
181 | 121 |
182 static void InsertRequestIntoQueue(const Request& r, | 122 static void InsertRequestIntoQueue(const Request& r, |
183 RequestQueue* pending_requests); | 123 RequestQueue* pending_requests); |
184 | 124 |
185 // Closes all idle sockets if |force| is true. Else, only closes idle | 125 // Closes all idle sockets if |force| is true. Else, only closes idle |
186 // sockets that timed out or can't be reused. | 126 // sockets that timed out or can't be reused. |
187 void CleanupIdleSockets(bool force); | 127 void CleanupIdleSockets(bool force); |
188 | 128 |
189 // Called when the number of idle sockets changes. | 129 // Called when the number of idle sockets changes. |
190 void IncrementIdleCount(); | 130 void IncrementIdleCount(); |
191 void DecrementIdleCount(); | 131 void DecrementIdleCount(); |
192 | 132 |
193 // Called via PostTask by ReleaseSocket. | 133 // Called via PostTask by ReleaseSocket. |
194 void DoReleaseSocket(const std::string& group_name, ClientSocket* socket); | 134 void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr); |
195 | 135 |
196 // Called when timer_ fires. This method scans the idle sockets removing | 136 // Called when timer_ fires. This method scans the idle sockets removing |
197 // sockets that timed out or can't be reused. | 137 // sockets that timed out or can't be reused. |
198 void OnCleanupTimerFired() { | 138 void OnCleanupTimerFired() { |
199 CleanupIdleSockets(false); | 139 CleanupIdleSockets(false); |
200 } | 140 } |
201 | 141 |
202 ClientSocketFactory* const client_socket_factory_; | |
203 | |
204 GroupMap group_map_; | 142 GroupMap group_map_; |
205 | 143 |
206 // Timer used to periodically prune idle sockets that timed out or can't be | 144 // Timer used to periodically prune idle sockets that timed out or can't be |
207 // reused. | 145 // reused. |
208 base::RepeatingTimer<ClientSocketPool> timer_; | 146 base::RepeatingTimer<ClientSocketPool> timer_; |
209 | 147 |
210 // The total number of idle sockets in the system. | 148 // The total number of idle sockets in the system. |
211 int idle_socket_count_; | 149 int idle_socket_count_; |
212 | 150 |
213 // The maximum number of sockets kept per group. | 151 // The maximum number of sockets kept per group. |
214 const int max_sockets_per_group_; | 152 int max_sockets_per_group_; |
215 | 153 |
216 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); | 154 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); |
217 }; | 155 }; |
218 | 156 |
219 } // namespace net | 157 } // namespace net |
220 | 158 |
221 #endif // NET_BASE_CLIENT_SOCKET_POOL_H_ | 159 #endif // NET_BASE_CLIENT_SOCKET_POOL_H_ |
OLD | NEW |