Chromium Code Reviews| Index: net/http/http_pipelined_connection_impl.h |
| diff --git a/net/http/http_pipelined_connection_impl.h b/net/http/http_pipelined_connection_impl.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c5cd8c305899a515af0da5a3cfb9a44e6eeb73aa |
| --- /dev/null |
| +++ b/net/http/http_pipelined_connection_impl.h |
| @@ -0,0 +1,259 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_ |
| +#define NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_ |
| +#pragma once |
| + |
| +#include <map> |
| +#include <queue> |
| +#include <string> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/task.h" |
| +#include "net/base/completion_callback.h" |
| +#include "net/base/net_log.h" |
| +#include "net/base/ssl_config_service.h" |
| +#include "net/base/upload_data_stream.h" |
| +#include "net/http/http_pipelined_connection.h" |
| +#include "net/http/http_request_info.h" |
| +#include "net/proxy/proxy_info.h" |
| + |
| +namespace net { |
| + |
| +class ClientSocketHandle; |
| +class GrowableIOBuffer; |
| +class HttpPipelinedStream; |
|
mmenke
2011/09/01 21:15:39
nit: Doesn't look like you use this.
James Simonsen
2011/09/07 21:20:10
Done.
|
| +class HttpRequestHeaders; |
| +class HttpResponseInfo; |
| +class HttpStreamParser; |
| +class IOBuffer; |
| +class SSLCertRequestInfo; |
| +class SSLInfo; |
| + |
| +// This class manages all of the state for a single pipelined connection. It |
| +// tracks the order that HTTP requests are sent and enforces that the |
| +// subsequent reads occur in the appropriate order. |
| +// |
| +// If an error occurs related to pipelining, ERR_PIPELINE_EVICTION will be |
| +// returned to the client. This indicates the client should retry the request |
| +// without pipelining. |
| +class HttpPipelinedConnectionImpl : public HttpPipelinedConnection { |
| + public: |
| + HttpPipelinedConnectionImpl(ClientSocketHandle* connection, |
| + Delegate* delegate, |
| + const SSLConfig& used_ssl_config, |
| + const ProxyInfo& used_proxy_info, |
| + const BoundNetLog& net_log, |
| + bool was_npn_negotiated); |
| + ~HttpPipelinedConnectionImpl(); |
| + |
| + // HttpPipelinedConnection interface. |
| + |
| + // Used by HttpStreamFactoryImpl and friends. |
| + virtual HttpStream* CreateNewStream() OVERRIDE; |
| + |
| + // Used by HttpPipelinedHost. |
| + virtual int depth() const OVERRIDE { return stream_state_map_.size(); } |
| + virtual bool usable() const OVERRIDE { return usable_; } |
| + virtual bool active() const OVERRIDE { return active_; } |
| + |
| + // Used by HttpStreamFactoryImpl. |
| + virtual const SSLConfig& used_ssl_config() const OVERRIDE { |
| + return used_ssl_config_; |
| + } |
| + virtual const ProxyInfo& used_proxy_info() const OVERRIDE { |
| + return used_proxy_info_; |
| + } |
| + virtual const NetLog::Source& source() const OVERRIDE { |
| + return net_log_.source(); |
| + } |
| + virtual bool was_npn_negotiated() const OVERRIDE { |
| + return was_npn_negotiated_; |
| + } |
| + |
| + // Used by HttpPipelinedStream. |
| + virtual void OnStreamDeleted(int pipeline_id) OVERRIDE; |
| + |
| + // Effective implementation of HttpStream. Note that we don't directly |
| + // implement that interface. Instead, these functions will be called by the |
| + // pass-through methods in HttpPipelinedStream. |
| + void InitializeParser(int pipeline_id, |
| + const HttpRequestInfo* request, |
| + const BoundNetLog& net_log); |
| + |
| + int SendRequest(int pipeline_id, |
| + const std::string& request_line, |
| + const HttpRequestHeaders& headers, |
| + UploadDataStream* request_body, |
| + HttpResponseInfo* response, |
| + CompletionCallback* callback); |
| + |
| + int ReadResponseHeaders(int pipeline_id, |
| + CompletionCallback* callback); |
| + |
| + int ReadResponseBody(int pipeline_id, |
| + IOBuffer* buf, int buf_len, |
| + CompletionCallback* callback); |
| + |
| + void Close(int pipeline_id, |
| + bool not_reusable); |
| + |
| + uint64 GetUploadProgress(int pipeline_id) const; |
| + |
| + HttpResponseInfo* GetResponseInfo(int pipeline_id); |
| + |
| + bool IsResponseBodyComplete(int pipeline_id) const; |
| + |
| + bool CanFindEndOfResponse(int pipeline_id) const; |
| + |
| + bool IsMoreDataBuffered(int pipeline_id) const; |
| + |
| + bool IsConnectionReused(int pipeline_id) const; |
| + |
| + void SetConnectionReused(int pipeline_id); |
| + |
| + void GetSSLInfo(int pipeline_id, |
| + SSLInfo* ssl_info); |
| + |
| + void GetSSLCertRequestInfo(int pipeline_id, |
| + SSLCertRequestInfo* cert_request_info); |
| + |
| + private: |
| + enum StreamState { |
| + STREAM_CREATED, |
| + STREAM_BOUND, |
| + STREAM_SENDING, |
| + STREAM_SENT, |
| + STREAM_READ_PENDING, |
| + STREAM_ACTIVE, |
| + STREAM_CLOSED, |
| + STREAM_UNUSED, |
| + }; |
| + enum SendRequestState { |
| + SEND_STATE_NEXT_REQUEST, |
| + SEND_STATE_COMPLETE, |
| + SEND_STATE_NONE, |
| + SEND_STATE_UNUSABLE, |
| + }; |
| + enum ReadHeadersState { |
| + READ_STATE_NEXT_HEADERS, |
| + READ_STATE_COMPLETE, |
| + READ_STATE_WAITING_FOR_CLOSE, |
| + READ_STATE_STREAM_CLOSED, |
| + READ_STATE_NONE, |
| + READ_STATE_UNUSABLE, |
| + }; |
| + |
| + struct DeferredSendRequest { |
| + int pipeline_id; |
| + std::string request_line; |
| + HttpRequestHeaders headers; |
| + UploadDataStream* request_body; |
| + HttpResponseInfo* response; |
| + CompletionCallback* callback; |
| + }; |
| + |
| + // Called after the first request is processed, allowing the rest of this |
| + // pipeline to fill up with any pending requests. |
| + void FillPipeline(); |
| + |
| + // Responsible for sending one request at a time and waiting until each |
| + // comepletes. |
| + int DoSendRequestLoop(int result); |
| + |
| + // Called when an asynchronous Send() completes. |
| + void OnSendIOCallback(int result); |
| + |
| + // Sends the next deferred request. This may be called immediately after |
| + // SendRequest(), or it may be in a new task after a prior send completes in |
| + // DoSendComplete(). |
| + int DoSendNextRequest(int result); |
| + |
| + // Notifies the user that the send has completed. This may be called directly |
| + // after SendRequest() for a synchronous request, or it may be called in |
| + // response to OnSendIOCallback for an asynchronous request. |
| + int DoSendComplete(int result); |
| + |
| + // Evicts all unsent deferred requests. This is called if there is a Send() |
| + // error or one of our streams informs us the connection is no longer |
| + // reusable. |
| + int DoEvictPendingSendRequests(int result); |
| + |
| + // Ensures that only the active request's HttpPipelinedSocket can read from |
| + // the underlying socket until it completes. A HttpPipelinedSocket informs us |
| + // that it's done by calling Close(). |
| + int DoReadHeadersLoop(int result); |
| + |
| + // Called when the pending asynchronous ReadResponseHeaders() completes. |
| + void OnReadIOCallback(int result); |
| + |
| + // Determines if the next response in the pipeline is ready to be read. |
| + // If it's ready, then we call ReadResponseHeaders() on the underlying parser. |
| + // HttpPipelinedSocket indicates its readiness by calling |
| + // ReadResponseHeaders(). This function may be called immediately after |
| + // ReadResponseHeaders(), or it may be called in a new task after a previous |
| + // HttpPipelinedSocket finishes its work. |
| + int DoReadNextHeaders(int result); |
| + |
| + // Notifies the user that reading the headers has completed. This may happen |
| + // directly after DoReadNextHeaders() if the response is already available. |
| + // Otherwise, it is called in response to OnReadIOCallback(). |
| + int DoReadHeadersComplete(int result); |
| + |
| + // This is a holding state. It does not do anything, except exit the |
| + // DoReadHeadersLoop(). It is called after DoReadHeadersComplete(). |
| + int DoReadWaitingForClose(int result); |
| + |
| + // Cleans up the state associated with the active request. Invokes |
| + // DoReadNextHeaders() in a new task to start the next response. This is |
| + // called after the active request's HttpPipelinedSocket calls Close(). |
| + int DoReadStreamClosed(); |
| + |
| + // Removes all pending ReadResponseHeaders() requests from the queue. This may |
| + // happen if there is an error with the pipeline or one of our |
| + // HttpPipelinedSockets indicates the connection was suddenly closed. |
| + int DoEvictPendingReadHeaders(int result); |
| + |
| + // Invokes the user's callback in response to one of our own IO callbacks |
| + // being invoked. This may be used for either Send or Read callbacks. |
|
mmenke
2011/09/01 21:15:39
nit: Update comment.
James Simonsen
2011/09/07 21:20:10
Done.
|
| + void FireReadUserCallback(int result); |
| + |
| + Delegate* delegate_; |
| + scoped_ptr<ClientSocketHandle> connection_; |
| + SSLConfig used_ssl_config_; |
| + ProxyInfo used_proxy_info_; |
| + BoundNetLog net_log_; |
| + bool was_npn_negotiated_; |
| + scoped_refptr<GrowableIOBuffer> read_buf_; |
| + int next_pipeline_id_; |
| + bool active_; |
| + bool usable_; |
| + bool completed_one_request_; |
| + ScopedRunnableMethodFactory<HttpPipelinedConnectionImpl> method_factory_; |
| + |
| + typedef std::map<int, StreamState> StreamStateMap; |
| + StreamStateMap stream_state_map_; |
| + typedef std::map<int, HttpStreamParser*> ParserMap; |
| + ParserMap parser_map_; |
| + |
| + std::queue<int> request_order_; |
| + |
| + std::queue<DeferredSendRequest> deferred_request_queue_; |
| + SendRequestState send_next_state_; |
| + CompletionCallbackImpl<HttpPipelinedConnectionImpl> send_io_callback_; |
| + CompletionCallback* send_user_callback_; |
| + |
| + ReadHeadersState read_next_state_; |
| + CompletionCallbackImpl<HttpPipelinedConnectionImpl> read_io_callback_; |
| + CompletionCallback* read_user_callback_; |
| + typedef std::map<int, CompletionCallback*> CallbackMap; |
| + CallbackMap callback_map_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionImpl); |
| +}; |
| + |
| +} // namespace net |
| + |
| +#endif // NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_ |