Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / net / quic / quic_headers_stream.cc
blob584b87e57adafe5962ddf7892b2db7ea7d9bb900
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.
5 #include "net/quic/quic_headers_stream.h"
7 #include "base/strings/stringprintf.h"
8 #include "net/quic/quic_spdy_session.h"
10 using base::StringPiece;
11 using std::string;
13 namespace net {
15 namespace {
17 const QuicStreamId kInvalidStreamId = 0;
19 } // namespace
21 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
22 // the QuicDataStream, and closes the connection if any unexpected frames
23 // are received.
24 class QuicHeadersStream::SpdyFramerVisitor
25 : public SpdyFramerVisitorInterface,
26 public SpdyFramerDebugVisitorInterface {
27 public:
28 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
30 // SpdyFramerVisitorInterface implementation
31 void OnSynStream(SpdyStreamId stream_id,
32 SpdyStreamId associated_stream_id,
33 SpdyPriority priority,
34 bool fin,
35 bool unidirectional) override {
36 CloseConnection("SPDY SYN_STREAM frame received.");
39 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
40 CloseConnection("SPDY SYN_REPLY frame received.");
43 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
44 const char* header_data,
45 size_t len) override {
46 if (!stream_->IsConnected()) {
47 return false;
49 stream_->OnControlFrameHeaderData(stream_id, header_data, len);
50 return true;
53 void OnStreamFrameData(SpdyStreamId stream_id,
54 const char* data,
55 size_t len,
56 bool fin) override {
57 if (fin && len == 0) {
58 // The framer invokes OnStreamFrameData with zero-length data and
59 // fin = true after processing a SYN_STREAM or SYN_REPLY frame
60 // that had the fin bit set.
61 return;
63 CloseConnection("SPDY DATA frame received.");
66 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
67 CloseConnection("SPDY frame padding received.");
70 void OnError(SpdyFramer* framer) override {
71 CloseConnection(base::StringPrintf(
72 "SPDY framing error: %s",
73 SpdyFramer::ErrorCodeToString(framer->error_code())));
76 void OnDataFrameHeader(SpdyStreamId stream_id,
77 size_t length,
78 bool fin) override {
79 CloseConnection("SPDY DATA frame received.");
82 void OnRstStream(SpdyStreamId stream_id,
83 SpdyRstStreamStatus status) override {
84 CloseConnection("SPDY RST_STREAM frame received.");
87 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
88 CloseConnection("SPDY SETTINGS frame received.");
91 void OnSettingsAck() override {
92 CloseConnection("SPDY SETTINGS frame received.");
95 void OnSettingsEnd() override {
96 CloseConnection("SPDY SETTINGS frame received.");
99 void OnPing(SpdyPingId unique_id, bool is_ack) override {
100 CloseConnection("SPDY PING frame received.");
103 void OnGoAway(SpdyStreamId last_accepted_stream_id,
104 SpdyGoAwayStatus status) override {
105 CloseConnection("SPDY GOAWAY frame received.");
108 void OnHeaders(SpdyStreamId stream_id,
109 bool has_priority,
110 SpdyPriority priority,
111 SpdyStreamId parent_stream_id,
112 bool exclusive,
113 bool fin,
114 bool end) override {
115 if (!stream_->IsConnected()) {
116 return;
118 if (has_priority) {
119 stream_->OnSynStream(stream_id, priority, fin);
120 } else {
121 stream_->OnSynReply(stream_id, fin);
125 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
126 CloseConnection("SPDY WINDOW_UPDATE frame received.");
129 void OnPushPromise(SpdyStreamId stream_id,
130 SpdyStreamId promised_stream_id,
131 bool end) override {
132 CloseConnection("SPDY PUSH_PROMISE frame received.");
135 void OnContinuation(SpdyStreamId stream_id, bool end) override {
138 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
139 CloseConnection("Unknown frame type received.");
140 return false;
143 // SpdyFramerDebugVisitorInterface implementation
144 void OnSendCompressedFrame(SpdyStreamId stream_id,
145 SpdyFrameType type,
146 size_t payload_len,
147 size_t frame_len) override {}
149 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
150 SpdyFrameType type,
151 size_t frame_len) override {
152 if (stream_->IsConnected()) {
153 stream_->OnCompressedFrameSize(frame_len);
157 private:
158 void CloseConnection(const string& details) {
159 if (stream_->IsConnected()) {
160 stream_->CloseConnectionWithDetails(
161 QUIC_INVALID_HEADERS_STREAM_DATA, details);
165 private:
166 QuicHeadersStream* stream_;
168 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
171 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session)
172 : ReliableQuicStream(kHeadersStreamId, session),
173 spdy_session_(session),
174 stream_id_(kInvalidStreamId),
175 fin_(false),
176 frame_len_(0),
177 spdy_framer_(HTTP2),
178 spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
179 spdy_framer_.set_visitor(spdy_framer_visitor_.get());
180 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
181 // The headers stream is exempt from connection level flow control.
182 DisableConnectionFlowControlForThisStream();
185 QuicHeadersStream::~QuicHeadersStream() {}
187 size_t QuicHeadersStream::WriteHeaders(
188 QuicStreamId stream_id,
189 const SpdyHeaderBlock& headers,
190 bool fin,
191 QuicPriority priority,
192 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
193 SpdyHeadersIR headers_frame(stream_id);
194 headers_frame.set_header_block(headers);
195 headers_frame.set_fin(fin);
196 if (session()->perspective() == Perspective::IS_CLIENT) {
197 headers_frame.set_has_priority(true);
198 headers_frame.set_priority(priority);
200 scoped_ptr<SpdySerializedFrame> frame(
201 spdy_framer_.SerializeFrame(headers_frame));
202 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
203 ack_notifier_delegate);
204 return frame->size();
207 void QuicHeadersStream::OnDataAvailable() {
208 char buffer[1024];
209 struct iovec iov;
210 while (true) {
211 iov.iov_base = buffer;
212 iov.iov_len = arraysize(buffer);
213 if (sequencer()->GetReadableRegions(&iov, 1) != 1) {
214 // No more data to read.
215 break;
217 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
218 iov.iov_len) != iov.iov_len) {
219 // Error processing data.
220 return;
222 sequencer()->MarkConsumed(iov.iov_len);
226 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
228 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
229 SpdyPriority priority,
230 bool fin) {
231 if (session()->perspective() == Perspective::IS_CLIENT) {
232 CloseConnectionWithDetails(
233 QUIC_INVALID_HEADERS_STREAM_DATA,
234 "SPDY SYN_STREAM frame received at the client");
235 return;
237 DCHECK_EQ(kInvalidStreamId, stream_id_);
238 stream_id_ = stream_id;
239 fin_ = fin;
240 spdy_session_->OnStreamHeadersPriority(stream_id, priority);
243 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
244 if (session()->perspective() == Perspective::IS_SERVER) {
245 CloseConnectionWithDetails(
246 QUIC_INVALID_HEADERS_STREAM_DATA,
247 "SPDY SYN_REPLY frame received at the server");
248 return;
250 DCHECK_EQ(kInvalidStreamId, stream_id_);
251 stream_id_ = stream_id;
252 fin_ = fin;
255 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
256 const char* header_data,
257 size_t len) {
258 DCHECK_EQ(stream_id_, stream_id);
259 if (len == 0) {
260 DCHECK_NE(0u, stream_id_);
261 DCHECK_NE(0u, frame_len_);
262 spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
263 // Reset state for the next frame.
264 stream_id_ = kInvalidStreamId;
265 fin_ = false;
266 frame_len_ = 0;
267 } else {
268 spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
272 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
273 frame_len_ += frame_len;
276 bool QuicHeadersStream::IsConnected() {
277 return session()->connection()->connected();
280 } // namespace net