Land Recent QUIC Changes.
[chromium-blink-merge.git] / net / quic / quic_headers_stream.cc
blobc3e07332ea434afe36c695035299f21e70643f36
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 "net/quic/quic_session.h"
8 #include "net/quic/quic_spdy_decompressor.h"
10 using base::StringPiece;
12 namespace net {
14 namespace {
16 const QuicStreamId kInvalidStreamId = 0;
18 } // namespace
20 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
21 // the QuicDataStream, and closes the connection if any unexpected frames
22 // are received.
23 class QuicHeadersStream::SpdyFramerVisitor
24 : public SpdyFramerVisitorInterface,
25 public SpdyFramerDebugVisitorInterface {
26 public:
27 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
29 // SpdyFramerVisitorInterface implementation
30 virtual void OnSynStream(SpdyStreamId stream_id,
31 SpdyStreamId associated_stream_id,
32 SpdyPriority priority,
33 uint8 credential_slot,
34 bool fin,
35 bool unidirectional) OVERRIDE {
36 if (!stream_->IsConnected()) {
37 return;
40 if (associated_stream_id != 0) {
41 CloseConnection("associated_stream_id != 0");
42 return;
45 if (credential_slot != 0) {
46 CloseConnection("credential_slot != 0");
47 return;
50 if (unidirectional != 0) {
51 CloseConnection("unidirectional != 0");
52 return;
55 stream_->OnSynStream(stream_id, priority, fin);
58 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
59 if (!stream_->IsConnected()) {
60 return;
63 stream_->OnSynReply(stream_id, fin);
66 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
67 const char* header_data,
68 size_t len) OVERRIDE {
69 if (!stream_->IsConnected()) {
70 return false;
72 stream_->OnControlFrameHeaderData(stream_id, header_data, len);
73 return true;
76 virtual void OnStreamFrameData(SpdyStreamId stream_id,
77 const char* data,
78 size_t len,
79 bool fin) OVERRIDE {
80 if (fin && len == 0) {
81 // The framer invokes OnStreamFrameData with zero-length data and
82 // fin = true after processing a SYN_STREAM or SYN_REPLY frame
83 // that had the fin bit set.
84 return;
86 CloseConnection("SPDY DATA frame recevied.");
89 virtual void OnError(SpdyFramer* framer) OVERRIDE {
90 CloseConnection("SPDY framing error.");
93 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
94 size_t length,
95 bool fin) OVERRIDE {
96 CloseConnection("SPDY DATA frame recevied.");
99 virtual void OnRstStream(SpdyStreamId stream_id,
100 SpdyRstStreamStatus status) OVERRIDE {
101 CloseConnection("SPDY RST_STREAM frame recevied.");
104 virtual void OnSetting(SpdySettingsIds id,
105 uint8 flags,
106 uint32 value) OVERRIDE {
107 CloseConnection("SPDY SETTINGS frame recevied.");
110 virtual void OnPing(uint32 unique_id) OVERRIDE {
111 CloseConnection("SPDY PING frame recevied.");
114 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
115 SpdyGoAwayStatus status) OVERRIDE {
116 CloseConnection("SPDY GOAWAY frame recevied.");
119 virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE {
120 CloseConnection("SPDY HEADERS frame recevied.");
123 virtual void OnWindowUpdate(SpdyStreamId stream_id,
124 uint32 delta_window_size) OVERRIDE {
125 CloseConnection("SPDY WINDOW_UPDATE frame recevied.");
128 virtual bool OnCredentialFrameData(const char* credential_data,
129 size_t len) OVERRIDE {
130 CloseConnection("SPDY CREDENTIAL frame recevied.");
131 return false;
134 virtual void OnPushPromise(SpdyStreamId stream_id,
135 SpdyStreamId promised_stream_id) OVERRIDE {
136 LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer";
137 CloseConnection("SPDY PUSH_PROMISE frame recevied.");
140 // SpdyFramerDebugVisitorInterface implementation
141 virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
142 SpdyFrameType type,
143 size_t payload_len,
144 size_t frame_len) OVERRIDE {}
146 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
147 SpdyFrameType type,
148 size_t frame_len) OVERRIDE {
149 if (stream_->IsConnected()) {
150 stream_->OnCompressedFrameSize(frame_len);
154 private:
155 void CloseConnection(const string& details) {
156 if (stream_->IsConnected()) {
157 stream_->CloseConnectionWithDetails(
158 QUIC_INVALID_HEADERS_STREAM_DATA, details);
162 private:
163 QuicHeadersStream* stream_;
165 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
168 QuicHeadersStream::QuicHeadersStream(QuicSession* session)
169 : ReliableQuicStream(kHeadersStreamId, session),
170 stream_id_(kInvalidStreamId),
171 fin_(false),
172 frame_len_(0),
173 spdy_framer_(SPDY3),
174 spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
175 spdy_framer_.set_visitor(spdy_framer_visitor_.get());
176 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
179 QuicHeadersStream::~QuicHeadersStream() {}
181 size_t QuicHeadersStream::WriteHeaders(QuicStreamId stream_id,
182 const SpdyHeaderBlock& headers,
183 bool fin) {
184 scoped_ptr<SpdySerializedFrame> frame;
185 if (session()->is_server()) {
186 SpdySynReplyIR syn_reply(stream_id);
187 *syn_reply.GetMutableNameValueBlock() = headers;
188 syn_reply.set_fin(fin);
189 frame.reset(spdy_framer_.SerializeFrame(syn_reply));
190 } else {
191 SpdySynStreamIR syn_stream(stream_id);
192 *syn_stream.GetMutableNameValueBlock() = headers;
193 syn_stream.set_fin(fin);
194 frame.reset(spdy_framer_.SerializeFrame(syn_stream));
196 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false);
197 return frame->size();
200 uint32 QuicHeadersStream::ProcessRawData(const char* data,
201 uint32 data_len) {
202 return spdy_framer_.ProcessInput(data, data_len);
205 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
207 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
208 SpdyPriority priority,
209 bool fin) {
210 if (!session()->is_server()) {
211 CloseConnectionWithDetails(
212 QUIC_INVALID_HEADERS_STREAM_DATA,
213 "SPDY SYN_STREAM frame recevied at the client");
214 return;
216 DCHECK_EQ(kInvalidStreamId, stream_id_);
217 stream_id_ = stream_id;
218 fin_ = fin;
219 session()->OnStreamHeadersPriority(stream_id, priority);
222 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
223 if (session()->is_server()) {
224 CloseConnectionWithDetails(
225 QUIC_INVALID_HEADERS_STREAM_DATA,
226 "SPDY SYN_REPLY frame recevied at the server");
227 return;
229 DCHECK_EQ(kInvalidStreamId, stream_id_);
230 stream_id_ = stream_id;
231 fin_ = fin;
234 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
235 const char* header_data,
236 size_t len) {
237 DCHECK_EQ(stream_id_, stream_id);
238 if (len == 0) {
239 DCHECK_NE(0u, stream_id_);
240 DCHECK_NE(0u, frame_len_);
241 session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
242 // Reset state for the next frame.
243 stream_id_ = kInvalidStreamId;
244 fin_ = false;
245 frame_len_ = 0;
246 } else {
247 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
251 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
252 DCHECK_EQ(kInvalidStreamId, stream_id_);
253 DCHECK_EQ(0u, frame_len_);
254 frame_len_ = frame_len;
257 bool QuicHeadersStream::IsConnected() {
258 return session()->connection()->connected();
261 } // namespace net