Fix mouse warp with 2x displays
[chromium-blink-merge.git] / net / spdy / buffered_spdy_framer.cc
blob239e49fff5ccc370fe326c6ec354e7caf8f2ff3e
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 kProtoDeprecatedSPDY2:
14 return SPDY2;
15 case kProtoSPDY3:
16 case kProtoSPDY31:
17 return SPDY3;
18 case kProtoHTTP2_14:
19 case kProtoHTTP2:
20 return HTTP2;
21 case kProtoUnknown:
22 case kProtoHTTP11:
23 case kProtoQUIC1SPDY3:
24 break;
26 NOTREACHED();
27 return SPDY2;
30 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
31 bool enable_compression)
32 : spdy_framer_(version),
33 visitor_(NULL),
34 header_buffer_used_(0),
35 header_buffer_valid_(false),
36 header_stream_id_(SpdyFramer::kInvalidStream),
37 frames_received_(0) {
38 spdy_framer_.set_enable_compression(enable_compression);
39 memset(header_buffer_, 0, sizeof(header_buffer_));
42 BufferedSpdyFramer::~BufferedSpdyFramer() {
45 void BufferedSpdyFramer::set_visitor(
46 BufferedSpdyFramerVisitorInterface* visitor) {
47 visitor_ = visitor;
48 spdy_framer_.set_visitor(this);
51 void BufferedSpdyFramer::set_debug_visitor(
52 SpdyFramerDebugVisitorInterface* debug_visitor) {
53 spdy_framer_.set_debug_visitor(debug_visitor);
56 void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) {
57 DCHECK(spdy_framer);
58 visitor_->OnError(spdy_framer->error_code());
61 void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id,
62 SpdyStreamId associated_stream_id,
63 SpdyPriority priority,
64 bool fin,
65 bool unidirectional) {
66 frames_received_++;
67 DCHECK(!control_frame_fields_.get());
68 control_frame_fields_.reset(new ControlFrameFields());
69 control_frame_fields_->type = SYN_STREAM;
70 control_frame_fields_->stream_id = stream_id;
71 control_frame_fields_->associated_stream_id = associated_stream_id;
72 control_frame_fields_->priority = priority;
73 control_frame_fields_->fin = fin;
74 control_frame_fields_->unidirectional = unidirectional;
76 InitHeaderStreaming(stream_id);
79 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
80 bool has_priority,
81 SpdyPriority priority,
82 SpdyStreamId parent_stream_id,
83 bool exclusive,
84 bool fin,
85 bool end) {
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_->has_priority = has_priority;
92 if (control_frame_fields_->has_priority) {
93 control_frame_fields_->priority = priority;
94 control_frame_fields_->parent_stream_id = parent_stream_id;
95 control_frame_fields_->exclusive = exclusive;
97 control_frame_fields_->fin = fin;
99 InitHeaderStreaming(stream_id);
102 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id,
103 bool fin) {
104 frames_received_++;
105 DCHECK(!control_frame_fields_.get());
106 control_frame_fields_.reset(new ControlFrameFields());
107 control_frame_fields_->type = SYN_REPLY;
108 control_frame_fields_->stream_id = stream_id;
109 control_frame_fields_->fin = fin;
111 InitHeaderStreaming(stream_id);
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_->fin,
140 control_frame_fields_->unidirectional,
141 headers);
142 break;
143 case SYN_REPLY:
144 visitor_->OnSynReply(control_frame_fields_->stream_id,
145 control_frame_fields_->fin,
146 headers);
147 break;
148 case HEADERS:
149 visitor_->OnHeaders(control_frame_fields_->stream_id,
150 control_frame_fields_->has_priority,
151 control_frame_fields_->priority,
152 control_frame_fields_->parent_stream_id,
153 control_frame_fields_->exclusive,
154 control_frame_fields_->fin, headers);
155 break;
156 case PUSH_PROMISE:
157 DCHECK_LT(SPDY3, protocol_version());
158 visitor_->OnPushPromise(control_frame_fields_->stream_id,
159 control_frame_fields_->promised_stream_id,
160 headers);
161 break;
162 default:
163 DCHECK(false) << "Unexpect control frame type: "
164 << control_frame_fields_->type;
165 break;
167 control_frame_fields_.reset(NULL);
168 return true;
171 const size_t available = kHeaderBufferSize - header_buffer_used_;
172 if (len > available) {
173 header_buffer_valid_ = false;
174 visitor_->OnStreamError(
175 stream_id, "Received more data than the allocated size.");
176 return false;
178 memcpy(header_buffer_ + header_buffer_used_, header_data, len);
179 header_buffer_used_ += len;
180 return true;
183 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
184 size_t length,
185 bool fin) {
186 frames_received_++;
187 header_stream_id_ = stream_id;
188 visitor_->OnDataFrameHeader(stream_id, length, fin);
191 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
192 const char* data,
193 size_t len,
194 bool fin) {
195 visitor_->OnStreamFrameData(stream_id, data, len, fin);
198 void BufferedSpdyFramer::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
199 visitor_->OnStreamPadding(stream_id, len);
202 void BufferedSpdyFramer::OnSettings(bool clear_persisted) {
203 visitor_->OnSettings(clear_persisted);
206 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id,
207 uint8 flags,
208 uint32 value) {
209 visitor_->OnSetting(id, flags, value);
212 void BufferedSpdyFramer::OnSettingsAck() {
213 visitor_->OnSettingsAck();
216 void BufferedSpdyFramer::OnSettingsEnd() {
217 visitor_->OnSettingsEnd();
220 void BufferedSpdyFramer::OnPing(SpdyPingId unique_id, bool is_ack) {
221 visitor_->OnPing(unique_id, is_ack);
224 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id,
225 SpdyRstStreamStatus status) {
226 visitor_->OnRstStream(stream_id, status);
228 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id,
229 SpdyGoAwayStatus status) {
230 visitor_->OnGoAway(last_accepted_stream_id, status);
233 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id,
234 int delta_window_size) {
235 visitor_->OnWindowUpdate(stream_id, delta_window_size);
238 void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id,
239 SpdyStreamId promised_stream_id,
240 bool end) {
241 DCHECK_LT(SPDY3, protocol_version());
242 frames_received_++;
243 DCHECK(!control_frame_fields_.get());
244 control_frame_fields_.reset(new ControlFrameFields());
245 control_frame_fields_->type = PUSH_PROMISE;
246 control_frame_fields_->stream_id = stream_id;
247 control_frame_fields_->promised_stream_id = promised_stream_id;
249 InitHeaderStreaming(stream_id);
252 void BufferedSpdyFramer::OnContinuation(SpdyStreamId stream_id, bool end) {
255 bool BufferedSpdyFramer::OnUnknownFrame(SpdyStreamId stream_id,
256 int frame_type) {
257 return visitor_->OnUnknownFrame(stream_id, frame_type);
260 SpdyMajorVersion BufferedSpdyFramer::protocol_version() {
261 return spdy_framer_.protocol_version();
264 size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) {
265 return spdy_framer_.ProcessInput(data, len);
268 void BufferedSpdyFramer::Reset() {
269 spdy_framer_.Reset();
272 SpdyFramer::SpdyError BufferedSpdyFramer::error_code() const {
273 return spdy_framer_.error_code();
276 SpdyFramer::SpdyState BufferedSpdyFramer::state() const {
277 return spdy_framer_.state();
280 bool BufferedSpdyFramer::MessageFullyRead() {
281 return state() == SpdyFramer::SPDY_FRAME_COMPLETE;
284 bool BufferedSpdyFramer::HasError() {
285 return spdy_framer_.HasError();
288 // TODO(jgraettinger): Eliminate uses of this method (prefer
289 // SpdySynStreamIR).
290 SpdyFrame* BufferedSpdyFramer::CreateSynStream(
291 SpdyStreamId stream_id,
292 SpdyStreamId associated_stream_id,
293 SpdyPriority priority,
294 SpdyControlFlags flags,
295 const SpdyHeaderBlock* headers) {
296 SpdySynStreamIR syn_stream(stream_id);
297 syn_stream.set_associated_to_stream_id(associated_stream_id);
298 syn_stream.set_priority(priority);
299 syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
300 syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
301 // TODO(hkhalil): Avoid copy here.
302 syn_stream.set_header_block(*headers);
303 return spdy_framer_.SerializeSynStream(syn_stream);
306 // TODO(jgraettinger): Eliminate uses of this method (prefer
307 // SpdySynReplyIR).
308 SpdyFrame* BufferedSpdyFramer::CreateSynReply(
309 SpdyStreamId stream_id,
310 SpdyControlFlags flags,
311 const SpdyHeaderBlock* headers) {
312 SpdySynReplyIR syn_reply(stream_id);
313 syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
314 // TODO(hkhalil): Avoid copy here.
315 syn_reply.set_header_block(*headers);
316 return spdy_framer_.SerializeSynReply(syn_reply);
319 // TODO(jgraettinger): Eliminate uses of this method (prefer
320 // SpdyRstStreamIR).
321 SpdyFrame* BufferedSpdyFramer::CreateRstStream(
322 SpdyStreamId stream_id,
323 SpdyRstStreamStatus status) const {
324 // RST_STREAM payloads are not part of any SPDY spec.
325 // SpdyFramer will accept them, but don't create them.
326 SpdyRstStreamIR rst_ir(stream_id, status, "");
327 return spdy_framer_.SerializeRstStream(rst_ir);
330 // TODO(jgraettinger): Eliminate uses of this method (prefer
331 // SpdySettingsIR).
332 SpdyFrame* BufferedSpdyFramer::CreateSettings(
333 const SettingsMap& values) const {
334 SpdySettingsIR settings_ir;
335 for (SettingsMap::const_iterator it = values.begin();
336 it != values.end();
337 ++it) {
338 settings_ir.AddSetting(
339 it->first,
340 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
341 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
342 it->second.second);
344 return spdy_framer_.SerializeSettings(settings_ir);
347 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPingIR).
348 SpdyFrame* BufferedSpdyFramer::CreatePingFrame(SpdyPingId unique_id,
349 bool is_ack) const {
350 SpdyPingIR ping_ir(unique_id);
351 ping_ir.set_is_ack(is_ack);
352 return spdy_framer_.SerializePing(ping_ir);
355 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyGoAwayIR).
356 SpdyFrame* BufferedSpdyFramer::CreateGoAway(
357 SpdyStreamId last_accepted_stream_id,
358 SpdyGoAwayStatus status) const {
359 SpdyGoAwayIR go_ir(last_accepted_stream_id, status, "");
360 return spdy_framer_.SerializeGoAway(go_ir);
363 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyHeadersIR).
364 SpdyFrame* BufferedSpdyFramer::CreateHeaders(
365 SpdyStreamId stream_id,
366 SpdyControlFlags flags,
367 SpdyPriority priority,
368 const SpdyHeaderBlock* headers) {
369 SpdyHeadersIR headers_ir(stream_id);
370 headers_ir.set_fin((flags & CONTROL_FLAG_FIN) != 0);
371 if (flags & HEADERS_FLAG_PRIORITY) {
372 headers_ir.set_has_priority(true);
373 headers_ir.set_priority(priority);
375 headers_ir.set_header_block(*headers);
376 return spdy_framer_.SerializeHeaders(headers_ir);
379 // TODO(jgraettinger): Eliminate uses of this method (prefer
380 // SpdyWindowUpdateIR).
381 SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
382 SpdyStreamId stream_id,
383 uint32 delta_window_size) const {
384 SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
385 return spdy_framer_.SerializeWindowUpdate(update_ir);
388 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyDataIR).
389 SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
390 const char* data,
391 uint32 len,
392 SpdyDataFlags flags) {
393 SpdyDataIR data_ir(stream_id,
394 base::StringPiece(data, len));
395 data_ir.set_fin((flags & DATA_FLAG_FIN) != 0);
396 return spdy_framer_.SerializeData(data_ir);
399 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPushPromiseIR).
400 SpdyFrame* BufferedSpdyFramer::CreatePushPromise(
401 SpdyStreamId stream_id,
402 SpdyStreamId promised_stream_id,
403 const SpdyHeaderBlock* headers) {
404 SpdyPushPromiseIR push_promise_ir(stream_id, promised_stream_id);
405 push_promise_ir.set_header_block(*headers);
406 return spdy_framer_.SerializePushPromise(push_promise_ir);
409 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
410 return spdy_framer_.GetHighestPriority();
413 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) {
414 memset(header_buffer_, 0, kHeaderBufferSize);
415 header_buffer_used_ = 0;
416 header_buffer_valid_ = true;
417 header_stream_id_ = stream_id;
418 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
421 } // namespace net