Web MIDI: make platform dependent initialization asynchronous
[chromium-blink-merge.git] / net / quic / quic_headers_stream.cc
blobaab8571553d2bf4ea5525fb8465723de28907260
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"
9 using base::StringPiece;
11 namespace net {
13 namespace {
15 const QuicStreamId kInvalidStreamId = 0;
17 } // namespace
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) {}
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;
38 if (associated_stream_id != 0) {
39 CloseConnection("associated_stream_id != 0");
40 return;
43 if (unidirectional != 0) {
44 CloseConnection("unidirectional != 0");
45 return;
48 stream_->OnSynStream(stream_id, priority, fin);
51 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {
52 if (!stream_->IsConnected()) {
53 return;
56 stream_->OnSynReply(stream_id, fin);
59 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
60 const char* header_data,
61 size_t len) OVERRIDE {
62 if (!stream_->IsConnected()) {
63 return false;
65 stream_->OnControlFrameHeaderData(stream_id, header_data, len);
66 return true;
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;
79 CloseConnection("SPDY DATA frame received.");
82 virtual void OnError(SpdyFramer* framer) OVERRIDE {
83 CloseConnection("SPDY framing error.");
86 virtual void OnDataFrameHeader(SpdyStreamId stream_id,
87 size_t length,
88 bool fin) OVERRIDE {
89 CloseConnection("SPDY DATA frame received.");
92 virtual void OnRstStream(SpdyStreamId stream_id,
93 SpdyRstStreamStatus status) OVERRIDE {
94 CloseConnection("SPDY RST_STREAM frame received.");
97 virtual void OnSetting(SpdySettingsIds id,
98 uint8 flags,
99 uint32 value) OVERRIDE {
100 CloseConnection("SPDY SETTINGS frame received.");
103 virtual void OnSettingsAck() OVERRIDE {
104 CloseConnection("SPDY SETTINGS frame received.");
107 virtual void OnSettingsEnd() OVERRIDE {
108 CloseConnection("SPDY SETTINGS frame received.");
111 virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
112 CloseConnection("SPDY PING frame received.");
115 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
116 SpdyGoAwayStatus status) OVERRIDE {
117 CloseConnection("SPDY GOAWAY frame received.");
120 virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE {
121 CloseConnection("SPDY HEADERS frame received.");
124 virtual void OnWindowUpdate(SpdyStreamId stream_id,
125 uint32 delta_window_size) OVERRIDE {
126 CloseConnection("SPDY WINDOW_UPDATE frame received.");
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.");
136 virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
137 CloseConnection("SPDY CONTINUATION frame received.");
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());
177 DisableFlowControl();
180 QuicHeadersStream::~QuicHeadersStream() {}
182 size_t QuicHeadersStream::WriteHeaders(
183 QuicStreamId stream_id,
184 const SpdyHeaderBlock& headers,
185 bool fin,
186 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
187 scoped_ptr<SpdySerializedFrame> frame;
188 if (session()->is_server()) {
189 SpdySynReplyIR syn_reply(stream_id);
190 syn_reply.set_name_value_block(headers);
191 syn_reply.set_fin(fin);
192 frame.reset(spdy_framer_.SerializeFrame(syn_reply));
193 } else {
194 SpdySynStreamIR syn_stream(stream_id);
195 syn_stream.set_name_value_block(headers);
196 syn_stream.set_fin(fin);
197 frame.reset(spdy_framer_.SerializeFrame(syn_stream));
199 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
200 ack_notifier_delegate);
201 return frame->size();
204 uint32 QuicHeadersStream::ProcessRawData(const char* data,
205 uint32 data_len) {
206 return spdy_framer_.ProcessInput(data, data_len);
209 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
211 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
212 SpdyPriority priority,
213 bool fin) {
214 if (!session()->is_server()) {
215 CloseConnectionWithDetails(
216 QUIC_INVALID_HEADERS_STREAM_DATA,
217 "SPDY SYN_STREAM frame received at the client");
218 return;
220 DCHECK_EQ(kInvalidStreamId, stream_id_);
221 stream_id_ = stream_id;
222 fin_ = fin;
223 session()->OnStreamHeadersPriority(stream_id, priority);
226 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
227 if (session()->is_server()) {
228 CloseConnectionWithDetails(
229 QUIC_INVALID_HEADERS_STREAM_DATA,
230 "SPDY SYN_REPLY frame received at the server");
231 return;
233 DCHECK_EQ(kInvalidStreamId, stream_id_);
234 stream_id_ = stream_id;
235 fin_ = fin;
238 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
239 const char* header_data,
240 size_t len) {
241 DCHECK_EQ(stream_id_, stream_id);
242 if (len == 0) {
243 DCHECK_NE(0u, stream_id_);
244 DCHECK_NE(0u, frame_len_);
245 session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
246 // Reset state for the next frame.
247 stream_id_ = kInvalidStreamId;
248 fin_ = false;
249 frame_len_ = 0;
250 } else {
251 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
255 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
256 DCHECK_EQ(kInvalidStreamId, stream_id_);
257 DCHECK_EQ(0u, frame_len_);
258 frame_len_ = frame_len;
261 bool QuicHeadersStream::IsConnected() {
262 return session()->connection()->connected();
265 } // namespace net