[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / net / quic / quic_headers_stream.cc
blob48fb3a01c098d3f2a475a6bed39720e323c60adc
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_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 SpdyFramerVisitor(SpdyMajorVersion spdy_version, QuicHeadersStream* stream)
29 : spdy_version_(spdy_version), stream_(stream) {}
31 // SpdyFramerVisitorInterface implementation
32 void OnSynStream(SpdyStreamId stream_id,
33 SpdyStreamId associated_stream_id,
34 SpdyPriority priority,
35 bool fin,
36 bool unidirectional) override {
37 if (spdy_version_ != SPDY3) {
38 CloseConnection("SPDY SYN_STREAM frame received.");
39 return;
42 if (!stream_->IsConnected()) {
43 return;
46 if (associated_stream_id != 0) {
47 CloseConnection("associated_stream_id != 0");
48 return;
51 if (unidirectional != 0) {
52 CloseConnection("unidirectional != 0");
53 return;
56 stream_->OnSynStream(stream_id, priority, fin);
59 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
60 if (spdy_version_ != SPDY3) {
61 CloseConnection("SPDY SYN_REPLY frame received.");
62 return;
65 if (!stream_->IsConnected()) {
66 return;
69 stream_->OnSynReply(stream_id, fin);
72 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
73 const char* header_data,
74 size_t len) override {
75 if (!stream_->IsConnected()) {
76 return false;
78 stream_->OnControlFrameHeaderData(stream_id, header_data, len);
79 return true;
82 void OnStreamFrameData(SpdyStreamId stream_id,
83 const char* data,
84 size_t len,
85 bool fin) override {
86 if (fin && len == 0) {
87 // The framer invokes OnStreamFrameData with zero-length data and
88 // fin = true after processing a SYN_STREAM or SYN_REPLY frame
89 // that had the fin bit set.
90 return;
92 CloseConnection("SPDY DATA frame received.");
95 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
96 CloseConnection("SPDY frame padding received.");
99 void OnError(SpdyFramer* framer) override {
100 CloseConnection(base::StringPrintf(
101 "SPDY framing error: %s",
102 SpdyFramer::ErrorCodeToString(framer->error_code())));
105 void OnDataFrameHeader(SpdyStreamId stream_id,
106 size_t length,
107 bool fin) override {
108 CloseConnection("SPDY DATA frame received.");
111 void OnRstStream(SpdyStreamId stream_id,
112 SpdyRstStreamStatus status) override {
113 CloseConnection("SPDY RST_STREAM frame received.");
116 void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
117 CloseConnection("SPDY SETTINGS frame received.");
120 void OnSettingsAck() override {
121 CloseConnection("SPDY SETTINGS frame received.");
124 void OnSettingsEnd() override {
125 CloseConnection("SPDY SETTINGS frame received.");
128 void OnPing(SpdyPingId unique_id, bool is_ack) override {
129 CloseConnection("SPDY PING frame received.");
132 void OnGoAway(SpdyStreamId last_accepted_stream_id,
133 SpdyGoAwayStatus status) override {
134 CloseConnection("SPDY GOAWAY frame received.");
137 void OnHeaders(SpdyStreamId stream_id,
138 bool has_priority,
139 SpdyPriority priority,
140 bool fin,
141 bool end) override {
142 if (spdy_version_ == SPDY3) {
143 CloseConnection("SPDY HEADERS frame received.");
144 return;
146 if (!stream_->IsConnected()) {
147 return;
149 if (has_priority) {
150 stream_->OnSynStream(stream_id, priority, fin);
151 } else {
152 stream_->OnSynReply(stream_id, fin);
156 void OnWindowUpdate(SpdyStreamId stream_id,
157 uint32 delta_window_size) override {
158 CloseConnection("SPDY WINDOW_UPDATE frame received.");
161 void OnPushPromise(SpdyStreamId stream_id,
162 SpdyStreamId promised_stream_id,
163 bool end) override {
164 LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer";
165 CloseConnection("SPDY PUSH_PROMISE frame received.");
168 void OnContinuation(SpdyStreamId stream_id, bool end) override {
169 if (spdy_version_ == SPDY3) {
170 LOG(DFATAL) << "CONTINUATION frame received from a SPDY/3 framer";
171 CloseConnection("SPDY CONTINUATION frame received.");
175 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
176 CloseConnection("Unknown frame type received.");
177 return false;
180 // SpdyFramerDebugVisitorInterface implementation
181 void OnSendCompressedFrame(SpdyStreamId stream_id,
182 SpdyFrameType type,
183 size_t payload_len,
184 size_t frame_len) override {}
186 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
187 SpdyFrameType type,
188 size_t frame_len) override {
189 if (stream_->IsConnected()) {
190 stream_->OnCompressedFrameSize(frame_len);
194 private:
195 void CloseConnection(const string& details) {
196 if (stream_->IsConnected()) {
197 stream_->CloseConnectionWithDetails(
198 QUIC_INVALID_HEADERS_STREAM_DATA, details);
202 private:
203 SpdyMajorVersion spdy_version_;
204 QuicHeadersStream* stream_;
206 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
209 QuicHeadersStream::QuicHeadersStream(QuicSession* session)
210 : ReliableQuicStream(kHeadersStreamId, session),
211 stream_id_(kInvalidStreamId),
212 fin_(false),
213 frame_len_(0) {
214 InitializeFramer(session->connection()->version());
215 // The headers stream is exempt from connection level flow control.
216 DisableConnectionFlowControlForThisStream();
219 QuicHeadersStream::~QuicHeadersStream() {}
221 size_t QuicHeadersStream::WriteHeaders(
222 QuicStreamId stream_id,
223 const SpdyHeaderBlock& headers,
224 bool fin,
225 QuicPriority priority,
226 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
227 scoped_ptr<SpdySerializedFrame> frame;
228 if (spdy_framer_->protocol_version() == SPDY3) {
229 if (session()->perspective() == Perspective::IS_SERVER) {
230 SpdySynReplyIR syn_reply(stream_id);
231 syn_reply.set_name_value_block(headers);
232 syn_reply.set_fin(fin);
233 frame.reset(spdy_framer_->SerializeFrame(syn_reply));
234 } else {
235 SpdySynStreamIR syn_stream(stream_id);
236 syn_stream.set_name_value_block(headers);
237 syn_stream.set_fin(fin);
238 syn_stream.set_priority(priority);
239 frame.reset(spdy_framer_->SerializeFrame(syn_stream));
241 } else {
242 SpdyHeadersIR headers_frame(stream_id);
243 headers_frame.set_name_value_block(headers);
244 headers_frame.set_fin(fin);
245 if (session()->perspective() == Perspective::IS_CLIENT) {
246 headers_frame.set_has_priority(true);
247 headers_frame.set_priority(priority);
249 frame.reset(spdy_framer_->SerializeFrame(headers_frame));
251 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
252 ack_notifier_delegate);
253 return frame->size();
256 uint32 QuicHeadersStream::ProcessRawData(const char* data,
257 uint32 data_len) {
258 return spdy_framer_->ProcessInput(data, data_len);
261 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
263 void QuicHeadersStream::OnSuccessfulVersionNegotiation(QuicVersion version) {
264 InitializeFramer(version);
267 void QuicHeadersStream::InitializeFramer(QuicVersion version) {
268 SpdyMajorVersion spdy_version = version > QUIC_VERSION_23 ? SPDY4 : SPDY3;
269 if (spdy_framer_.get() != nullptr &&
270 spdy_framer_->protocol_version() == spdy_version) {
271 return;
273 spdy_framer_.reset(new SpdyFramer(spdy_version));
274 spdy_framer_visitor_.reset(new SpdyFramerVisitor(spdy_version, this));
275 spdy_framer_->set_visitor(spdy_framer_visitor_.get());
276 spdy_framer_->set_debug_visitor(spdy_framer_visitor_.get());
279 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
280 SpdyPriority priority,
281 bool fin) {
282 if (session()->perspective() == Perspective::IS_CLIENT) {
283 CloseConnectionWithDetails(
284 QUIC_INVALID_HEADERS_STREAM_DATA,
285 "SPDY SYN_STREAM frame received at the client");
286 return;
288 DCHECK_EQ(kInvalidStreamId, stream_id_);
289 stream_id_ = stream_id;
290 fin_ = fin;
291 session()->OnStreamHeadersPriority(stream_id, priority);
294 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
295 if (session()->perspective() == Perspective::IS_SERVER) {
296 CloseConnectionWithDetails(
297 QUIC_INVALID_HEADERS_STREAM_DATA,
298 "SPDY SYN_REPLY frame received at the server");
299 return;
301 DCHECK_EQ(kInvalidStreamId, stream_id_);
302 stream_id_ = stream_id;
303 fin_ = fin;
306 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
307 const char* header_data,
308 size_t len) {
309 DCHECK_EQ(stream_id_, stream_id);
310 if (len == 0) {
311 DCHECK_NE(0u, stream_id_);
312 DCHECK_NE(0u, frame_len_);
313 session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
314 // Reset state for the next frame.
315 stream_id_ = kInvalidStreamId;
316 fin_ = false;
317 frame_len_ = 0;
318 } else {
319 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
323 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
324 if (spdy_framer_->protocol_version() == SPDY3) {
325 // SPDY/3 headers always fit into a single frame, so the previous headers
326 // should be completely processed when a new frame is received.
327 DCHECK_EQ(kInvalidStreamId, stream_id_);
328 DCHECK_EQ(0u, frame_len_);
330 frame_len_ += frame_len;
333 bool QuicHeadersStream::IsConnected() {
334 return session()->connection()->connected();
337 } // namespace net