• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
Delegate()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>;
~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);
GetDelegate()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.
pushed()109   bool pushed() const { return pushed_; }
110 
stream_id()111   spdy::SpdyStreamId stream_id() const { return stream_id_; }
set_stream_id(spdy::SpdyStreamId stream_id)112   void set_stream_id(spdy::SpdyStreamId stream_id) { stream_id_ = stream_id; }
113 
response_received()114   bool response_received() const { return response_received_; }
set_response_received()115   void set_response_received() { response_received_ = true; }
116 
117   // For pushed streams, we track a path to identify them.
path()118   const std::string& path() const { return path_; }
set_path(const std::string & path)119   void set_path(const std::string& path) { path_ = path; }
120 
priority()121   int priority() const { return priority_; }
set_priority(int priority)122   void set_priority(int priority) { priority_ = priority; }
123 
send_window_size()124   int send_window_size() const { return send_window_size_; }
set_send_window_size(int window_size)125   void set_send_window_size(int window_size) {
126     send_window_size_ = window_size;
127   }
128 
recv_window_size()129   int recv_window_size() const { return recv_window_size_; }
set_recv_window_size(int window_size)130   void set_recv_window_size(int window_size) {
131     recv_window_size_ = window_size;
132   }
133 
set_stalled_by_flow_control(bool stalled)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 
net_log()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();
cancelled()201   bool cancelled() const { return cancelled_; }
closed()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 
is_idle()221   bool is_idle() const {
222     return io_state_ == STATE_OPEN || io_state_ == STATE_DONE;
223   }
224 
response_status()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