Home | History | Annotate | Download | only in quic
      1 // Copyright 2013 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 #include "net/quic/quic_headers_stream.h"
      6 
      7 #include "net/quic/quic_session.h"
      8 
      9 using base::StringPiece;
     10 
     11 namespace net {
     12 
     13 namespace {
     14 
     15 const QuicStreamId kInvalidStreamId = 0;
     16 
     17 }  // namespace
     18 
     19 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
     20 // the QuicDataStream, and closes the connection if any unexpected frames
     21 // are received.
     22 class QuicHeadersStream::SpdyFramerVisitor
     23     : public SpdyFramerVisitorInterface,
     24       public SpdyFramerDebugVisitorInterface {
     25  public:
     26   explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
     27 
     28   // SpdyFramerVisitorInterface implementation
     29   virtual void OnSynStream(SpdyStreamId stream_id,
     30                            SpdyStreamId associated_stream_id,
     31                            SpdyPriority priority,
     32                            bool fin,
     33                            bool unidirectional) OVERRIDE {
     34     if (!stream_->IsConnected()) {
     35       return;
     36     }
     37 
     38     if (associated_stream_id != 0) {
     39       CloseConnection("associated_stream_id != 0");
     40       return;
     41     }
     42 
     43     if (unidirectional != 0) {
     44       CloseConnection("unidirectional != 0");
     45       return;
     46     }
     47 
     48     stream_->OnSynStream(stream_id, priority, fin);
     49   }
     50 
     51   virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
     52     if (!stream_->IsConnected()) {
     53       return;
     54     }
     55 
     56     stream_->OnSynReply(stream_id, fin);
     57   }
     58 
     59   virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
     60                                         const char* header_data,
     61                                         size_t len) OVERRIDE {
     62     if (!stream_->IsConnected()) {
     63       return false;
     64     }
     65     stream_->OnControlFrameHeaderData(stream_id, header_data, len);
     66     return true;
     67   }
     68 
     69   virtual void OnStreamFrameData(SpdyStreamId stream_id,
     70                                  const char* data,
     71                                  size_t len,
     72                                  bool fin) OVERRIDE {
     73     if (fin && len == 0) {
     74       // The framer invokes OnStreamFrameData with zero-length data and
     75       // fin = true after processing a SYN_STREAM or SYN_REPLY frame
     76       // that had the fin bit set.
     77       return;
     78     }
     79     CloseConnection("SPDY DATA frame received.");
     80   }
     81 
     82   virtual void OnError(SpdyFramer* framer) OVERRIDE {
     83     CloseConnection("SPDY framing error.");
     84   }
     85 
     86   virtual void OnDataFrameHeader(SpdyStreamId stream_id,
     87                                  size_t length,
     88                                  bool fin) OVERRIDE {
     89     CloseConnection("SPDY DATA frame received.");
     90   }
     91 
     92   virtual void OnRstStream(SpdyStreamId stream_id,
     93                            SpdyRstStreamStatus status) OVERRIDE {
     94     CloseConnection("SPDY RST_STREAM frame received.");
     95   }
     96 
     97   virtual void OnSetting(SpdySettingsIds id,
     98                          uint8 flags,
     99                          uint32 value) OVERRIDE {
    100     CloseConnection("SPDY SETTINGS frame received.");
    101   }
    102 
    103   virtual void OnSettingsAck() OVERRIDE {
    104     CloseConnection("SPDY SETTINGS frame received.");
    105   }
    106 
    107   virtual void OnSettingsEnd() OVERRIDE {
    108     CloseConnection("SPDY SETTINGS frame received.");
    109   }
    110 
    111   virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
    112     CloseConnection("SPDY PING frame received.");
    113   }
    114 
    115   virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
    116                         SpdyGoAwayStatus status) OVERRIDE {
    117     CloseConnection("SPDY GOAWAY frame received.");
    118   }
    119 
    120   virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE {
    121     CloseConnection("SPDY HEADERS frame received.");
    122   }
    123 
    124   virtual void OnWindowUpdate(SpdyStreamId stream_id,
    125                               uint32 delta_window_size) OVERRIDE {
    126     CloseConnection("SPDY WINDOW_UPDATE frame received.");
    127   }
    128 
    129   virtual void OnPushPromise(SpdyStreamId stream_id,
    130                              SpdyStreamId promised_stream_id,
    131                              bool end) OVERRIDE {
    132     LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer";
    133     CloseConnection("SPDY PUSH_PROMISE frame received.");
    134   }
    135 
    136   virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
    137     CloseConnection("SPDY CONTINUATION frame received.");
    138   }
    139 
    140   virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) OVERRIDE {
    141     CloseConnection("SPDY unknown frame received.");
    142     return false;
    143   }
    144 
    145   // SpdyFramerDebugVisitorInterface implementation
    146   virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
    147                                      SpdyFrameType type,
    148                                      size_t payload_len,
    149                                      size_t frame_len) OVERRIDE {}
    150 
    151   virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
    152                                         SpdyFrameType type,
    153                                         size_t frame_len) OVERRIDE {
    154     if (stream_->IsConnected()) {
    155       stream_->OnCompressedFrameSize(frame_len);
    156     }
    157   }
    158 
    159  private:
    160   void CloseConnection(const string& details) {
    161     if (stream_->IsConnected()) {
    162       stream_->CloseConnectionWithDetails(
    163           QUIC_INVALID_HEADERS_STREAM_DATA, details);
    164     }
    165   }
    166 
    167  private:
    168   QuicHeadersStream* stream_;
    169 
    170   DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
    171 };
    172 
    173 QuicHeadersStream::QuicHeadersStream(QuicSession* session)
    174     : ReliableQuicStream(kHeadersStreamId, session),
    175       stream_id_(kInvalidStreamId),
    176       fin_(false),
    177       frame_len_(0),
    178       spdy_framer_(SPDY3),
    179       spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
    180   spdy_framer_.set_visitor(spdy_framer_visitor_.get());
    181   spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
    182   if (version() < QUIC_VERSION_21) {
    183     // Prior to QUIC_VERSION_21 the headers stream is not subject to any flow
    184     // control.
    185     DisableFlowControl();
    186   }
    187   // The headers stream is exempt from connection level flow control.
    188   DisableConnectionFlowControlForThisStream();
    189 }
    190 
    191 QuicHeadersStream::~QuicHeadersStream() {}
    192 
    193 size_t QuicHeadersStream::WriteHeaders(
    194     QuicStreamId stream_id,
    195     const SpdyHeaderBlock& headers,
    196     bool fin,
    197     QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
    198   scoped_ptr<SpdySerializedFrame> frame;
    199   if (session()->is_server()) {
    200     SpdySynReplyIR syn_reply(stream_id);
    201     syn_reply.set_name_value_block(headers);
    202     syn_reply.set_fin(fin);
    203     frame.reset(spdy_framer_.SerializeFrame(syn_reply));
    204   } else {
    205     SpdySynStreamIR syn_stream(stream_id);
    206     syn_stream.set_name_value_block(headers);
    207     syn_stream.set_fin(fin);
    208     frame.reset(spdy_framer_.SerializeFrame(syn_stream));
    209   }
    210   WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
    211                     ack_notifier_delegate);
    212   return frame->size();
    213 }
    214 
    215 uint32 QuicHeadersStream::ProcessRawData(const char* data,
    216                                          uint32 data_len) {
    217   return spdy_framer_.ProcessInput(data, data_len);
    218 }
    219 
    220 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
    221 
    222 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
    223                                     SpdyPriority priority,
    224                                     bool fin) {
    225   if (!session()->is_server()) {
    226     CloseConnectionWithDetails(
    227         QUIC_INVALID_HEADERS_STREAM_DATA,
    228         "SPDY SYN_STREAM frame received at the client");
    229     return;
    230   }
    231   DCHECK_EQ(kInvalidStreamId, stream_id_);
    232   stream_id_ = stream_id;
    233   fin_ = fin;
    234   session()->OnStreamHeadersPriority(stream_id, priority);
    235 }
    236 
    237 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
    238   if (session()->is_server()) {
    239     CloseConnectionWithDetails(
    240         QUIC_INVALID_HEADERS_STREAM_DATA,
    241         "SPDY SYN_REPLY frame received at the server");
    242     return;
    243   }
    244   DCHECK_EQ(kInvalidStreamId, stream_id_);
    245   stream_id_ = stream_id;
    246   fin_ = fin;
    247 }
    248 
    249 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
    250                                                  const char* header_data,
    251                                                  size_t len) {
    252   DCHECK_EQ(stream_id_, stream_id);
    253   if (len == 0) {
    254     DCHECK_NE(0u, stream_id_);
    255     DCHECK_NE(0u, frame_len_);
    256     session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
    257     // Reset state for the next frame.
    258     stream_id_ = kInvalidStreamId;
    259     fin_ = false;
    260     frame_len_ = 0;
    261   } else {
    262     session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
    263   }
    264 }
    265 
    266 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
    267   DCHECK_EQ(kInvalidStreamId, stream_id_);
    268   DCHECK_EQ(0u, frame_len_);
    269   frame_len_ = frame_len;
    270 }
    271 
    272 bool QuicHeadersStream::IsConnected() {
    273   return session()->connection()->connected();
    274 }
    275 
    276 }  // namespace net
    277