1 // Copyright (c) 2011 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_SPDY_SPDY_STREAM_H_ 6 #define NET_SPDY_SPDY_STREAM_H_ 7 #pragma once 8 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/memory/linked_ptr.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "googleurl/src/gurl.h" 17 #include "net/base/bandwidth_metrics.h" 18 #include "net/base/io_buffer.h" 19 #include "net/base/upload_data.h" 20 #include "net/base/net_log.h" 21 #include "net/spdy/spdy_framer.h" 22 #include "net/spdy/spdy_protocol.h" 23 24 namespace net { 25 26 class AddressList; 27 class IPEndPoint; 28 class SpdySession; 29 class SSLCertRequestInfo; 30 class SSLInfo; 31 32 // The SpdyStream is used by the SpdySession to represent each stream known 33 // on the SpdySession. This class provides interfaces for SpdySession to use. 34 // Streams can be created either by the client or by the server. When they 35 // are initiated by the client, both the SpdySession and client object (such as 36 // a SpdyNetworkTransaction) will maintain a reference to the stream. When 37 // initiated by the server, only the SpdySession will maintain any reference, 38 // until such a time as a client object requests a stream for the path. 39 class SpdyStream 40 : public base::RefCounted<SpdyStream>, 41 public ChunkCallback { 42 public: 43 // Delegate handles protocol specific behavior of spdy stream. 44 class Delegate { 45 public: 46 Delegate() {} 47 48 // Called when SYN frame has been sent. 49 // Returns true if no more data to be sent after SYN frame. 50 virtual bool OnSendHeadersComplete(int status) = 0; 51 52 // Called when stream is ready to send data. 53 // Returns network error code. OK when it successfully sent data. 54 virtual int OnSendBody() = 0; 55 56 // Called when data has been sent. |status| indicates network error 57 // or number of bytes that has been sent. On return, |eof| is set to true 58 // if no more data is available to send in the request body. 59 // Returns network error code. OK when it successfully sent data. 60 virtual int OnSendBodyComplete(int status, bool* eof) = 0; 61 62 // Called when the SYN_STREAM, SYN_REPLY, or HEADERS frames are received. 63 // Normal streams will receive a SYN_REPLY and optional HEADERS frames. 64 // Pushed streams will receive a SYN_STREAM and optional HEADERS frames. 65 // Because a stream may have a SYN_* frame and multiple HEADERS frames, 66 // this callback may be called multiple times. 67 // |status| indicates network error. Returns network error code. 68 virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response, 69 base::Time response_time, 70 int status) = 0; 71 72 // Called when data is received. 73 virtual void OnDataReceived(const char* data, int length) = 0; 74 75 // Called when data is sent. 76 virtual void OnDataSent(int length) = 0; 77 78 // Called when SpdyStream is closed. 79 virtual void OnClose(int status) = 0; 80 81 // Sets the callback to be invoked when a new chunk is available to upload. 82 virtual void set_chunk_callback(ChunkCallback* callback) = 0; 83 84 protected: 85 friend class base::RefCounted<Delegate>; 86 virtual ~Delegate() {} 87 88 private: 89 DISALLOW_COPY_AND_ASSIGN(Delegate); 90 }; 91 92 // SpdyStream constructor 93 SpdyStream(SpdySession* session, 94 spdy::SpdyStreamId stream_id, 95 bool pushed, 96 const BoundNetLog& net_log); 97 98 // Set new |delegate|. |delegate| must not be NULL. 99 // If it already received SYN_REPLY or data, OnResponseReceived() or 100 // OnDataReceived() will be called. 101 void SetDelegate(Delegate* delegate); 102 Delegate* GetDelegate() { return delegate_; } 103 104 // Detach delegate from the stream. It will cancel the stream if it was not 105 // cancelled yet. It is safe to call multiple times. 106 void DetachDelegate(); 107 108 // Is this stream a pushed stream from the server. 109 bool pushed() const { return pushed_; } 110 111 spdy::SpdyStreamId stream_id() const { return stream_id_; } 112 void set_stream_id(spdy::SpdyStreamId stream_id) { stream_id_ = stream_id; } 113 114 bool response_received() const { return response_received_; } 115 void set_response_received() { response_received_ = true; } 116 117 // For pushed streams, we track a path to identify them. 118 const std::string& path() const { return path_; } 119 void set_path(const std::string& path) { path_ = path; } 120 121 int priority() const { return priority_; } 122 void set_priority(int priority) { priority_ = priority; } 123 124 int send_window_size() const { return send_window_size_; } 125 void set_send_window_size(int window_size) { 126 send_window_size_ = window_size; 127 } 128 129 int recv_window_size() const { return recv_window_size_; } 130 void set_recv_window_size(int window_size) { 131 recv_window_size_ = window_size; 132 } 133 134 void set_stalled_by_flow_control(bool stalled) { 135 stalled_by_flow_control_ = stalled; 136 } 137 138 // Increases |send_window_size_| with delta extracted from a WINDOW_UPDATE 139 // frame; sends a RST_STREAM if delta overflows |send_window_size_| and 140 // removes the stream from the session. 141 void IncreaseSendWindowSize(int delta_window_size); 142 143 // Decreases |send_window_size_| by the given number of bytes. 144 void DecreaseSendWindowSize(int delta_window_size); 145 146 int GetPeerAddress(AddressList* address) const; 147 int GetLocalAddress(IPEndPoint* address) const; 148 149 // Returns true if the underlying transport socket ever had any reads or 150 // writes. 151 bool WasEverUsed() const; 152 153 // Increases |recv_window_size_| by the given number of bytes, also sends 154 // a WINDOW_UPDATE frame. 155 void IncreaseRecvWindowSize(int delta_window_size); 156 157 // Decreases |recv_window_size_| by the given number of bytes, called 158 // whenever data is read. May also send a RST_STREAM and remove the 159 // stream from the session if the resultant |recv_window_size_| is 160 // negative, since that would be a flow control violation. 161 void DecreaseRecvWindowSize(int delta_window_size); 162 163 const BoundNetLog& net_log() const { return net_log_; } 164 165 const linked_ptr<spdy::SpdyHeaderBlock>& spdy_headers() const; 166 void set_spdy_headers(const linked_ptr<spdy::SpdyHeaderBlock>& headers); 167 base::Time GetRequestTime() const; 168 void SetRequestTime(base::Time t); 169 170 // Called by the SpdySession when a response (e.g. a SYN_STREAM or SYN_REPLY) 171 // has been received for this stream. Returns a status code. 172 int OnResponseReceived(const spdy::SpdyHeaderBlock& response); 173 174 // Called by the SpdySession when late-bound headers are received for a 175 // stream. Returns a status code. 176 int OnHeaders(const spdy::SpdyHeaderBlock& headers); 177 178 // Called by the SpdySession when response data has been received for this 179 // stream. This callback may be called multiple times as data arrives 180 // from the network, and will never be called prior to OnResponseReceived. 181 // |buffer| contains the data received. The stream must copy any data 182 // from this buffer before returning from this callback. 183 // |length| is the number of bytes received or an error. 184 // A zero-length count does not indicate end-of-stream. 185 void OnDataReceived(const char* buffer, int bytes); 186 187 // Called by the SpdySession when a write has completed. This callback 188 // will be called multiple times for each write which completes. Writes 189 // include the SYN_STREAM write and also DATA frame writes. 190 // |result| is the number of bytes written or a net error code. 191 void OnWriteComplete(int bytes); 192 193 // Called by the SpdySession when the request is finished. This callback 194 // will always be called at the end of the request and signals to the 195 // stream that the stream has no more network events. No further callbacks 196 // to the stream will be made after this call. 197 // |status| is an error code or OK. 198 void OnClose(int status); 199 200 void Cancel(); 201 bool cancelled() const { return cancelled_; } 202 bool closed() const { return io_state_ == STATE_DONE; } 203 204 // Interface for Spdy[Http|WebSocket]Stream to use. 205 206 // Sends the request. 207 // For non push stream, it will send SYN_STREAM frame. 208 int SendRequest(bool has_upload_data); 209 210 // Sends DATA frame. 211 int WriteStreamData(IOBuffer* data, int length, 212 spdy::SpdyDataFlags flags); 213 214 // Fills SSL info in |ssl_info| and returns true when SSL is in use. 215 bool GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated); 216 217 // Fills SSL Certificate Request info |cert_request_info| and returns 218 // true when SSL is in use. 219 bool GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); 220 221 bool is_idle() const { 222 return io_state_ == STATE_OPEN || io_state_ == STATE_DONE; 223 } 224 225 int response_status() const { return response_status_; } 226 227 // Returns true if the URL for this stream is known. 228 bool HasUrl() const; 229 230 // Get the URL associated with this stream. Only valid when has_url() is 231 // true. 232 GURL GetUrl() const; 233 234 // ChunkCallback methods. 235 virtual void OnChunkAvailable(); 236 237 private: 238 enum State { 239 STATE_NONE, 240 STATE_SEND_HEADERS, 241 STATE_SEND_HEADERS_COMPLETE, 242 STATE_SEND_BODY, 243 STATE_SEND_BODY_COMPLETE, 244 STATE_WAITING_FOR_RESPONSE, 245 STATE_OPEN, 246 STATE_DONE 247 }; 248 249 friend class base::RefCounted<SpdyStream>; 250 virtual ~SpdyStream(); 251 252 // Try to make progress sending/receiving the request/response. 253 int DoLoop(int result); 254 255 // The implementations of each state of the state machine. 256 int DoSendHeaders(); 257 int DoSendHeadersComplete(int result); 258 int DoSendBody(); 259 int DoSendBodyComplete(int result); 260 int DoReadHeaders(); 261 int DoReadHeadersComplete(int result); 262 int DoOpen(int result); 263 264 // Update the histograms. Can safely be called repeatedly, but should only 265 // be called after the stream has completed. 266 void UpdateHistograms(); 267 268 // When a server pushed stream is first created, this function is posted on 269 // the MessageLoop to replay all the data that the server has already sent. 270 void PushedStreamReplayData(); 271 272 // There is a small period of time between when a server pushed stream is 273 // first created, and the pushed data is replayed. Any data received during 274 // this time should continue to be buffered. 275 bool continue_buffering_data_; 276 277 spdy::SpdyStreamId stream_id_; 278 std::string path_; 279 int priority_; 280 281 // Flow control variables. 282 bool stalled_by_flow_control_; 283 int send_window_size_; 284 int recv_window_size_; 285 286 const bool pushed_; 287 ScopedBandwidthMetrics metrics_; 288 bool response_received_; 289 290 scoped_refptr<SpdySession> session_; 291 292 // The transaction should own the delegate. 293 SpdyStream::Delegate* delegate_; 294 295 // The request to send. 296 linked_ptr<spdy::SpdyHeaderBlock> request_; 297 298 // The time at which the request was made that resulted in this response. 299 // For cached responses, this time could be "far" in the past. 300 base::Time request_time_; 301 302 linked_ptr<spdy::SpdyHeaderBlock> response_; 303 base::Time response_time_; 304 305 State io_state_; 306 307 // Since we buffer the response, we also buffer the response status. 308 // Not valid until the stream is closed. 309 int response_status_; 310 311 bool cancelled_; 312 bool has_upload_data_; 313 314 BoundNetLog net_log_; 315 316 base::TimeTicks send_time_; 317 base::TimeTicks recv_first_byte_time_; 318 base::TimeTicks recv_last_byte_time_; 319 int send_bytes_; 320 int recv_bytes_; 321 // Data received before delegate is attached. 322 std::vector<scoped_refptr<IOBufferWithSize> > pending_buffers_; 323 324 DISALLOW_COPY_AND_ASSIGN(SpdyStream); 325 }; 326 327 } // namespace net 328 329 #endif // NET_SPDY_SPDY_STREAM_H_ 330