15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_headers_stream.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_session.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::StringPiece;
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net {
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const QuicStreamId kInvalidStreamId = 0;
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the QuicDataStream, and closes the connection if any unexpected frames
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// are received.
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class QuicHeadersStream::SpdyFramerVisitor
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : public SpdyFramerVisitorInterface,
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      public SpdyFramerDebugVisitorInterface {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // SpdyFramerVisitorInterface implementation
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnSynStream(SpdyStreamId stream_id,
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           SpdyStreamId associated_stream_id,
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           SpdyPriority priority,
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           bool fin,
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           bool unidirectional) OVERRIDE {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!stream_->IsConnected()) {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (associated_stream_id != 0) {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CloseConnection("associated_stream_id != 0");
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (unidirectional != 0) {
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CloseConnection("unidirectional != 0");
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream_->OnSynStream(stream_id, priority, fin);
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!stream_->IsConnected()) {
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream_->OnSynReply(stream_id, fin);
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const char* header_data,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        size_t len) OVERRIDE {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!stream_->IsConnected()) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream_->OnControlFrameHeaderData(stream_id, header_data, len);
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnStreamFrameData(SpdyStreamId stream_id,
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 const char* data,
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 size_t len,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 bool fin) OVERRIDE {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (fin && len == 0) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // The framer invokes OnStreamFrameData with zero-length data and
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // fin = true after processing a SYN_STREAM or SYN_REPLY frame
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // that had the fin bit set.
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY DATA frame received.");
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnError(SpdyFramer* framer) OVERRIDE {
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloseConnection("SPDY framing error.");
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnDataFrameHeader(SpdyStreamId stream_id,
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 size_t length,
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 bool fin) OVERRIDE {
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY DATA frame received.");
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnRstStream(SpdyStreamId stream_id,
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           SpdyRstStreamStatus status) OVERRIDE {
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY RST_STREAM frame received.");
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnSetting(SpdySettingsIds id,
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         uint8 flags,
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         uint32 value) OVERRIDE {
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY SETTINGS frame received.");
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnSettingsAck() OVERRIDE {
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY SETTINGS frame received.");
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnSettingsEnd() OVERRIDE {
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY SETTINGS frame received.");
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY PING frame received.");
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        SpdyGoAwayStatus status) OVERRIDE {
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY GOAWAY frame received.");
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE {
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY HEADERS frame received.");
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWindowUpdate(SpdyStreamId stream_id,
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              uint32 delta_window_size) OVERRIDE {
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY WINDOW_UPDATE frame received.");
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPushPromise(SpdyStreamId stream_id,
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             SpdyStreamId promised_stream_id,
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             bool end) OVERRIDE {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer";
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY PUSH_PROMISE frame received.");
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    CloseConnection("SPDY CONTINUATION frame received.");
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) OVERRIDE {
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CloseConnection("SPDY unknown frame received.");
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // SpdyFramerDebugVisitorInterface implementation
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     SpdyFrameType type,
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     size_t payload_len,
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     size_t frame_len) OVERRIDE {}
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        SpdyFrameType type,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        size_t frame_len) OVERRIDE {
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (stream_->IsConnected()) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      stream_->OnCompressedFrameSize(frame_len);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CloseConnection(const string& details) {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (stream_->IsConnected()) {
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      stream_->CloseConnectionWithDetails(
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          QUIC_INVALID_HEADERS_STREAM_DATA, details);
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicHeadersStream* stream_;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicHeadersStream::QuicHeadersStream(QuicSession* session)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : ReliableQuicStream(kHeadersStreamId, session),
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      stream_id_(kInvalidStreamId),
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      fin_(false),
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      frame_len_(0),
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_framer_(SPDY3),
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_framer_.set_visitor(spdy_framer_visitor_.get());
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (version() < QUIC_VERSION_21) {
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Prior to QUIC_VERSION_21 the headers stream is not subject to any flow
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // control.
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DisableFlowControl();
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The headers stream is exempt from connection level flow control.
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DisableConnectionFlowControlForThisStream();
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicHeadersStream::~QuicHeadersStream() {}
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicHeadersStream::WriteHeaders(
19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicStreamId stream_id,
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyHeaderBlock& headers,
19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdySerializedFrame> frame;
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (session()->is_server()) {
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SpdySynReplyIR syn_reply(stream_id);
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syn_reply.set_name_value_block(headers);
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syn_reply.set_fin(fin);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    frame.reset(spdy_framer_.SerializeFrame(syn_reply));
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SpdySynStreamIR syn_stream(stream_id);
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syn_stream.set_name_value_block(headers);
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    syn_stream.set_fin(fin);
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    frame.reset(spdy_framer_.SerializeFrame(syn_stream));
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    ack_notifier_delegate);
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return frame->size();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint32 QuicHeadersStream::ProcessRawData(const char* data,
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         uint32 data_len) {
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return spdy_framer_.ProcessInput(data, data_len);
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    SpdyPriority priority,
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    bool fin) {
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!session()->is_server()) {
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloseConnectionWithDetails(
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_HEADERS_STREAM_DATA,
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        "SPDY SYN_STREAM frame received at the client");
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(kInvalidStreamId, stream_id_);
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream_id_ = stream_id;
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  fin_ = fin;
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session()->OnStreamHeadersPriority(stream_id, priority);
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (session()->is_server()) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloseConnectionWithDetails(
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        QUIC_INVALID_HEADERS_STREAM_DATA,
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        "SPDY SYN_REPLY frame received at the server");
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(kInvalidStreamId, stream_id_);
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream_id_ = stream_id;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  fin_ = fin;
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                 const char* header_data,
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                 size_t len) {
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(stream_id_, stream_id);
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len == 0) {
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(0u, stream_id_);
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_NE(0u, frame_len_);
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Reset state for the next frame.
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    stream_id_ = kInvalidStreamId;
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    fin_ = false;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    frame_len_ = 0;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(kInvalidStreamId, stream_id_);
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(0u, frame_len_);
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  frame_len_ = frame_len;
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicHeadersStream::IsConnected() {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return session()->connection()->connected();
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace net
277