Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(388)

Unified Diff: net/http/http_pipelined_connection_impl.h

Issue 7289006: Basic HTTP pipelining support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix races Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..7a8f2d7c97e267ea1860a51ad6246b6458eb2977
--- /dev/null
+++ b/net/http/http_pipelined_connection_impl.h
@@ -0,0 +1,274 @@
+// 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_export.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 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 NET_EXPORT_PRIVATE 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 HttpPipelinedStream* CreateNewStream() OVERRIDE;
+
+ // Used by HttpPipelinedHost.
+ virtual int depth() const OVERRIDE { return stream_info_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,
+ OldCompletionCallback* callback);
+
+ int ReadResponseHeaders(int pipeline_id,
+ OldCompletionCallback* callback);
+
+ int ReadResponseBody(int pipeline_id,
+ IOBuffer* buf, int buf_len,
+ OldCompletionCallback* 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;
+ OldCompletionCallback* callback;
+ };
+
+ struct StreamInfo {
+ StreamInfo() : parser(NULL),
+ read_headers_callback(NULL),
+ state(STREAM_CREATED) {}
+
+ 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'
+ OldCompletionCallback* read_headers_callback;
+ StreamState state;
+ };
+
+ typedef std::map<int, StreamInfo> StreamInfoMap;
+
+ // Called after the first request is sent or in a task sometime after the
+ // first stream is added to this pipeline. This gives the first request
+ // priority to send, but doesn't hold up other requests if it doesn't.
+ // When called the first time, notifies the |delegate_| that we can accept new
+ // requests.
+ void ActivatePipeline();
+
+ // 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 SendRequest() or
+ // ReadResponseHeaders() completing on an underlying parser. This might be
+ // invoked in response to our own IO callbacks, or it may be invoked if the
+ // underlying parser completes SendRequest() or ReadResponseHeaders()
+ // synchronously, but we've already returned ERR_IO_PENDING to the user's
+ // SendRequest() or ReadResponseHeaders() call into us.
+ void FireUserCallback(OldCompletionCallback* callback, 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_;
+
+ StreamInfoMap stream_info_map_;
+
+ std::queue<int> request_order_;
+
+ std::queue<DeferredSendRequest> deferred_request_queue_;
+ SendRequestState send_next_state_;
+ OldCompletionCallbackImpl<HttpPipelinedConnectionImpl> send_io_callback_;
+ OldCompletionCallback* send_user_callback_;
+
+ ReadHeadersState read_next_state_;
+ OldCompletionCallbackImpl<HttpPipelinedConnectionImpl> read_io_callback_;
+ OldCompletionCallback* read_user_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionImpl);
+};
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_PIPELINED_CONNECTION_IMPL_H_

Powered by Google App Engine
This is Rietveld 408576698