OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_H_ | |
6 #define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_H_ | |
7 | |
8 #include "base/memory/ref_counted.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/memory/weak_ptr.h" | |
11 #include "net/base/completion_callback.h" | |
12 #include "net/base/net_log.h" | |
13 #include "net/base/request_priority.h" | |
14 #include "net/http/http_auth.h" | |
15 #include "net/http/http_auth_controller.h" | |
16 #include "net/http/http_request_info.h" | |
17 #include "net/http/http_stream_factory_impl.h" | |
18 #include "net/proxy/proxy_service.h" | |
19 #include "net/quic/quic_stream_factory.h" | |
20 #include "net/socket/client_socket_handle.h" | |
21 #include "net/socket/ssl_client_socket.h" | |
22 #include "net/spdy/spdy_session_key.h" | |
23 #include "net/ssl/ssl_config_service.h" | |
24 | |
25 namespace net { | |
26 | |
27 class ClientSocketHandle; | |
28 class HttpAuthController; | |
29 class HttpNetworkSession; | |
30 class HttpStream; | |
31 class SpdySessionPool; | |
32 class QuicHttpStream; | |
33 | |
34 // An HttpStreamRequestImpl exists for each stream which is in progress of being | |
35 // created for the StreamFactory. | |
36 class HttpStreamFactoryImpl::Job { | |
37 public: | |
38 Job(HttpStreamFactoryImpl* stream_factory, | |
39 HttpNetworkSession* session, | |
40 const HttpRequestInfo& request_info, | |
41 RequestPriority priority, | |
42 const SSLConfig& server_ssl_config, | |
43 const SSLConfig& proxy_ssl_config, | |
44 NetLog* net_log); | |
45 ~Job(); | |
46 | |
47 // Start initiates the process of creating a new HttpStream. |request| will be | |
48 // notified upon completion if the Job has not been Orphan()'d. | |
49 void Start(Request* request); | |
50 | |
51 // Preconnect will attempt to request |num_streams| sockets from the | |
52 // appropriate ClientSocketPool. | |
53 int Preconnect(int num_streams); | |
54 | |
55 int RestartTunnelWithProxyAuth(const AuthCredentials& credentials); | |
56 LoadState GetLoadState() const; | |
57 | |
58 // Marks this Job as the "alternate" job, from Alternate-Protocol. Tracks the | |
59 // original url so we can mark the Alternate-Protocol as broken if | |
60 // we fail to connect. |alternate| specifies the alternate protocol to use | |
61 // and alternate port to connect to. | |
62 void MarkAsAlternate(const GURL& original_url, | |
63 AlternateProtocolInfo alternate); | |
64 | |
65 // Tells |this| to wait for |job| to resume it. | |
66 void WaitFor(Job* job); | |
67 | |
68 // Tells |this| that |job| has determined it still needs to continue | |
69 // connecting, so allow |this| to continue. If this is not called, then | |
70 // |request_| is expected to cancel |this| by deleting it. | |
71 void Resume(Job* job); | |
72 | |
73 // Used to detach the Job from |request|. | |
74 void Orphan(const Request* request); | |
75 | |
76 void SetPriority(RequestPriority priority); | |
77 | |
78 RequestPriority priority() const { return priority_; } | |
79 bool was_npn_negotiated() const; | |
80 NextProto protocol_negotiated() const; | |
81 bool using_spdy() const; | |
82 const BoundNetLog& net_log() const { return net_log_; } | |
83 | |
84 const SSLConfig& server_ssl_config() const; | |
85 const SSLConfig& proxy_ssl_config() const; | |
86 const ProxyInfo& proxy_info() const; | |
87 | |
88 // Indicates whether or not this job is performing a preconnect. | |
89 bool IsPreconnecting() const; | |
90 | |
91 // Indicates whether or not this Job has been orphaned by a Request. | |
92 bool IsOrphaned() const; | |
93 | |
94 // Called to indicate that this job succeeded, and some other jobs | |
95 // will be orphaned. | |
96 void ReportJobSuccededForRequest(); | |
97 | |
98 // Marks that the other |job| has completed. | |
99 void MarkOtherJobComplete(const Job& job); | |
100 | |
101 private: | |
102 enum State { | |
103 STATE_START, | |
104 STATE_RESOLVE_PROXY, | |
105 STATE_RESOLVE_PROXY_COMPLETE, | |
106 | |
107 // Note that when Alternate-Protocol says we can connect to an alternate | |
108 // port using a different protocol, we have the choice of communicating over | |
109 // the original protocol, or speaking the alternate protocol (currently, | |
110 // only npn-spdy) over an alternate port. For a cold page load, the http | |
111 // connection that delivers the http response that has the | |
112 // Alternate-Protocol header will already be warm. So, blocking the next | |
113 // http request on establishing a new npn-spdy connection would incur extra | |
114 // latency. Even if the http connection was not reused, establishing a new | |
115 // http connection is typically faster than npn-spdy, since npn-spdy | |
116 // requires a SSL handshake. Therefore, we start both the http and the | |
117 // npn-spdy jobs in parallel. In order not to unnecessarily waste sockets, | |
118 // we have the http job block on the npn-spdy job after proxy resolution. | |
119 // The npn-spdy job will Resume() the http job if, in | |
120 // STATE_INIT_CONNECTION_COMPLETE, it detects an error or does not find an | |
121 // existing SpdySession. In that case, the http and npn-spdy jobs will race. | |
122 STATE_WAIT_FOR_JOB, | |
123 STATE_WAIT_FOR_JOB_COMPLETE, | |
124 | |
125 STATE_INIT_CONNECTION, | |
126 STATE_INIT_CONNECTION_COMPLETE, | |
127 STATE_WAITING_USER_ACTION, | |
128 STATE_RESTART_TUNNEL_AUTH, | |
129 STATE_RESTART_TUNNEL_AUTH_COMPLETE, | |
130 STATE_CREATE_STREAM, | |
131 STATE_CREATE_STREAM_COMPLETE, | |
132 STATE_DRAIN_BODY_FOR_AUTH_RESTART, | |
133 STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE, | |
134 STATE_DONE, | |
135 STATE_NONE | |
136 }; | |
137 | |
138 enum JobStatus { | |
139 STATUS_RUNNING, | |
140 STATUS_FAILED, | |
141 STATUS_BROKEN, | |
142 STATUS_SUCCEEDED | |
143 }; | |
144 | |
145 void OnStreamReadyCallback(); | |
146 void OnWebSocketHandshakeStreamReadyCallback(); | |
147 // This callback function is called when a new SPDY session is created. | |
148 void OnNewSpdySessionReadyCallback(); | |
149 void OnStreamFailedCallback(int result); | |
150 void OnCertificateErrorCallback(int result, const SSLInfo& ssl_info); | |
151 void OnNeedsProxyAuthCallback(const HttpResponseInfo& response_info, | |
152 HttpAuthController* auth_controller); | |
153 void OnNeedsClientAuthCallback(SSLCertRequestInfo* cert_info); | |
154 void OnHttpsProxyTunnelResponseCallback(const HttpResponseInfo& response_info, | |
155 HttpStream* stream); | |
156 void OnPreconnectsComplete(); | |
157 | |
158 void OnIOComplete(int result); | |
159 int RunLoop(int result); | |
160 int DoLoop(int result); | |
161 int StartInternal(); | |
162 | |
163 // Each of these methods corresponds to a State value. Those with an input | |
164 // argument receive the result from the previous state. If a method returns | |
165 // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the | |
166 // next state method as the result arg. | |
167 int DoStart(); | |
168 int DoResolveProxy(); | |
169 int DoResolveProxyComplete(int result); | |
170 int DoWaitForJob(); | |
171 int DoWaitForJobComplete(int result); | |
172 int DoInitConnection(); | |
173 int DoInitConnectionComplete(int result); | |
174 int DoWaitingUserAction(int result); | |
175 int DoCreateStream(); | |
176 int DoCreateStreamComplete(int result); | |
177 int DoRestartTunnelAuth(); | |
178 int DoRestartTunnelAuthComplete(int result); | |
179 | |
180 // Creates a SpdyHttpStream from the given values and sets to |stream_|. Does | |
181 // nothing if |stream_factory_| is for WebSockets. | |
182 int SetSpdyHttpStream(base::WeakPtr<SpdySession> session, bool direct); | |
183 | |
184 // Returns to STATE_INIT_CONNECTION and resets some state. | |
185 void ReturnToStateInitConnection(bool close_connection); | |
186 | |
187 // Set the motivation for this request onto the underlying socket. | |
188 void SetSocketMotivation(); | |
189 | |
190 bool IsHttpsProxyAndHttpUrl() const; | |
191 | |
192 // Sets several fields of ssl_config for the given origin_server based on the | |
193 // proxy info and other factors. | |
194 void InitSSLConfig(const HostPortPair& origin_server, | |
195 SSLConfig* ssl_config, | |
196 bool is_proxy) const; | |
197 | |
198 // Retrieve SSLInfo from our SSL Socket. | |
199 // This must only be called when we are using an SSLSocket. | |
200 // After calling, the caller can use ssl_info_. | |
201 void GetSSLInfo(); | |
202 | |
203 SpdySessionKey GetSpdySessionKey() const; | |
204 | |
205 // Returns true if the current request can use an existing spdy session. | |
206 bool CanUseExistingSpdySession() const; | |
207 | |
208 // Called when we encounter a network error that could be resolved by trying | |
209 // a new proxy configuration. If there is another proxy configuration to try | |
210 // then this method sets next_state_ appropriately and returns either OK or | |
211 // ERR_IO_PENDING depending on whether or not the new proxy configuration is | |
212 // available synchronously or asynchronously. Otherwise, the given error | |
213 // code is simply returned. | |
214 int ReconsiderProxyAfterError(int error); | |
215 | |
216 // Called to handle a certificate error. Stores the certificate in the | |
217 // allowed_bad_certs list, and checks if the error can be ignored. Returns | |
218 // OK if it can be ignored, or the error code otherwise. | |
219 int HandleCertificateError(int error); | |
220 | |
221 // Called to handle a client certificate request. | |
222 int HandleCertificateRequest(int error); | |
223 | |
224 // Moves this stream request into SPDY mode. | |
225 void SwitchToSpdyMode(); | |
226 | |
227 // Should we force SPDY to run over SSL for this stream request. | |
228 bool ShouldForceSpdySSL() const; | |
229 | |
230 // Should we force SPDY to run without SSL for this stream request. | |
231 bool ShouldForceSpdyWithoutSSL() const; | |
232 | |
233 // Should we force QUIC for this stream request. | |
234 bool ShouldForceQuic() const; | |
235 | |
236 void MaybeMarkAlternateProtocolBroken(); | |
237 | |
238 // Record histograms of latency until Connect() completes. | |
239 static void LogHttpConnectedMetrics(const ClientSocketHandle& handle); | |
240 | |
241 // Invoked by the transport socket pool after host resolution is complete | |
242 // to allow the connection to be aborted, if a matching SPDY session can | |
243 // be found. Will return ERR_SPDY_SESSION_ALREADY_EXISTS if such a | |
244 // session is found, and OK otherwise. | |
245 static int OnHostResolution(SpdySessionPool* spdy_session_pool, | |
246 const SpdySessionKey& spdy_session_key, | |
247 const AddressList& addresses, | |
248 const BoundNetLog& net_log); | |
249 | |
250 Request* request_; | |
251 | |
252 const HttpRequestInfo request_info_; | |
253 RequestPriority priority_; | |
254 ProxyInfo proxy_info_; | |
255 SSLConfig server_ssl_config_; | |
256 SSLConfig proxy_ssl_config_; | |
257 const BoundNetLog net_log_; | |
258 | |
259 CompletionCallback io_callback_; | |
260 scoped_ptr<ClientSocketHandle> connection_; | |
261 HttpNetworkSession* const session_; | |
262 HttpStreamFactoryImpl* const stream_factory_; | |
263 State next_state_; | |
264 ProxyService::PacRequest* pac_request_; | |
265 SSLInfo ssl_info_; | |
266 | |
267 // The origin server we're trying to reach. | |
268 HostPortPair origin_; | |
269 | |
270 // The origin url we're trying to reach. This url may be different from the | |
271 // original request when host mapping rules are set-up. | |
272 GURL origin_url_; | |
273 | |
274 // If this is a Job for an "Alternate-Protocol", then this will be non-NULL | |
275 // and will specify the original URL. | |
276 scoped_ptr<GURL> original_url_; | |
277 | |
278 // AlternateProtocol for this job if this is an alternate job. | |
279 AlternateProtocolInfo alternate_protocol_; | |
280 | |
281 // AlternateProtocol for the other job if this is not an alternate job. | |
282 AlternateProtocolInfo other_job_alternate_protocol_; | |
283 | |
284 // This is the Job we're dependent on. It will notify us if/when it's OK to | |
285 // proceed. | |
286 Job* blocking_job_; | |
287 | |
288 // |waiting_job_| is a Job waiting to see if |this| can reuse a connection. | |
289 // If |this| is unable to do so, we'll notify |waiting_job_| that it's ok to | |
290 // proceed and then race the two Jobs. | |
291 Job* waiting_job_; | |
292 | |
293 // True if handling a HTTPS request, or using SPDY with SSL | |
294 bool using_ssl_; | |
295 | |
296 // True if this network transaction is using SPDY instead of HTTP. | |
297 bool using_spdy_; | |
298 | |
299 // True if this network transaction is using QUIC instead of HTTP. | |
300 bool using_quic_; | |
301 QuicStreamRequest quic_request_; | |
302 | |
303 // True if this job used an existing QUIC session. | |
304 bool using_existing_quic_session_; | |
305 | |
306 // Force quic for a specific port. | |
307 int force_quic_port_; | |
308 | |
309 // The certificate error while using SPDY over SSL for insecure URLs. | |
310 int spdy_certificate_error_; | |
311 | |
312 scoped_refptr<HttpAuthController> | |
313 auth_controllers_[HttpAuth::AUTH_NUM_TARGETS]; | |
314 | |
315 // True when the tunnel is in the process of being established - we can't | |
316 // read from the socket until the tunnel is done. | |
317 bool establishing_tunnel_; | |
318 | |
319 scoped_ptr<HttpStream> stream_; | |
320 scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_; | |
321 | |
322 // True if we negotiated NPN. | |
323 bool was_npn_negotiated_; | |
324 | |
325 // Protocol negotiated with the server. | |
326 NextProto protocol_negotiated_; | |
327 | |
328 // 0 if we're not preconnecting. Otherwise, the number of streams to | |
329 // preconnect. | |
330 int num_streams_; | |
331 | |
332 // Initialized when we create a new SpdySession. | |
333 base::WeakPtr<SpdySession> new_spdy_session_; | |
334 | |
335 // Initialized when we have an existing SpdySession. | |
336 base::WeakPtr<SpdySession> existing_spdy_session_; | |
337 | |
338 // Only used if |new_spdy_session_| is non-NULL. | |
339 bool spdy_session_direct_; | |
340 | |
341 JobStatus job_status_; | |
342 JobStatus other_job_status_; | |
343 | |
344 base::WeakPtrFactory<Job> ptr_factory_; | |
345 | |
346 DISALLOW_COPY_AND_ASSIGN(Job); | |
347 }; | |
348 | |
349 } // namespace net | |
350 | |
351 #endif // NET_HTTP_HTTP_STREAM_FACTORY_IMPL_JOB_H_ | |
OLD | NEW |