Home | History | Annotate | Download | only in spdy
      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