| OLD | NEW |
| (Empty) |
| 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_ | |
| OLD | NEW |