summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_stream.h
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy/spdy_stream.h')
-rw-r--r--net/spdy/spdy_stream.h211
1 files changed, 211 insertions, 0 deletions
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
new file mode 100644
index 0000000..ab2659e
--- /dev/null
+++ b/net/spdy/spdy_stream.h
@@ -0,0 +1,211 @@
+// Copyright (c) 2010 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_SPDY_SPDY_STREAM_H_
+#define NET_SPDY_SPDY_STREAM_H_
+
+#include <string>
+#include <list>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "net/base/bandwidth_metrics.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/load_log.h"
+#include "net/spdy/spdy_framer.h"
+#include "net/spdy/spdy_protocol.h"
+
+namespace net {
+
+class FlipSession;
+class HttpRequestInfo;
+class HttpResponseInfo;
+class UploadData;
+class UploadDataStream;
+
+// The FlipStream is used by the FlipSession to represent each stream known
+// on the FlipSession.
+// Streams can be created either by the client or by the server. When they
+// are initiated by the client, both the FlipSession and client object (such as
+// a FlipNetworkTransaction) will maintain a reference to the stream. When
+// initiated by the server, only the FlipSession will maintain any reference,
+// until such a time as a client object requests a stream for the path.
+class FlipStream : public base::RefCounted<FlipStream> {
+ public:
+ // FlipStream constructor
+ FlipStream(FlipSession* session, flip::FlipStreamId stream_id, bool pushed,
+ LoadLog* log);
+
+ // Ideally I'd use two abstract classes as interfaces for these two sections,
+ // but since we're ref counted, I can't make both abstract classes inherit
+ // from RefCounted or we'll have two separate ref counts for the same object.
+ // TODO(willchan): Consider using linked_ptr here orcreating proxy wrappers
+ // for FlipStream to provide the appropriate interface.
+
+ // ===================================================
+ // Interface for [Http|Flip]NetworkTransaction to use.
+
+ // Sends the request. If |upload_data| is non-NULL, sends that in the request
+ // body. |callback| is used when this completes asynchronously. Note that
+ // the actual SYN_STREAM packet will have already been sent by this point.
+ // Also note that FlipStream takes ownership of |upload_data|.
+ int SendRequest(UploadDataStream* upload_data,
+ HttpResponseInfo* response,
+ CompletionCallback* callback);
+
+ // Reads the response headers. Returns a net error code.
+ int ReadResponseHeaders(CompletionCallback* callback);
+
+ // Reads the response body. Returns a net error code or the number of bytes
+ // read.
+ int ReadResponseBody(
+ IOBuffer* buf, int buf_len, CompletionCallback* callback);
+
+ // Cancels the stream. Note that this does not immediately cause deletion of
+ // the stream. This function is used to cancel any callbacks from being
+ // invoked. TODO(willchan): It should also free up any memory associated with
+ // the stream, such as IOBuffers.
+ void Cancel();
+
+ // Returns the number of bytes uploaded.
+ uint64 GetUploadProgress() const;
+
+ const HttpResponseInfo* GetResponseInfo() const;
+
+ // Is this stream a pushed stream from the server.
+ bool pushed() const { return pushed_; }
+
+ // =================================
+ // Interface for FlipSession to use.
+
+ flip::FlipStreamId stream_id() const { return stream_id_; }
+ void set_stream_id(flip::FlipStreamId stream_id) { stream_id_ = stream_id; }
+
+ // For pushed streams, we track a path to identify them.
+ const std::string& path() const { return path_; }
+ void set_path(const std::string& path) { path_ = path; }
+
+ int priority() const { return priority_; }
+ void set_priority(int priority) { priority_ = priority; }
+
+ // Called by the FlipSession when a response (e.g. a SYN_REPLY) has been
+ // received for this stream. |path| is the path of the URL for a server
+ // initiated stream, otherwise is empty.
+ void OnResponseReceived(const HttpResponseInfo& response);
+
+ // Called by the FlipSession when response data has been received for this
+ // stream. This callback may be called multiple times as data arrives
+ // from the network, and will never be called prior to OnResponseReceived.
+ // |buffer| contains the data received. The stream must copy any data
+ // from this buffer before returning from this callback.
+ // |length| is the number of bytes received or an error.
+ // A zero-length count does not indicate end-of-stream.
+ // Returns true on success and false on error.
+ bool OnDataReceived(const char* buffer, int bytes);
+
+ // Called by the FlipSession when a write has completed. This callback
+ // will be called multiple times for each write which completes. Writes
+ // include the SYN_STREAM write and also DATA frame writes.
+ // |result| is the number of bytes written or a net error code.
+ void OnWriteComplete(int status);
+
+ // Called by the FlipSession when the request is finished. This callback
+ // will always be called at the end of the request and signals to the
+ // stream that the stream has no more network events. No further callbacks
+ // to the stream will be made after this call.
+ // |status| is an error code or OK.
+ void OnClose(int status);
+
+ bool cancelled() const { return cancelled_; }
+
+ void set_response_info_pointer(HttpResponseInfo* response_info) {
+ response_ = response_info;
+ }
+
+ private:
+ friend class base::RefCounted<FlipStream>;
+
+ enum State {
+ STATE_NONE,
+ STATE_SEND_HEADERS,
+ STATE_SEND_HEADERS_COMPLETE,
+ STATE_SEND_BODY,
+ STATE_SEND_BODY_COMPLETE,
+ STATE_READ_HEADERS,
+ STATE_READ_HEADERS_COMPLETE,
+ STATE_READ_BODY,
+ STATE_READ_BODY_COMPLETE,
+ STATE_DONE
+ };
+
+ ~FlipStream();
+
+ // Try to make progress sending/receiving the request/response.
+ int DoLoop(int result);
+
+ // Call the user callback.
+ void DoCallback(int rv);
+
+ // The implementations of each state of the state machine.
+ int DoSendHeaders();
+ int DoSendHeadersComplete(int result);
+ int DoSendBody();
+ int DoSendBodyComplete(int result);
+ int DoReadHeaders();
+ int DoReadHeadersComplete(int result);
+ int DoReadBody();
+ int DoReadBodyComplete(int result);
+
+ // Update the histograms. Can safely be called repeatedly, but should only
+ // be called after the stream has completed.
+ void UpdateHistograms();
+
+ flip::FlipStreamId stream_id_;
+ std::string path_;
+ int priority_;
+ const bool pushed_;
+ // We buffer the response body as it arrives asynchronously from the stream.
+ // TODO(mbelshe): is this infinite buffering?
+ std::list<scoped_refptr<IOBufferWithSize> > response_body_;
+ bool download_finished_;
+ ScopedBandwidthMetrics metrics_;
+
+ scoped_refptr<FlipSession> session_;
+
+ HttpResponseInfo* response_;
+ scoped_ptr<UploadDataStream> request_body_stream_;
+
+ bool response_complete_; // TODO(mbelshe): fold this into the io_state.
+ State io_state_;
+
+ // Since we buffer the response, we also buffer the response status.
+ // Not valid until response_complete_ is true.
+ int response_status_;
+
+ CompletionCallback* user_callback_;
+
+ // User provided buffer for the ReadResponseBody() response.
+ scoped_refptr<IOBuffer> user_buffer_;
+ int user_buffer_len_;
+
+ bool cancelled_;
+
+ scoped_refptr<LoadLog> load_log_;
+
+ base::TimeTicks send_time_;
+ base::TimeTicks recv_first_byte_time_;
+ base::TimeTicks recv_last_byte_time_;
+ int send_bytes_;
+ int recv_bytes_;
+ bool histograms_recorded_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlipStream);
+};
+
+} // namespace net
+
+#endif // NET_SPDY_SPDY_STREAM_H_