• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PIPELINED_CONNECTION_IMPL_H_
6 #define NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
7 
8 #include <map>
9 #include <queue>
10 #include <string>
11 
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"
24 
25 namespace net {
26 
27 class ClientSocketHandle;
28 class GrowableIOBuffer;
29 class HostPortPair;
30 class HttpNetworkSession;
31 class HttpRequestHeaders;
32 class HttpResponseInfo;
33 class IOBuffer;
34 struct LoadTimingInfo;
35 class SSLCertRequestInfo;
36 class SSLInfo;
37 
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.
41 //
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 {
47  public:
48   class Factory : public HttpPipelinedConnection::Factory {
49    public:
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;
59   };
60 
61   HttpPipelinedConnectionImpl(ClientSocketHandle* connection,
62                               Delegate* delegate,
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();
70 
71   // HttpPipelinedConnection interface.
72 
73   // Used by HttpStreamFactoryImpl and friends.
74   virtual HttpPipelinedStream* CreateNewStream() OVERRIDE;
75 
76   // Used by HttpPipelinedHost.
77   virtual int depth() const OVERRIDE;
78   virtual bool usable() const OVERRIDE;
79   virtual bool active() const OVERRIDE;
80 
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;
87 
88   // Used by HttpPipelinedStream.
89 
90   // Notifies this pipeline that a stream is no longer using it.
91   void OnStreamDeleted(int pipeline_id);
92 
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);
99 
100   int SendRequest(int pipeline_id,
101                   const std::string& request_line,
102                   const HttpRequestHeaders& headers,
103                   HttpResponseInfo* response,
104                   const CompletionCallback& callback);
105 
106   int ReadResponseHeaders(int pipeline_id,
107                           const CompletionCallback& callback);
108 
109   int ReadResponseBody(int pipeline_id,
110                        IOBuffer* buf, int buf_len,
111                        const CompletionCallback& callback);
112 
113   void Close(int pipeline_id,
114              bool not_reusable);
115 
116   UploadProgress GetUploadProgress(int pipeline_id) const;
117 
118   HttpResponseInfo* GetResponseInfo(int pipeline_id);
119 
120   bool IsResponseBodyComplete(int pipeline_id) const;
121 
122   bool CanFindEndOfResponse(int pipeline_id) const;
123 
124   bool IsConnectionReused(int pipeline_id) const;
125 
126   void SetConnectionReused(int pipeline_id);
127 
128   int64 GetTotalReceivedBytes(int pipeline_id) const;
129 
130   bool GetLoadTimingInfo(int pipeline_id,
131                          LoadTimingInfo* load_timing_info) const;
132 
133   void GetSSLInfo(int pipeline_id, SSLInfo* ssl_info);
134 
135   void GetSSLCertRequestInfo(int pipeline_id,
136                              SSLCertRequestInfo* cert_request_info);
137 
138   // Attempts to drain the response body for |stream| so that the pipeline may
139   // be reused.
140   void Drain(HttpPipelinedStream* stream, HttpNetworkSession* session);
141 
142  private:
143   enum StreamState {
144     STREAM_CREATED,
145     STREAM_BOUND,
146     STREAM_SENDING,
147     STREAM_SENT,
148     STREAM_READ_PENDING,
149     STREAM_ACTIVE,
150     STREAM_CLOSED,
151     STREAM_READ_EVICTED,
152     STREAM_UNUSED,
153   };
154   enum SendRequestState {
155     SEND_STATE_START_IMMEDIATELY,
156     SEND_STATE_START_NEXT_DEFERRED_REQUEST,
157     SEND_STATE_SEND_ACTIVE_REQUEST,
158     SEND_STATE_COMPLETE,
159     SEND_STATE_EVICT_PENDING_REQUESTS,
160     SEND_STATE_NONE,
161   };
162   enum ReadHeadersState {
163     READ_STATE_START_IMMEDIATELY,
164     READ_STATE_START_NEXT_DEFERRED_READ,
165     READ_STATE_READ_HEADERS,
166     READ_STATE_READ_HEADERS_COMPLETE,
167     READ_STATE_WAITING_FOR_CLOSE,
168     READ_STATE_STREAM_CLOSED,
169     READ_STATE_NONE,
170     READ_STATE_EVICT_PENDING_READS,
171   };
172 
173   struct PendingSendRequest {
174     PendingSendRequest();
175     ~PendingSendRequest();
176 
177     int pipeline_id;
178     std::string request_line;
179     HttpRequestHeaders headers;
180     HttpResponseInfo* response;
181     CompletionCallback callback;
182   };
183 
184   struct StreamInfo {
185     StreamInfo();
186     ~StreamInfo();
187 
188     linked_ptr<HttpStreamParser> parser;
189     CompletionCallback read_headers_callback;
190     CompletionCallback pending_user_callback;
191     StreamState state;
192     NetLog::Source source;
193   };
194 
195   typedef std::map<int, StreamInfo> StreamInfoMap;
196 
197   // Called after the first request is sent or in a task sometime after the
198   // first stream is added to this pipeline. This gives the first request
199   // priority to send, but doesn't hold up other requests if it doesn't.
200   // When called the first time, notifies the |delegate_| that we can accept new
201   // requests.
202   void ActivatePipeline();
203 
204   // Responsible for sending one request at a time and waiting until each
205   // comepletes.
206   int DoSendRequestLoop(int result);
207 
208   // Called when an asynchronous Send() completes.
209   void OnSendIOCallback(int result);
210 
211   // Activates the only request in |pending_send_request_queue_|. This should
212   // only be called via SendRequest() when the send loop is idle.
213   int DoStartRequestImmediately(int result);
214 
215   // Activates the first request in |pending_send_request_queue_| that hasn't
216   // been closed, if any. This is called via DoSendComplete() after a prior
217   // request complets.
218   int DoStartNextDeferredRequest(int result);
219 
220   // Sends the active request.
221   int DoSendActiveRequest(int result);
222 
223   // Notifies the user that the send has completed. This may be called directly
224   // after SendRequest() for a synchronous request, or it may be called in
225   // response to OnSendIOCallback for an asynchronous request.
226   int DoSendComplete(int result);
227 
228   // Evicts all unsent deferred requests. This is called if there is a Send()
229   // error or one of our streams informs us the connection is no longer
230   // reusable.
231   int DoEvictPendingSendRequests(int result);
232 
233   // Ensures that only the active request's HttpPipelinedSocket can read from
234   // the underlying socket until it completes. A HttpPipelinedSocket informs us
235   // that it's done by calling Close().
236   int DoReadHeadersLoop(int result);
237 
238   // Called when the pending asynchronous ReadResponseHeaders() completes.
239   void OnReadIOCallback(int result);
240 
241   // Invokes DoStartNextDeferredRead() if the read loop is idle. This is called
242   // via a task queued when the previous |active_read_id_| closes its stream
243   // after a succesful response.
244   void StartNextDeferredRead();
245 
246   // Activates the next read request immediately. This is called via
247   // ReadResponseHeaders() if that stream is at the front of |request_order_|
248   // and the read loop is idle.
249   int DoStartReadImmediately(int result);
250 
251   // Activates the next read request in |request_order_| if it's ready to go.
252   // This is called via StartNextDeferredRead().
253   int DoStartNextDeferredRead(int result);
254 
255   // Calls ReadResponseHeaders() on the active request's parser.
256   int DoReadHeaders(int result);
257 
258   // Notifies the user that reading the headers has completed. This may happen
259   // directly after DoReadNextHeaders() if the response is already available.
260   // Otherwise, it is called in response to OnReadIOCallback().
261   int DoReadHeadersComplete(int result);
262 
263   // Halts the read loop until Close() is called by the active stream.
264   int DoReadWaitForClose(int result);
265 
266   // Cleans up the state associated with the active request. Invokes
267   // DoReadNextHeaders() in a new task to start the next response. This is
268   // called after the active request's HttpPipelinedSocket calls Close().
269   int DoReadStreamClosed();
270 
271   // Removes all pending ReadResponseHeaders() requests from the queue. This may
272   // happen if there is an error with the pipeline or one of our
273   // HttpPipelinedSockets indicates the connection was suddenly closed.
274   int DoEvictPendingReadHeaders(int result);
275 
276   // Determines if the response headers indicate pipelining will work. This is
277   // called every time we receive headers.
278   void CheckHeadersForPipelineCompatibility(int pipeline_id, int result);
279 
280   // Reports back to |delegate_| whether pipelining will work.
281   void ReportPipelineFeedback(int pipeline_id, Feedback feedback);
282 
283   // Posts a task to fire the user's callback in response to SendRequest() or
284   // ReadResponseHeaders() completing on an underlying parser. This might be
285   // invoked in response to our own IO callbacks, or it may be invoked if the
286   // underlying parser completes SendRequest() or ReadResponseHeaders()
287   // synchronously, but we've already returned ERR_IO_PENDING to the user's
288   // SendRequest() or ReadResponseHeaders() call into us.
289   void QueueUserCallback(int pipeline_id,
290                          const CompletionCallback& callback,
291                          int rv,
292                          const tracked_objects::Location& from_here);
293 
294   // Invokes the callback queued in QueueUserCallback().
295   void FireUserCallback(int pipeline_id, int result);
296 
297   Delegate* delegate_;
298   scoped_ptr<ClientSocketHandle> connection_;
299   SSLConfig used_ssl_config_;
300   ProxyInfo used_proxy_info_;
301   BoundNetLog net_log_;
302   bool was_npn_negotiated_;
303   // Protocol negotiated with the server.
304   NextProto protocol_negotiated_;
305   scoped_refptr<GrowableIOBuffer> read_buf_;
306   int next_pipeline_id_;
307   bool active_;
308   bool usable_;
309   bool completed_one_request_;
310   base::WeakPtrFactory<HttpPipelinedConnectionImpl> weak_factory_;
311 
312   StreamInfoMap stream_info_map_;
313 
314   std::queue<int> request_order_;
315 
316   std::queue<PendingSendRequest*> pending_send_request_queue_;
317   scoped_ptr<PendingSendRequest> active_send_request_;
318   SendRequestState send_next_state_;
319   bool send_still_on_call_stack_;
320 
321   ReadHeadersState read_next_state_;
322   int active_read_id_;
323   bool read_still_on_call_stack_;
324 
325   DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionImpl);
326 };
327 
328 }  // namespace net
329 
330 #endif  // NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_
331