file_manager: Fix a bug where hosted documents could not be opened without active...
[chromium-blink-merge.git] / net / spdy / buffered_spdy_framer.cc
blob46d028404febd201e41143e26daea1ba90042b9e
1 // Copyright (c) 2012 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/spdy/buffered_spdy_framer.h"
7 #include "base/logging.h"
9 namespace net {
11 SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
12 switch (next_proto) {
13 case kProtoSPDY2:
14 case kProtoSPDY21:
15 return SPDY2;
16 case kProtoSPDY3:
17 case kProtoSPDY31:
18 return SPDY3;
19 // SPDY/4 and HTTP/2 share the same framing for now.
20 case kProtoSPDY4a2:
21 case kProtoHTTP2Draft04:
22 return SPDY4;
23 case kProtoUnknown:
24 case kProtoHTTP11:
25 case kProtoSPDY1:
26 case kProtoQUIC1SPDY3:
27 break;
29 NOTREACHED();
30 return SPDY2;
33 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
34 bool enable_compression)
35 : spdy_framer_(version),
36 visitor_(NULL),
37 header_buffer_used_(0),
38 header_buffer_valid_(false),
39 header_stream_id_(SpdyFramer::kInvalidStream),
40 frames_received_(0) {
41 spdy_framer_.set_enable_compression(enable_compression);
42 memset(header_buffer_, 0, sizeof(header_buffer_));
45 BufferedSpdyFramer::~BufferedSpdyFramer() {
48 void BufferedSpdyFramer::set_visitor(
49 BufferedSpdyFramerVisitorInterface* visitor) {
50 visitor_ = visitor;
51 spdy_framer_.set_visitor(this);
54 void BufferedSpdyFramer::set_debug_visitor(
55 SpdyFramerDebugVisitorInterface* debug_visitor) {
56 spdy_framer_.set_debug_visitor(debug_visitor);
59 void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) {
60 DCHECK(spdy_framer);
61 visitor_->OnError(spdy_framer->error_code());
64 void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id,
65 SpdyStreamId associated_stream_id,
66 SpdyPriority priority,
67 uint8 credential_slot,
68 bool fin,
69 bool unidirectional) {
70 frames_received_++;
71 DCHECK(!control_frame_fields_.get());
72 control_frame_fields_.reset(new ControlFrameFields());
73 control_frame_fields_->type = SYN_STREAM;
74 control_frame_fields_->stream_id = stream_id;
75 control_frame_fields_->associated_stream_id = associated_stream_id;
76 control_frame_fields_->priority = priority;
77 control_frame_fields_->credential_slot = credential_slot;
78 control_frame_fields_->fin = fin;
79 control_frame_fields_->unidirectional = unidirectional;
81 InitHeaderStreaming(stream_id);
84 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
85 bool fin) {
86 frames_received_++;
87 DCHECK(!control_frame_fields_.get());
88 control_frame_fields_.reset(new ControlFrameFields());
89 control_frame_fields_->type = HEADERS;
90 control_frame_fields_->stream_id = stream_id;
91 control_frame_fields_->fin = fin;
93 InitHeaderStreaming(stream_id);
96 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id,
97 bool fin) {
98 frames_received_++;
99 DCHECK(!control_frame_fields_.get());
100 control_frame_fields_.reset(new ControlFrameFields());
101 control_frame_fields_->type = SYN_REPLY;
102 control_frame_fields_->stream_id = stream_id;
103 control_frame_fields_->fin = fin;
105 InitHeaderStreaming(stream_id);
108 bool BufferedSpdyFramer::OnCredentialFrameData(const char* frame_data,
109 size_t len) {
110 DCHECK(false);
111 return false;
114 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id,
115 const char* header_data,
116 size_t len) {
117 CHECK_EQ(header_stream_id_, stream_id);
119 if (len == 0) {
120 // Indicates end-of-header-block.
121 CHECK(header_buffer_valid_);
123 SpdyHeaderBlock headers;
124 size_t parsed_len = spdy_framer_.ParseHeaderBlockInBuffer(
125 header_buffer_, header_buffer_used_, &headers);
126 // TODO(rch): this really should be checking parsed_len != len,
127 // but a bunch of tests fail. Need to figure out why.
128 if (parsed_len == 0) {
129 visitor_->OnStreamError(
130 stream_id, "Could not parse Spdy Control Frame Header.");
131 return false;
133 DCHECK(control_frame_fields_.get());
134 switch (control_frame_fields_->type) {
135 case SYN_STREAM:
136 visitor_->OnSynStream(control_frame_fields_->stream_id,
137 control_frame_fields_->associated_stream_id,
138 control_frame_fields_->priority,
139 control_frame_fields_->credential_slot,
140 control_frame_fields_->fin,
141 control_frame_fields_->unidirectional,
142 headers);
143 break;
144 case SYN_REPLY:
145 visitor_->OnSynReply(control_frame_fields_->stream_id,
146 control_frame_fields_->fin,
147 headers);
148 break;
149 case HEADERS:
150 visitor_->OnHeaders(control_frame_fields_->stream_id,
151 control_frame_fields_->fin,
152 headers);
153 break;
154 default:
155 DCHECK(false) << "Unexpect control frame type: "
156 << control_frame_fields_->type;
157 break;
159 control_frame_fields_.reset(NULL);
160 return true;
163 const size_t available = kHeaderBufferSize - header_buffer_used_;
164 if (len > available) {
165 header_buffer_valid_ = false;
166 visitor_->OnStreamError(
167 stream_id, "Received more data than the allocated size.");
168 return false;
170 memcpy(header_buffer_ + header_buffer_used_, header_data, len);
171 header_buffer_used_ += len;
172 return true;
175 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
176 size_t length,
177 bool fin) {
178 frames_received_++;
179 header_stream_id_ = stream_id;
182 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
183 const char* data,
184 size_t len,
185 bool fin) {
186 visitor_->OnStreamFrameData(stream_id, data, len, fin);
189 void BufferedSpdyFramer::OnSettings(bool clear_persisted) {
190 visitor_->OnSettings(clear_persisted);
193 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id,
194 uint8 flags,
195 uint32 value) {
196 visitor_->OnSetting(id, flags, value);
199 void BufferedSpdyFramer::OnPing(uint32 unique_id) {
200 visitor_->OnPing(unique_id);
203 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id,
204 SpdyRstStreamStatus status) {
205 visitor_->OnRstStream(stream_id, status);
207 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id,
208 SpdyGoAwayStatus status) {
209 visitor_->OnGoAway(last_accepted_stream_id, status);
212 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id,
213 uint32 delta_window_size) {
214 visitor_->OnWindowUpdate(stream_id, delta_window_size);
217 void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id,
218 SpdyStreamId promised_stream_id) {
219 visitor_->OnPushPromise(stream_id, promised_stream_id);
222 int BufferedSpdyFramer::protocol_version() {
223 return spdy_framer_.protocol_version();
226 size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) {
227 return spdy_framer_.ProcessInput(data, len);
230 void BufferedSpdyFramer::Reset() {
231 spdy_framer_.Reset();
234 SpdyFramer::SpdyError BufferedSpdyFramer::error_code() const {
235 return spdy_framer_.error_code();
238 SpdyFramer::SpdyState BufferedSpdyFramer::state() const {
239 return spdy_framer_.state();
242 bool BufferedSpdyFramer::MessageFullyRead() {
243 return state() == SpdyFramer::SPDY_AUTO_RESET;
246 bool BufferedSpdyFramer::HasError() {
247 return spdy_framer_.HasError();
250 SpdyFrame* BufferedSpdyFramer::CreateSynStream(
251 SpdyStreamId stream_id,
252 SpdyStreamId associated_stream_id,
253 SpdyPriority priority,
254 uint8 credential_slot,
255 SpdyControlFlags flags,
256 bool compressed,
257 const SpdyHeaderBlock* headers) {
258 return spdy_framer_.CreateSynStream(stream_id, associated_stream_id, priority,
259 credential_slot, flags, compressed,
260 headers);
263 SpdyFrame* BufferedSpdyFramer::CreateSynReply(
264 SpdyStreamId stream_id,
265 SpdyControlFlags flags,
266 bool compressed,
267 const SpdyHeaderBlock* headers) {
268 return spdy_framer_.CreateSynReply(stream_id, flags, compressed, headers);
271 SpdyFrame* BufferedSpdyFramer::CreateRstStream(
272 SpdyStreamId stream_id,
273 SpdyRstStreamStatus status) const {
274 return spdy_framer_.CreateRstStream(stream_id, status);
277 SpdyFrame* BufferedSpdyFramer::CreateSettings(
278 const SettingsMap& values) const {
279 return spdy_framer_.CreateSettings(values);
282 SpdyFrame* BufferedSpdyFramer::CreatePingFrame(
283 uint32 unique_id) const {
284 return spdy_framer_.CreatePingFrame(unique_id);
287 SpdyFrame* BufferedSpdyFramer::CreateGoAway(
288 SpdyStreamId last_accepted_stream_id,
289 SpdyGoAwayStatus status) const {
290 return spdy_framer_.CreateGoAway(last_accepted_stream_id, status);
293 SpdyFrame* BufferedSpdyFramer::CreateHeaders(
294 SpdyStreamId stream_id,
295 SpdyControlFlags flags,
296 bool compressed,
297 const SpdyHeaderBlock* headers) {
298 return spdy_framer_.CreateHeaders(stream_id, flags, compressed, headers);
301 SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
302 SpdyStreamId stream_id,
303 uint32 delta_window_size) const {
304 return spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size);
307 SpdyFrame* BufferedSpdyFramer::CreateCredentialFrame(
308 const SpdyCredential& credential) const {
309 return spdy_framer_.CreateCredentialFrame(credential);
312 SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
313 const char* data,
314 uint32 len,
315 SpdyDataFlags flags) {
316 return spdy_framer_.CreateDataFrame(stream_id, data, len, flags);
319 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
320 return spdy_framer_.GetHighestPriority();
323 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) {
324 memset(header_buffer_, 0, kHeaderBufferSize);
325 header_buffer_used_ = 0;
326 header_buffer_valid_ = true;
327 header_stream_id_ = stream_id;
328 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
331 } // namespace net