1 // Copyright (c) 2009 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_FLIP_FLIP_STREAM_H_ 6 #define NET_FLIP_FLIP_STREAM_H_ 7 8 #include <string> 9 #include <list> 10 11 #include "base/basictypes.h" 12 #include "base/ref_counted.h" 13 #include "base/scoped_ptr.h" 14 #include "base/singleton.h" 15 #include "net/base/bandwidth_metrics.h" 16 #include "net/base/completion_callback.h" 17 #include "net/base/io_buffer.h" 18 #include "net/base/load_log.h" 19 #include "net/flip/flip_framer.h" 20 #include "net/flip/flip_protocol.h" 21 22 namespace net { 23 24 class FlipSession; 25 class HttpRequestInfo; 26 class HttpResponseInfo; 27 class UploadData; 28 class UploadDataStream; 29 30 // The FlipStream is used by the FlipSession to represent each stream known 31 // on the FlipSession. 32 // Streams can be created either by the client or by the server. When they 33 // are initiated by the client, both the FlipSession and client object (such as 34 // a FlipNetworkTransaction) will maintain a reference to the stream. When 35 // initiated by the server, only the FlipSession will maintain any reference, 36 // until such a time as a client object requests a stream for the path. 37 class FlipStream : public base::RefCounted<FlipStream> { 38 public: 39 // FlipStream constructor 40 FlipStream(FlipSession* session, flip::FlipStreamId stream_id, bool pushed, 41 LoadLog* log); 42 43 // Ideally I'd use two abstract classes as interfaces for these two sections, 44 // but since we're ref counted, I can't make both abstract classes inherit 45 // from RefCounted or we'll have two separate ref counts for the same object. 46 // TODO(willchan): Consider using linked_ptr here orcreating proxy wrappers 47 // for FlipStream to provide the appropriate interface. 48 49 // =================================================== 50 // Interface for [Http|Flip]NetworkTransaction to use. 51 52 // Sends the request. If |upload_data| is non-NULL, sends that in the request 53 // body. |callback| is used when this completes asynchronously. Note that 54 // the actual SYN_STREAM packet will have already been sent by this point. 55 // Also note that FlipStream takes ownership of |upload_data|. 56 int SendRequest(UploadDataStream* upload_data, 57 HttpResponseInfo* response, 58 CompletionCallback* callback); 59 60 // Reads the response headers. Returns a net error code. 61 int ReadResponseHeaders(CompletionCallback* callback); 62 63 // Reads the response body. Returns a net error code or the number of bytes 64 // read. 65 int ReadResponseBody( 66 IOBuffer* buf, int buf_len, CompletionCallback* callback); 67 68 // Cancels the stream. Note that this does not immediately cause deletion of 69 // the stream. This function is used to cancel any callbacks from being 70 // invoked. TODO(willchan): It should also free up any memory associated with 71 // the stream, such as IOBuffers. 72 void Cancel(); 73 74 // Returns the number of bytes uploaded. 75 uint64 GetUploadProgress() const; 76 77 const HttpResponseInfo* GetResponseInfo() const; 78 79 // Is this stream a pushed stream from the server. pushed()80 bool pushed() const { return pushed_; } 81 82 // ================================= 83 // Interface for FlipSession to use. 84 stream_id()85 flip::FlipStreamId stream_id() const { return stream_id_; } set_stream_id(flip::FlipStreamId stream_id)86 void set_stream_id(flip::FlipStreamId stream_id) { stream_id_ = stream_id; } 87 88 // For pushed streams, we track a path to identify them. path()89 const std::string& path() const { return path_; } set_path(const std::string & path)90 void set_path(const std::string& path) { path_ = path; } 91 priority()92 int priority() const { return priority_; } set_priority(int priority)93 void set_priority(int priority) { priority_ = priority; } 94 95 // Called by the FlipSession when a response (e.g. a SYN_REPLY) has been 96 // received for this stream. |path| is the path of the URL for a server 97 // initiated stream, otherwise is empty. 98 void OnResponseReceived(const HttpResponseInfo& response); 99 100 // Called by the FlipSession when response data has been received for this 101 // stream. This callback may be called multiple times as data arrives 102 // from the network, and will never be called prior to OnResponseReceived. 103 // |buffer| contains the data received. The stream must copy any data 104 // from this buffer before returning from this callback. 105 // |length| is the number of bytes received or an error. 106 // A zero-length count does not indicate end-of-stream. 107 // Returns true on success and false on error. 108 bool OnDataReceived(const char* buffer, int bytes); 109 110 // Called by the FlipSession when a write has completed. This callback 111 // will be called multiple times for each write which completes. Writes 112 // include the SYN_STREAM write and also DATA frame writes. 113 // |result| is the number of bytes written or a net error code. 114 void OnWriteComplete(int status); 115 116 // Called by the FlipSession when the request is finished. This callback 117 // will always be called at the end of the request and signals to the 118 // stream that the stream has no more network events. No further callbacks 119 // to the stream will be made after this call. 120 // |status| is an error code or OK. 121 void OnClose(int status); 122 cancelled()123 bool cancelled() const { return cancelled_; } 124 125 private: 126 friend class base::RefCounted<FlipStream>; 127 128 enum State { 129 STATE_NONE, 130 STATE_SEND_HEADERS, 131 STATE_SEND_HEADERS_COMPLETE, 132 STATE_SEND_BODY, 133 STATE_SEND_BODY_COMPLETE, 134 STATE_READ_HEADERS, 135 STATE_READ_HEADERS_COMPLETE, 136 STATE_READ_BODY, 137 STATE_READ_BODY_COMPLETE, 138 STATE_DONE 139 }; 140 141 ~FlipStream(); 142 143 // Try to make progress sending/receiving the request/response. 144 int DoLoop(int result); 145 146 // Call the user callback. 147 void DoCallback(int rv); 148 149 // The implementations of each state of the state machine. 150 int DoSendHeaders(); 151 int DoSendHeadersComplete(int result); 152 int DoSendBody(); 153 int DoSendBodyComplete(int result); 154 int DoReadHeaders(); 155 int DoReadHeadersComplete(int result); 156 int DoReadBody(); 157 int DoReadBodyComplete(int result); 158 159 // Update the histograms. Can safely be called repeatedly, but should only 160 // be called after the stream has completed. 161 void UpdateHistograms(); 162 163 flip::FlipStreamId stream_id_; 164 std::string path_; 165 int priority_; 166 const bool pushed_; 167 // We buffer the response body as it arrives asynchronously from the stream. 168 // TODO(mbelshe): is this infinite buffering? 169 std::list<scoped_refptr<IOBufferWithSize> > response_body_; 170 bool download_finished_; 171 ScopedBandwidthMetrics metrics_; 172 173 scoped_refptr<FlipSession> session_; 174 175 HttpResponseInfo* response_; 176 scoped_ptr<UploadDataStream> request_body_stream_; 177 178 bool response_complete_; // TODO(mbelshe): fold this into the io_state. 179 State io_state_; 180 181 // Since we buffer the response, we also buffer the response status. 182 // Not valid until response_complete_ is true. 183 int response_status_; 184 185 CompletionCallback* user_callback_; 186 187 // User provided buffer for the ReadResponseBody() response. 188 scoped_refptr<IOBuffer> user_buffer_; 189 int user_buffer_len_; 190 191 bool cancelled_; 192 193 scoped_refptr<LoadLog> load_log_; 194 195 base::TimeTicks send_time_; 196 base::TimeTicks recv_first_byte_time_; 197 base::TimeTicks recv_last_byte_time_; 198 int send_bytes_; 199 int recv_bytes_; 200 bool histograms_recorded_; 201 202 DISALLOW_COPY_AND_ASSIGN(FlipStream); 203 }; 204 205 } // namespace net 206 207 #endif // NET_FLIP_FLIP_STREAM_H_ 208