OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 #ifndef NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
6 #define NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
7 | |
8 #include <list> | |
9 #include <map> | |
10 #include <set> | |
11 #include <string> | |
12 | |
13 #include "base/basictypes.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "base/memory/scoped_ptr.h" | |
16 #include "base/memory/weak_ptr.h" | |
17 #include "base/time/time.h" | |
18 #include "base/timer/timer.h" | |
19 #include "net/base/net_export.h" | |
20 #include "net/base/net_log.h" | |
21 #include "net/socket/client_socket_pool.h" | |
22 #include "net/socket/client_socket_pool_base.h" | |
23 #include "net/socket/transport_client_socket_pool.h" | |
24 | |
25 namespace net { | |
26 | |
27 class ClientSocketFactory; | |
28 class ClientSocketPoolHistograms; | |
29 class HostResolver; | |
30 class NetLog; | |
31 class WebSocketEndpointLockManager; | |
32 class WebSocketTransportConnectSubJob; | |
33 | |
34 // WebSocketTransportConnectJob handles the host resolution necessary for socket | |
35 // creation and the TCP connect. WebSocketTransportConnectJob also has fallback | |
36 // logic for IPv6 connect() timeouts (which may happen due to networks / routers | |
37 // with broken IPv6 support). Those timeouts take 20s, so rather than make the | |
38 // user wait 20s for the timeout to fire, we use a fallback timer | |
39 // (kIPv6FallbackTimerInMs) and start a connect() to an IPv4 address if the | |
40 // timer fires. Then we race the IPv4 connect(s) against the IPv6 connect(s) and | |
41 // use the socket that completes successfully first or fails last. | |
42 class NET_EXPORT_PRIVATE WebSocketTransportConnectJob : public ConnectJob { | |
43 public: | |
44 WebSocketTransportConnectJob( | |
45 const std::string& group_name, | |
46 RequestPriority priority, | |
47 const scoped_refptr<TransportSocketParams>& params, | |
48 base::TimeDelta timeout_duration, | |
49 const CompletionCallback& callback, | |
50 ClientSocketFactory* client_socket_factory, | |
51 HostResolver* host_resolver, | |
52 ClientSocketHandle* handle, | |
53 Delegate* delegate, | |
54 NetLog* pool_net_log, | |
55 const BoundNetLog& request_net_log); | |
56 ~WebSocketTransportConnectJob() override; | |
57 | |
58 // Unlike normal socket pools, the WebSocketTransportClientPool uses | |
59 // early-binding of sockets. | |
60 ClientSocketHandle* handle() const { return handle_; } | |
61 | |
62 // Stash the callback from RequestSocket() here for convenience. | |
63 const CompletionCallback& callback() const { return callback_; } | |
64 | |
65 const BoundNetLog& request_net_log() const { return request_net_log_; } | |
66 | |
67 // ConnectJob methods. | |
68 LoadState GetLoadState() const override; | |
69 | |
70 private: | |
71 friend class WebSocketTransportConnectSubJob; | |
72 friend class TransportConnectJobHelper; | |
73 friend class WebSocketEndpointLockManager; | |
74 | |
75 // Although it is not strictly necessary, it makes the code simpler if each | |
76 // subjob knows what type it is. | |
77 enum SubJobType { SUB_JOB_IPV4, SUB_JOB_IPV6 }; | |
78 | |
79 int DoResolveHost(); | |
80 int DoResolveHostComplete(int result); | |
81 int DoTransportConnect(); | |
82 int DoTransportConnectComplete(int result); | |
83 | |
84 // Called back from a SubJob when it completes. | |
85 void OnSubJobComplete(int result, WebSocketTransportConnectSubJob* job); | |
86 | |
87 // Called from |fallback_timer_|. | |
88 void StartIPv4JobAsync(); | |
89 | |
90 // Begins the host resolution and the TCP connect. Returns OK on success | |
91 // and ERR_IO_PENDING if it cannot immediately service the request. | |
92 // Otherwise, it returns a net error code. | |
93 int ConnectInternal() override; | |
94 | |
95 TransportConnectJobHelper helper_; | |
96 | |
97 // The addresses are divided into IPv4 and IPv6, which are performed partially | |
98 // in parallel. If the list of IPv6 addresses is non-empty, then the IPv6 jobs | |
99 // go first, followed after |kIPv6FallbackTimerInMs| by the IPv4 | |
100 // addresses. First sub-job to establish a connection wins. | |
101 scoped_ptr<WebSocketTransportConnectSubJob> ipv4_job_; | |
102 scoped_ptr<WebSocketTransportConnectSubJob> ipv6_job_; | |
103 | |
104 base::OneShotTimer<WebSocketTransportConnectJob> fallback_timer_; | |
105 TransportConnectJobHelper::ConnectionLatencyHistogram race_result_; | |
106 ClientSocketHandle* const handle_; | |
107 CompletionCallback callback_; | |
108 BoundNetLog request_net_log_; | |
109 | |
110 bool had_ipv4_; | |
111 bool had_ipv6_; | |
112 | |
113 DISALLOW_COPY_AND_ASSIGN(WebSocketTransportConnectJob); | |
114 }; | |
115 | |
116 class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool | |
117 : public TransportClientSocketPool { | |
118 public: | |
119 WebSocketTransportClientSocketPool(int max_sockets, | |
120 int max_sockets_per_group, | |
121 ClientSocketPoolHistograms* histograms, | |
122 HostResolver* host_resolver, | |
123 ClientSocketFactory* client_socket_factory, | |
124 NetLog* net_log); | |
125 | |
126 ~WebSocketTransportClientSocketPool() override; | |
127 | |
128 // Allow another connection to be started to the IPEndPoint that this |handle| | |
129 // is connected to. Used when the WebSocket handshake completes successfully. | |
130 // This only works if the socket is connected, however the caller does not | |
131 // need to explicitly check for this. Instead, ensure that dead sockets are | |
132 // returned to ReleaseSocket() in a timely fashion. | |
133 static void UnlockEndpoint(ClientSocketHandle* handle); | |
134 | |
135 // ClientSocketPool implementation. | |
136 int RequestSocket(const std::string& group_name, | |
137 const void* resolve_info, | |
138 RequestPriority priority, | |
139 ClientSocketHandle* handle, | |
140 const CompletionCallback& callback, | |
141 const BoundNetLog& net_log) override; | |
142 void RequestSockets(const std::string& group_name, | |
143 const void* params, | |
144 int num_sockets, | |
145 const BoundNetLog& net_log) override; | |
146 void CancelRequest(const std::string& group_name, | |
147 ClientSocketHandle* handle) override; | |
148 void ReleaseSocket(const std::string& group_name, | |
149 scoped_ptr<StreamSocket> socket, | |
150 int id) override; | |
151 void FlushWithError(int error) override; | |
152 void CloseIdleSockets() override; | |
153 int IdleSocketCount() const override; | |
154 int IdleSocketCountInGroup(const std::string& group_name) const override; | |
155 LoadState GetLoadState(const std::string& group_name, | |
156 const ClientSocketHandle* handle) const override; | |
157 base::DictionaryValue* GetInfoAsValue( | |
158 const std::string& name, | |
159 const std::string& type, | |
160 bool include_nested_pools) const override; | |
161 base::TimeDelta ConnectionTimeout() const override; | |
162 ClientSocketPoolHistograms* histograms() const override; | |
163 | |
164 // HigherLayeredPool implementation. | |
165 bool IsStalled() const override; | |
166 | |
167 private: | |
168 class ConnectJobDelegate : public ConnectJob::Delegate { | |
169 public: | |
170 explicit ConnectJobDelegate(WebSocketTransportClientSocketPool* owner); | |
171 ~ConnectJobDelegate() override; | |
172 | |
173 void OnConnectJobComplete(int result, ConnectJob* job) override; | |
174 | |
175 private: | |
176 WebSocketTransportClientSocketPool* owner_; | |
177 | |
178 DISALLOW_COPY_AND_ASSIGN(ConnectJobDelegate); | |
179 }; | |
180 | |
181 // Store the arguments from a call to RequestSocket() that has stalled so we | |
182 // can replay it when there are available socket slots. | |
183 struct StalledRequest { | |
184 StalledRequest(const scoped_refptr<TransportSocketParams>& params, | |
185 RequestPriority priority, | |
186 ClientSocketHandle* handle, | |
187 const CompletionCallback& callback, | |
188 const BoundNetLog& net_log); | |
189 ~StalledRequest(); | |
190 const scoped_refptr<TransportSocketParams> params; | |
191 const RequestPriority priority; | |
192 ClientSocketHandle* const handle; | |
193 const CompletionCallback callback; | |
194 const BoundNetLog net_log; | |
195 }; | |
196 friend class ConnectJobDelegate; | |
197 typedef std::map<const ClientSocketHandle*, WebSocketTransportConnectJob*> | |
198 PendingConnectsMap; | |
199 // This is a list so that we can remove requests from the middle, and also | |
200 // so that iterators are not invalidated unless the corresponding request is | |
201 // removed. | |
202 typedef std::list<StalledRequest> StalledRequestQueue; | |
203 typedef std::map<const ClientSocketHandle*, StalledRequestQueue::iterator> | |
204 StalledRequestMap; | |
205 | |
206 void OnConnectJobComplete(int result, WebSocketTransportConnectJob* job); | |
207 void InvokeUserCallbackLater(ClientSocketHandle* handle, | |
208 const CompletionCallback& callback, | |
209 int rv); | |
210 void InvokeUserCallback(ClientSocketHandle* handle, | |
211 const CompletionCallback& callback, | |
212 int rv); | |
213 bool ReachedMaxSocketsLimit() const; | |
214 void HandOutSocket(scoped_ptr<StreamSocket> socket, | |
215 const LoadTimingInfo::ConnectTiming& connect_timing, | |
216 ClientSocketHandle* handle, | |
217 const BoundNetLog& net_log); | |
218 void AddJob(ClientSocketHandle* handle, | |
219 scoped_ptr<WebSocketTransportConnectJob> connect_job); | |
220 bool DeleteJob(ClientSocketHandle* handle); | |
221 const WebSocketTransportConnectJob* LookupConnectJob( | |
222 const ClientSocketHandle* handle) const; | |
223 void ActivateStalledRequest(); | |
224 bool DeleteStalledRequest(ClientSocketHandle* handle); | |
225 | |
226 ConnectJobDelegate connect_job_delegate_; | |
227 std::set<const ClientSocketHandle*> pending_callbacks_; | |
228 PendingConnectsMap pending_connects_; | |
229 StalledRequestQueue stalled_request_queue_; | |
230 StalledRequestMap stalled_request_map_; | |
231 ClientSocketPoolHistograms* const histograms_; | |
232 NetLog* const pool_net_log_; | |
233 ClientSocketFactory* const client_socket_factory_; | |
234 HostResolver* const host_resolver_; | |
235 const int max_sockets_; | |
236 int handed_out_socket_count_; | |
237 bool flushing_; | |
238 | |
239 base::WeakPtrFactory<WebSocketTransportClientSocketPool> weak_factory_; | |
240 | |
241 DISALLOW_COPY_AND_ASSIGN(WebSocketTransportClientSocketPool); | |
242 }; | |
243 | |
244 } // namespace net | |
245 | |
246 #endif // NET_SOCKET_WEBSOCKET_TRANSPORT_CLIENT_SOCKET_POOL_H_ | |
OLD | NEW |