Home | History | Annotate | Download | only in http
      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