diff options
Diffstat (limited to 'net/spdy/spdy_stream.h')
-rw-r--r-- | net/spdy/spdy_stream.h | 211 |
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_ |