Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 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 #pragma once | |
| 8 | |
| 9 #include <map> | |
| 10 #include <queue> | |
| 11 #include <string> | |
| 12 | |
| 13 #include "base/basictypes.h" | |
| 14 #include "base/task.h" | |
| 15 #include "net/base/completion_callback.h" | |
| 16 #include "net/base/net_export.h" | |
| 17 #include "net/base/net_log.h" | |
| 18 #include "net/base/ssl_config_service.h" | |
| 19 #include "net/base/upload_data_stream.h" | |
| 20 #include "net/http/http_pipelined_connection.h" | |
| 21 #include "net/http/http_request_info.h" | |
| 22 #include "net/proxy/proxy_info.h" | |
| 23 | |
| 24 namespace net { | |
| 25 | |
| 26 class ClientSocketHandle; | |
| 27 class GrowableIOBuffer; | |
| 28 class HttpRequestHeaders; | |
| 29 class HttpResponseInfo; | |
| 30 class HttpStreamParser; | |
| 31 class IOBuffer; | |
| 32 class SSLCertRequestInfo; | |
| 33 class SSLInfo; | |
| 34 | |
| 35 // This class manages all of the state for a single pipelined connection. It | |
| 36 // tracks the order that HTTP requests are sent and enforces that the | |
| 37 // subsequent reads occur in the appropriate order. | |
| 38 // | |
| 39 // If an error occurs related to pipelining, ERR_PIPELINE_EVICTION will be | |
| 40 // returned to the client. This indicates the client should retry the request | |
| 41 // without pipelining. | |
| 42 class NET_EXPORT_PRIVATE HttpPipelinedConnectionImpl | |
| 43 : public HttpPipelinedConnection { | |
| 44 public: | |
| 45 HttpPipelinedConnectionImpl(ClientSocketHandle* connection, | |
| 46 Delegate* delegate, | |
| 47 const SSLConfig& used_ssl_config, | |
| 48 const ProxyInfo& used_proxy_info, | |
| 49 const BoundNetLog& net_log, | |
| 50 bool was_npn_negotiated); | |
| 51 ~HttpPipelinedConnectionImpl(); | |
| 52 | |
| 53 // HttpPipelinedConnection interface. | |
| 54 | |
| 55 // Used by HttpStreamFactoryImpl and friends. | |
| 56 virtual HttpPipelinedStream* CreateNewStream() OVERRIDE; | |
| 57 | |
| 58 // Used by HttpPipelinedHost. | |
| 59 virtual int depth() const OVERRIDE { return stream_info_map_.size(); } | |
| 60 virtual bool usable() const OVERRIDE { return usable_; } | |
| 61 virtual bool active() const OVERRIDE { return active_; } | |
| 62 | |
| 63 // Used by HttpStreamFactoryImpl. | |
| 64 virtual const SSLConfig& used_ssl_config() const OVERRIDE { | |
| 65 return used_ssl_config_; | |
| 66 } | |
| 67 virtual const ProxyInfo& used_proxy_info() const OVERRIDE { | |
| 68 return used_proxy_info_; | |
| 69 } | |
| 70 virtual const NetLog::Source& source() const OVERRIDE { | |
| 71 return net_log_.source(); | |
| 72 } | |
| 73 virtual bool was_npn_negotiated() const OVERRIDE { | |
| 74 return was_npn_negotiated_; | |
| 75 } | |
| 76 | |
| 77 // Used by HttpPipelinedStream. | |
| 78 virtual void OnStreamDeleted(int pipeline_id) OVERRIDE; | |
| 79 | |
| 80 // Effective implementation of HttpStream. Note that we don't directly | |
| 81 // implement that interface. Instead, these functions will be called by the | |
| 82 // pass-through methods in HttpPipelinedStream. | |
| 83 void InitializeParser(int pipeline_id, | |
| 84 const HttpRequestInfo* request, | |
| 85 const BoundNetLog& net_log); | |
| 86 | |
| 87 int SendRequest(int pipeline_id, | |
| 88 const std::string& request_line, | |
| 89 const HttpRequestHeaders& headers, | |
| 90 UploadDataStream* request_body, | |
| 91 HttpResponseInfo* response, | |
| 92 OldCompletionCallback* callback); | |
| 93 | |
| 94 int ReadResponseHeaders(int pipeline_id, | |
| 95 OldCompletionCallback* callback); | |
| 96 | |
| 97 int ReadResponseBody(int pipeline_id, | |
| 98 IOBuffer* buf, int buf_len, | |
| 99 OldCompletionCallback* callback); | |
| 100 | |
| 101 void Close(int pipeline_id, | |
| 102 bool not_reusable); | |
| 103 | |
| 104 uint64 GetUploadProgress(int pipeline_id) const; | |
| 105 | |
| 106 HttpResponseInfo* GetResponseInfo(int pipeline_id); | |
| 107 | |
| 108 bool IsResponseBodyComplete(int pipeline_id) const; | |
| 109 | |
| 110 bool CanFindEndOfResponse(int pipeline_id) const; | |
| 111 | |
| 112 bool IsMoreDataBuffered(int pipeline_id) const; | |
| 113 | |
| 114 bool IsConnectionReused(int pipeline_id) const; | |
| 115 | |
| 116 void SetConnectionReused(int pipeline_id); | |
| 117 | |
| 118 void GetSSLInfo(int pipeline_id, | |
| 119 SSLInfo* ssl_info); | |
| 120 | |
| 121 void GetSSLCertRequestInfo(int pipeline_id, | |
| 122 SSLCertRequestInfo* cert_request_info); | |
| 123 | |
| 124 private: | |
| 125 enum StreamState { | |
| 126 STREAM_CREATED, | |
| 127 STREAM_BOUND, | |
| 128 STREAM_SENDING, | |
| 129 STREAM_SENT, | |
| 130 STREAM_READ_PENDING, | |
| 131 STREAM_ACTIVE, | |
| 132 STREAM_CLOSED, | |
| 133 STREAM_UNUSED, | |
| 134 }; | |
| 135 enum SendRequestState { | |
| 136 SEND_STATE_NEXT_REQUEST, | |
| 137 SEND_STATE_COMPLETE, | |
| 138 SEND_STATE_NONE, | |
| 139 SEND_STATE_UNUSABLE, | |
| 140 }; | |
| 141 enum ReadHeadersState { | |
| 142 READ_STATE_NEXT_HEADERS, | |
| 143 READ_STATE_COMPLETE, | |
| 144 READ_STATE_WAITING_FOR_CLOSE, | |
| 145 READ_STATE_STREAM_CLOSED, | |
| 146 READ_STATE_NONE, | |
| 147 READ_STATE_UNUSABLE, | |
| 148 }; | |
| 149 | |
| 150 struct DeferredSendRequest { | |
| 151 int pipeline_id; | |
| 152 std::string request_line; | |
| 153 HttpRequestHeaders headers; | |
| 154 UploadDataStream* request_body; | |
| 155 HttpResponseInfo* response; | |
| 156 OldCompletionCallback* callback; | |
| 157 }; | |
| 158 | |
| 159 struct StreamInfo { | |
| 160 StreamInfo() : parser(NULL), | |
| 161 read_headers_callback(NULL), | |
| 162 state(STREAM_CREATED) {} | |
| 163 | |
| 164 HttpStreamParser* parser; | |
|
mmenke
2011/10/12 19:41:35
Any reason to not use scoped_ptr for this? Makes
James Simonsen
2011/10/12 21:55:51
Hadn't tried it. Had to use linked_ptr because it'
| |
| 165 OldCompletionCallback* read_headers_callback; | |
| 166 StreamState state; | |
| 167 }; | |
| 168 | |
| 169 typedef std::map<int, StreamInfo> StreamInfoMap; | |
| 170 | |
| 171 // Called after the first request is sent or in a task sometime after the | |
| 172 // first stream is added to this pipeline. This gives the first request | |
| 173 // priority to send, but doesn't hold up other requests if it doesn't. | |
| 174 // When called the first time, notifies the |delegate_| that we can accept new | |
| 175 // requests. | |
| 176 void ActivatePipeline(); | |
| 177 | |
| 178 // Responsible for sending one request at a time and waiting until each | |
| 179 // comepletes. | |
| 180 int DoSendRequestLoop(int result); | |
| 181 | |
| 182 // Called when an asynchronous Send() completes. | |
| 183 void OnSendIOCallback(int result); | |
| 184 | |
| 185 // Sends the next deferred request. This may be called immediately after | |
| 186 // SendRequest(), or it may be in a new task after a prior send completes in | |
| 187 // DoSendComplete(). | |
| 188 int DoSendNextRequest(int result); | |
| 189 | |
| 190 // Notifies the user that the send has completed. This may be called directly | |
| 191 // after SendRequest() for a synchronous request, or it may be called in | |
| 192 // response to OnSendIOCallback for an asynchronous request. | |
| 193 int DoSendComplete(int result); | |
| 194 | |
| 195 // Evicts all unsent deferred requests. This is called if there is a Send() | |
| 196 // error or one of our streams informs us the connection is no longer | |
| 197 // reusable. | |
| 198 int DoEvictPendingSendRequests(int result); | |
| 199 | |
| 200 // Ensures that only the active request's HttpPipelinedSocket can read from | |
| 201 // the underlying socket until it completes. A HttpPipelinedSocket informs us | |
| 202 // that it's done by calling Close(). | |
| 203 int DoReadHeadersLoop(int result); | |
| 204 | |
| 205 // Called when the pending asynchronous ReadResponseHeaders() completes. | |
| 206 void OnReadIOCallback(int result); | |
| 207 | |
| 208 // Determines if the next response in the pipeline is ready to be read. | |
| 209 // If it's ready, then we call ReadResponseHeaders() on the underlying parser. | |
| 210 // HttpPipelinedSocket indicates its readiness by calling | |
| 211 // ReadResponseHeaders(). This function may be called immediately after | |
| 212 // ReadResponseHeaders(), or it may be called in a new task after a previous | |
| 213 // HttpPipelinedSocket finishes its work. | |
| 214 int DoReadNextHeaders(int result); | |
| 215 | |
| 216 // Notifies the user that reading the headers has completed. This may happen | |
| 217 // directly after DoReadNextHeaders() if the response is already available. | |
| 218 // Otherwise, it is called in response to OnReadIOCallback(). | |
| 219 int DoReadHeadersComplete(int result); | |
| 220 | |
| 221 // This is a holding state. It does not do anything, except exit the | |
| 222 // DoReadHeadersLoop(). It is called after DoReadHeadersComplete(). | |
| 223 int DoReadWaitingForClose(int result); | |
| 224 | |
| 225 // Cleans up the state associated with the active request. Invokes | |
| 226 // DoReadNextHeaders() in a new task to start the next response. This is | |
| 227 // called after the active request's HttpPipelinedSocket calls Close(). | |
| 228 int DoReadStreamClosed(); | |
| 229 | |
| 230 // Removes all pending ReadResponseHeaders() requests from the queue. This may | |
| 231 // happen if there is an error with the pipeline or one of our | |
| 232 // HttpPipelinedSockets indicates the connection was suddenly closed. | |
| 233 int DoEvictPendingReadHeaders(int result); | |
| 234 | |
| 235 // Invokes the user's callback in response to SendRequest() or | |
| 236 // ReadResponseHeaders() completing on an underlying parser. This might be | |
| 237 // invoked in response to our own IO callbacks, or it may be invoked if the | |
| 238 // underlying parser completes SendRequest() or ReadResponseHeaders() | |
| 239 // synchronously, but we've already returned ERR_IO_PENDING to the user's | |
| 240 // SendRequest() or ReadResponseHeaders() call into us. | |
| 241 void FireUserCallback(OldCompletionCallback* callback, int result); | |
| 242 | |
| 243 Delegate* delegate_; | |
| 244 scoped_ptr<ClientSocketHandle> connection_; | |
| 245 SSLConfig used_ssl_config_; | |
| 246 ProxyInfo used_proxy_info_; | |
| 247 BoundNetLog net_log_; | |
| 248 bool was_npn_negotiated_; | |
| 249 scoped_refptr<GrowableIOBuffer> read_buf_; | |
| 250 int next_pipeline_id_; | |
| 251 bool active_; | |
| 252 bool usable_; | |
| 253 bool completed_one_request_; | |
| 254 ScopedRunnableMethodFactory<HttpPipelinedConnectionImpl> method_factory_; | |
| 255 | |
| 256 StreamInfoMap stream_info_map_; | |
| 257 | |
| 258 std::queue<int> request_order_; | |
| 259 | |
| 260 std::queue<DeferredSendRequest> deferred_request_queue_; | |
| 261 SendRequestState send_next_state_; | |
| 262 OldCompletionCallbackImpl<HttpPipelinedConnectionImpl> send_io_callback_; | |
| 263 OldCompletionCallback* send_user_callback_; | |
| 264 | |
| 265 ReadHeadersState read_next_state_; | |
| 266 OldCompletionCallbackImpl<HttpPipelinedConnectionImpl> read_io_callback_; | |
| 267 OldCompletionCallback* read_user_callback_; | |
| 268 | |
| 269 DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionImpl); | |
| 270 }; | |
| 271 | |
| 272 } // namespace net | |
| 273 | |
| 274 #endif // NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_ | |
| OLD | NEW |