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.
5 #ifndef NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
6 #define NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
12 #include "base/basictypes.h"
13 #include "base/location.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "net/base/completion_callback.h"
17 #include "net/base/net_export.h"
18 #include "net/base/net_log.h"
19 #include "net/http/http_pipelined_connection.h"
20 #include "net/http/http_request_info.h"
21 #include "net/http/http_stream_parser.h"
22 #include "net/proxy/proxy_info.h"
23 #include "net/ssl/ssl_config_service.h"
27 class ClientSocketHandle
;
28 class GrowableIOBuffer
;
30 class HttpNetworkSession
;
31 class HttpRequestHeaders
;
32 class HttpResponseInfo
;
34 struct LoadTimingInfo
;
35 class SSLCertRequestInfo
;
38 // This class manages all of the state for a single pipelined connection. It
39 // tracks the order that HTTP requests are sent and enforces that the
40 // subsequent reads occur in the appropriate order.
42 // If an error occurs related to pipelining, ERR_PIPELINE_EVICTION will be
43 // returned to the client. This indicates the client should retry the request
44 // without pipelining.
45 class NET_EXPORT_PRIVATE HttpPipelinedConnectionImpl
46 : public HttpPipelinedConnection
{
48 class Factory
: public HttpPipelinedConnection::Factory
{
50 virtual HttpPipelinedConnection
* CreateNewPipeline(
51 ClientSocketHandle
* connection
,
52 HttpPipelinedConnection::Delegate
* delegate
,
53 const HostPortPair
& origin
,
54 const SSLConfig
& used_ssl_config
,
55 const ProxyInfo
& used_proxy_info
,
56 const BoundNetLog
& net_log
,
57 bool was_npn_negotiated
,
58 NextProto protocol_negotiated
) OVERRIDE
;
61 HttpPipelinedConnectionImpl(ClientSocketHandle
* connection
,
63 const HostPortPair
& origin
,
64 const SSLConfig
& used_ssl_config
,
65 const ProxyInfo
& used_proxy_info
,
66 const BoundNetLog
& net_log
,
67 bool was_npn_negotiated
,
68 NextProto protocol_negotiated
);
69 virtual ~HttpPipelinedConnectionImpl();
71 // HttpPipelinedConnection interface.
73 // Used by HttpStreamFactoryImpl and friends.
74 virtual HttpPipelinedStream
* CreateNewStream() OVERRIDE
;
76 // Used by HttpPipelinedHost.
77 virtual int depth() const OVERRIDE
;
78 virtual bool usable() const OVERRIDE
;
79 virtual bool active() const OVERRIDE
;
81 // Used by HttpStreamFactoryImpl.
82 virtual const SSLConfig
& used_ssl_config() const OVERRIDE
;
83 virtual const ProxyInfo
& used_proxy_info() const OVERRIDE
;
84 virtual const BoundNetLog
& net_log() const OVERRIDE
;
85 virtual bool was_npn_negotiated() const OVERRIDE
;
86 virtual NextProto
protocol_negotiated() const OVERRIDE
;
88 // Used by HttpPipelinedStream.
90 // Notifies this pipeline that a stream is no longer using it.
91 void OnStreamDeleted(int pipeline_id
);
93 // Effective implementation of HttpStream. Note that we don't directly
94 // implement that interface. Instead, these functions will be called by the
95 // pass-through methods in HttpPipelinedStream.
96 void InitializeParser(int pipeline_id
,
97 const HttpRequestInfo
* request
,
98 const BoundNetLog
& net_log
);
100 int SendRequest(int pipeline_id
,
101 const std::string
& request_line
,
102 const HttpRequestHeaders
& headers
,
103 HttpResponseInfo
* response
,
104 const CompletionCallback
& callback
);
106 int ReadResponseHeaders(int pipeline_id
,
107 const CompletionCallback
& callback
);
109 int ReadResponseBody(int pipeline_id
,
110 IOBuffer
* buf
, int buf_len
,
111 const CompletionCallback
& callback
);
113 void Close(int pipeline_id
,
116 UploadProgress
GetUploadProgress(int pipeline_id
) const;
118 HttpResponseInfo
* GetResponseInfo(int pipeline_id
);
120 bool IsResponseBodyComplete(int pipeline_id
) const;
122 bool CanFindEndOfResponse(int pipeline_id
) const;
124 bool IsConnectionReused(int pipeline_id
) const;
126 void SetConnectionReused(int pipeline_id
);
128 bool GetLoadTimingInfo(int pipeline_id
,
129 LoadTimingInfo
* load_timing_info
) const;
131 void GetSSLInfo(int pipeline_id
, SSLInfo
* ssl_info
);
133 void GetSSLCertRequestInfo(int pipeline_id
,
134 SSLCertRequestInfo
* cert_request_info
);
136 // Attempts to drain the response body for |stream| so that the pipeline may
138 void Drain(HttpPipelinedStream
* stream
, HttpNetworkSession
* session
);
152 enum SendRequestState
{
153 SEND_STATE_START_IMMEDIATELY
,
154 SEND_STATE_START_NEXT_DEFERRED_REQUEST
,
155 SEND_STATE_SEND_ACTIVE_REQUEST
,
157 SEND_STATE_EVICT_PENDING_REQUESTS
,
160 enum ReadHeadersState
{
161 READ_STATE_START_IMMEDIATELY
,
162 READ_STATE_START_NEXT_DEFERRED_READ
,
163 READ_STATE_READ_HEADERS
,
164 READ_STATE_READ_HEADERS_COMPLETE
,
165 READ_STATE_WAITING_FOR_CLOSE
,
166 READ_STATE_STREAM_CLOSED
,
168 READ_STATE_EVICT_PENDING_READS
,
171 struct PendingSendRequest
{
172 PendingSendRequest();
173 ~PendingSendRequest();
176 std::string request_line
;
177 HttpRequestHeaders headers
;
178 HttpResponseInfo
* response
;
179 CompletionCallback callback
;
186 linked_ptr
<HttpStreamParser
> parser
;
187 CompletionCallback read_headers_callback
;
188 CompletionCallback pending_user_callback
;
190 NetLog::Source source
;
193 typedef std::map
<int, StreamInfo
> StreamInfoMap
;
195 // Called after the first request is sent or in a task sometime after the
196 // first stream is added to this pipeline. This gives the first request
197 // priority to send, but doesn't hold up other requests if it doesn't.
198 // When called the first time, notifies the |delegate_| that we can accept new
200 void ActivatePipeline();
202 // Responsible for sending one request at a time and waiting until each
204 int DoSendRequestLoop(int result
);
206 // Called when an asynchronous Send() completes.
207 void OnSendIOCallback(int result
);
209 // Activates the only request in |pending_send_request_queue_|. This should
210 // only be called via SendRequest() when the send loop is idle.
211 int DoStartRequestImmediately(int result
);
213 // Activates the first request in |pending_send_request_queue_| that hasn't
214 // been closed, if any. This is called via DoSendComplete() after a prior
216 int DoStartNextDeferredRequest(int result
);
218 // Sends the active request.
219 int DoSendActiveRequest(int result
);
221 // Notifies the user that the send has completed. This may be called directly
222 // after SendRequest() for a synchronous request, or it may be called in
223 // response to OnSendIOCallback for an asynchronous request.
224 int DoSendComplete(int result
);
226 // Evicts all unsent deferred requests. This is called if there is a Send()
227 // error or one of our streams informs us the connection is no longer
229 int DoEvictPendingSendRequests(int result
);
231 // Ensures that only the active request's HttpPipelinedSocket can read from
232 // the underlying socket until it completes. A HttpPipelinedSocket informs us
233 // that it's done by calling Close().
234 int DoReadHeadersLoop(int result
);
236 // Called when the pending asynchronous ReadResponseHeaders() completes.
237 void OnReadIOCallback(int result
);
239 // Invokes DoStartNextDeferredRead() if the read loop is idle. This is called
240 // via a task queued when the previous |active_read_id_| closes its stream
241 // after a succesful response.
242 void StartNextDeferredRead();
244 // Activates the next read request immediately. This is called via
245 // ReadResponseHeaders() if that stream is at the front of |request_order_|
246 // and the read loop is idle.
247 int DoStartReadImmediately(int result
);
249 // Activates the next read request in |request_order_| if it's ready to go.
250 // This is called via StartNextDeferredRead().
251 int DoStartNextDeferredRead(int result
);
253 // Calls ReadResponseHeaders() on the active request's parser.
254 int DoReadHeaders(int result
);
256 // Notifies the user that reading the headers has completed. This may happen
257 // directly after DoReadNextHeaders() if the response is already available.
258 // Otherwise, it is called in response to OnReadIOCallback().
259 int DoReadHeadersComplete(int result
);
261 // Halts the read loop until Close() is called by the active stream.
262 int DoReadWaitForClose(int result
);
264 // Cleans up the state associated with the active request. Invokes
265 // DoReadNextHeaders() in a new task to start the next response. This is
266 // called after the active request's HttpPipelinedSocket calls Close().
267 int DoReadStreamClosed();
269 // Removes all pending ReadResponseHeaders() requests from the queue. This may
270 // happen if there is an error with the pipeline or one of our
271 // HttpPipelinedSockets indicates the connection was suddenly closed.
272 int DoEvictPendingReadHeaders(int result
);
274 // Determines if the response headers indicate pipelining will work. This is
275 // called every time we receive headers.
276 void CheckHeadersForPipelineCompatibility(int pipeline_id
, int result
);
278 // Reports back to |delegate_| whether pipelining will work.
279 void ReportPipelineFeedback(int pipeline_id
, Feedback feedback
);
281 // Posts a task to fire the user's callback in response to SendRequest() or
282 // ReadResponseHeaders() completing on an underlying parser. This might be
283 // invoked in response to our own IO callbacks, or it may be invoked if the
284 // underlying parser completes SendRequest() or ReadResponseHeaders()
285 // synchronously, but we've already returned ERR_IO_PENDING to the user's
286 // SendRequest() or ReadResponseHeaders() call into us.
287 void QueueUserCallback(int pipeline_id
,
288 const CompletionCallback
& callback
,
290 const tracked_objects::Location
& from_here
);
292 // Invokes the callback queued in QueueUserCallback().
293 void FireUserCallback(int pipeline_id
, int result
);
296 scoped_ptr
<ClientSocketHandle
> connection_
;
297 SSLConfig used_ssl_config_
;
298 ProxyInfo used_proxy_info_
;
299 BoundNetLog net_log_
;
300 bool was_npn_negotiated_
;
301 // Protocol negotiated with the server.
302 NextProto protocol_negotiated_
;
303 scoped_refptr
<GrowableIOBuffer
> read_buf_
;
304 int next_pipeline_id_
;
307 bool completed_one_request_
;
308 base::WeakPtrFactory
<HttpPipelinedConnectionImpl
> weak_factory_
;
310 StreamInfoMap stream_info_map_
;
312 std::queue
<int> request_order_
;
314 std::queue
<PendingSendRequest
*> pending_send_request_queue_
;
315 scoped_ptr
<PendingSendRequest
> active_send_request_
;
316 SendRequestState send_next_state_
;
317 bool send_still_on_call_stack_
;
319 ReadHeadersState read_next_state_
;
321 bool read_still_on_call_stack_
;
323 DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionImpl
);
328 #endif // NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_