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
25namespace net {
26
27class ClientSocketHandle;
28class GrowableIOBuffer;
29class HostPortPair;
30class HttpNetworkSession;
31class HttpRequestHeaders;
32class HttpResponseInfo;
33class IOBuffer;
34struct LoadTimingInfo;
35class SSLCertRequestInfo;
36class 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.
45class 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