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