Web MIDI: enable receiving functionality in Linux and Chrome OS
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blob1764ecd8b4ec14a9219ec121524154a9694b3ead
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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't
6 // constantly adding and subtracting header sizes; this is ugly and error-
7 // prone.
9 #include "net/spdy/spdy_framer.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/stats_counters.h"
14 #include "base/third_party/valgrind/memcheck.h"
15 #include "net/spdy/spdy_frame_builder.h"
16 #include "net/spdy/spdy_frame_reader.h"
17 #include "net/spdy/spdy_bitmasks.h"
18 #include "third_party/zlib/zlib.h"
20 using std::vector;
22 namespace net {
24 namespace {
26 // Compute the id of our dictionary so that we know we're using the
27 // right one when asked for it.
28 uLong CalculateDictionaryId(const char* dictionary,
29 const size_t dictionary_size) {
30 uLong initial_value = adler32(0L, Z_NULL, 0);
31 return adler32(initial_value,
32 reinterpret_cast<const Bytef*>(dictionary),
33 dictionary_size);
36 struct DictionaryIds {
37 DictionaryIds()
38 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
39 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
41 const uLong v2_dictionary_id;
42 const uLong v3_dictionary_id;
45 // Adler ID for the SPDY header compressor dictionaries. Note that they are
46 // initialized lazily to avoid static initializers.
47 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
49 // Used to indicate no flags in a SPDY flags field.
50 const uint8 kNoFlags = 0;
52 } // namespace
54 const SpdyStreamId SpdyFramer::kInvalidStream = -1;
55 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
56 // The size of the control frame buffer. Must be >= the minimum size of the
57 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
58 // calculation details.
59 const size_t SpdyFramer::kControlFrameBufferSize = 18;
61 #ifdef DEBUG_SPDY_STATE_CHANGES
62 #define CHANGE_STATE(newstate) \
63 do { \
64 DVLOG(1) << "Changing state from: " \
65 << StateToString(state_) \
66 << " to " << StateToString(newstate) << "\n"; \
67 DCHECK(state_ != SPDY_ERROR); \
68 DCHECK_EQ(previous_state_, state_); \
69 previous_state_ = state_; \
70 state_ = newstate; \
71 } while (false)
72 #else
73 #define CHANGE_STATE(newstate) \
74 do { \
75 DCHECK(state_ != SPDY_ERROR); \
76 DCHECK_EQ(previous_state_, state_); \
77 previous_state_ = state_; \
78 state_ = newstate; \
79 } while (false)
80 #endif
82 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
83 uint32 wire) {
84 if (version < 3) {
85 ConvertFlagsAndIdForSpdy2(&wire);
87 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
90 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
91 : flags_(flags), id_(id & 0x00ffffff) {
92 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large.";
95 uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
96 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
97 if (version < 3) {
98 ConvertFlagsAndIdForSpdy2(&wire);
100 return wire;
103 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
104 // This method is used to preserve buggy behavior and works on both
105 // little-endian and big-endian hosts.
106 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
107 // as well as vice versa).
108 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
109 uint8* wire_array = reinterpret_cast<uint8*>(val);
110 std::swap(wire_array[0], wire_array[3]);
111 std::swap(wire_array[1], wire_array[2]);
114 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
115 size_t len) {
116 return true;
119 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
120 const char* rst_stream_data,
121 size_t len) {
122 return true;
125 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
126 : current_frame_buffer_(new char[kControlFrameBufferSize]),
127 enable_compression_(true),
128 visitor_(NULL),
129 debug_visitor_(NULL),
130 display_protocol_("SPDY"),
131 spdy_version_(version),
132 syn_frame_processed_(false),
133 probable_http_response_(false) {
134 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
135 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
136 Reset();
139 SpdyFramer::~SpdyFramer() {
140 if (header_compressor_.get()) {
141 deflateEnd(header_compressor_.get());
143 if (header_decompressor_.get()) {
144 inflateEnd(header_decompressor_.get());
148 void SpdyFramer::Reset() {
149 state_ = SPDY_RESET;
150 previous_state_ = SPDY_RESET;
151 error_code_ = SPDY_NO_ERROR;
152 remaining_data_length_ = 0;
153 remaining_control_header_ = 0;
154 current_frame_buffer_length_ = 0;
155 current_frame_type_ = DATA;
156 current_frame_flags_ = 0;
157 current_frame_length_ = 0;
158 current_frame_stream_id_ = kInvalidStream;
159 settings_scratch_.Reset();
162 size_t SpdyFramer::GetDataFrameMinimumSize() const {
163 // Size, in bytes, of the data frame header. Future versions of SPDY
164 // will likely vary this, so we allow for the flexibility of a function call
165 // for this value as opposed to a constant.
166 return 8;
169 // Size, in bytes, of the control frame header.
170 size_t SpdyFramer::GetControlFrameHeaderSize() const {
171 switch (protocol_version()) {
172 case SPDY2:
173 case SPDY3:
174 case SPDY4:
175 return 8;
177 LOG(DFATAL) << "Unhandled SPDY version.";
178 return 0;
181 size_t SpdyFramer::GetSynStreamMinimumSize() const {
182 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
183 // name-value block.
184 if (spdy_version_ < 4) {
185 // Calculated as:
186 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
187 // + 1 (unused, was credential slot)
188 return GetControlFrameHeaderSize() + 10;
189 } else {
190 // Calculated as:
191 // frame prefix + 4 (priority)
192 return GetControlFrameHeaderSize() + 4;
196 size_t SpdyFramer::GetSynReplyMinimumSize() const {
197 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
198 // name-value block.
199 size_t size = GetControlFrameHeaderSize();
200 if (spdy_version_ < 4) {
201 // Calculated as:
202 // control frame header + 4 (stream IDs)
203 size += 4;
206 // In SPDY 2, there were 2 unused bytes before payload.
207 if (protocol_version() < 3) {
208 size += 2;
211 return size;
214 size_t SpdyFramer::GetRstStreamMinimumSize() const {
215 // Size, in bytes, of a RST_STREAM frame.
216 if (spdy_version_ < 4) {
217 // Calculated as:
218 // control frame header + 4 (stream id) + 4 (status code)
219 return GetControlFrameHeaderSize() + 8;
220 } else {
221 // Calculated as:
222 // frame prefix + 4 (status code)
223 return GetControlFrameHeaderSize() + 4;
227 size_t SpdyFramer::GetSettingsMinimumSize() const {
228 // Size, in bytes, of a SETTINGS frame not including the IDs and values
229 // from the variable-length value block. Calculated as:
230 // control frame header + 4 (number of ID/value pairs)
231 return GetControlFrameHeaderSize() + 4;
234 size_t SpdyFramer::GetPingSize() const {
235 // Size, in bytes, of this PING frame. Calculated as:
236 // control frame header + 4 (id)
237 return GetControlFrameHeaderSize() + 4;
240 size_t SpdyFramer::GetGoAwayMinimumSize() const {
241 // Size, in bytes, of this GOAWAY frame. Calculated as:
242 // 1. Control frame header size
243 size_t size = GetControlFrameHeaderSize();
245 // 2. Last good stream id (4 bytes)
246 size += 4;
248 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
249 if (protocol_version() >= 3) {
250 size += 4;
253 return size;
256 size_t SpdyFramer::GetHeadersMinimumSize() const {
257 // Size, in bytes, of a HEADERS frame not including the variable-length
258 // name-value block.
259 size_t size = GetControlFrameHeaderSize();
260 if (spdy_version_ < 4) {
261 // Calculated as:
262 // control frame header + 4 (stream IDs)
263 size += 4;
266 // In SPDY 2, there were 2 unused bytes before payload.
267 if (protocol_version() < 3) {
268 size += 2;
271 return size;
274 size_t SpdyFramer::GetWindowUpdateSize() const {
275 // Size, in bytes, of a WINDOW_UPDATE frame.
276 if (spdy_version_ < 4) {
277 // Calculated as:
278 // control frame header + 4 (stream id) + 4 (delta)
279 return GetControlFrameHeaderSize() + 8;
280 } else {
281 // Calculated as:
282 // frame prefix + 4 (delta)
283 return GetControlFrameHeaderSize() + 4;
287 size_t SpdyFramer::GetBlockedSize() const {
288 DCHECK_LE(4, protocol_version());
289 // Size, in bytes, of a BLOCKED frame.
290 // The BLOCKED frame has no payload beyond the control frame header.
291 return GetControlFrameHeaderSize();
294 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
295 DCHECK_LE(4, protocol_version());
296 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
297 // Calculated as frame prefix + 4 (promised stream id).
298 return GetControlFrameHeaderSize() + 4;
301 size_t SpdyFramer::GetFrameMinimumSize() const {
302 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
305 size_t SpdyFramer::GetFrameMaximumSize() const {
306 return (protocol_version() < 4) ? 0xffffff : 0xffff;
309 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
310 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
313 const char* SpdyFramer::StateToString(int state) {
314 switch (state) {
315 case SPDY_ERROR:
316 return "ERROR";
317 case SPDY_AUTO_RESET:
318 return "AUTO_RESET";
319 case SPDY_RESET:
320 return "RESET";
321 case SPDY_READING_COMMON_HEADER:
322 return "READING_COMMON_HEADER";
323 case SPDY_CONTROL_FRAME_PAYLOAD:
324 return "CONTROL_FRAME_PAYLOAD";
325 case SPDY_IGNORE_REMAINING_PAYLOAD:
326 return "IGNORE_REMAINING_PAYLOAD";
327 case SPDY_FORWARD_STREAM_FRAME:
328 return "FORWARD_STREAM_FRAME";
329 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
330 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
331 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
332 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
333 case SPDY_GOAWAY_FRAME_PAYLOAD:
334 return "SPDY_GOAWAY_FRAME_PAYLOAD";
335 case SPDY_RST_STREAM_FRAME_PAYLOAD:
336 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
337 case SPDY_SETTINGS_FRAME_PAYLOAD:
338 return "SPDY_SETTINGS_FRAME_PAYLOAD";
340 return "UNKNOWN_STATE";
343 void SpdyFramer::set_error(SpdyError error) {
344 DCHECK(visitor_);
345 error_code_ = error;
346 CHANGE_STATE(SPDY_ERROR);
347 visitor_->OnError(this);
350 const char* SpdyFramer::ErrorCodeToString(int error_code) {
351 switch (error_code) {
352 case SPDY_NO_ERROR:
353 return "NO_ERROR";
354 case SPDY_INVALID_CONTROL_FRAME:
355 return "INVALID_CONTROL_FRAME";
356 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
357 return "CONTROL_PAYLOAD_TOO_LARGE";
358 case SPDY_ZLIB_INIT_FAILURE:
359 return "ZLIB_INIT_FAILURE";
360 case SPDY_UNSUPPORTED_VERSION:
361 return "UNSUPPORTED_VERSION";
362 case SPDY_DECOMPRESS_FAILURE:
363 return "DECOMPRESS_FAILURE";
364 case SPDY_COMPRESS_FAILURE:
365 return "COMPRESS_FAILURE";
366 case SPDY_INVALID_DATA_FRAME_FLAGS:
367 return "SPDY_INVALID_DATA_FRAME_FLAGS";
368 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
369 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
371 return "UNKNOWN_ERROR";
374 const char* SpdyFramer::StatusCodeToString(int status_code) {
375 switch (status_code) {
376 case RST_STREAM_INVALID:
377 return "INVALID";
378 case RST_STREAM_PROTOCOL_ERROR:
379 return "PROTOCOL_ERROR";
380 case RST_STREAM_INVALID_STREAM:
381 return "INVALID_STREAM";
382 case RST_STREAM_REFUSED_STREAM:
383 return "REFUSED_STREAM";
384 case RST_STREAM_UNSUPPORTED_VERSION:
385 return "UNSUPPORTED_VERSION";
386 case RST_STREAM_CANCEL:
387 return "CANCEL";
388 case RST_STREAM_INTERNAL_ERROR:
389 return "INTERNAL_ERROR";
390 case RST_STREAM_FLOW_CONTROL_ERROR:
391 return "FLOW_CONTROL_ERROR";
392 case RST_STREAM_STREAM_IN_USE:
393 return "STREAM_IN_USE";
394 case RST_STREAM_STREAM_ALREADY_CLOSED:
395 return "STREAM_ALREADY_CLOSED";
396 case RST_STREAM_INVALID_CREDENTIALS:
397 return "INVALID_CREDENTIALS";
398 case RST_STREAM_FRAME_TOO_LARGE:
399 return "FRAME_TOO_LARGE";
401 return "UNKNOWN_STATUS";
404 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
405 switch (type) {
406 case DATA:
407 return "DATA";
408 case SYN_STREAM:
409 return "SYN_STREAM";
410 case SYN_REPLY:
411 return "SYN_REPLY";
412 case RST_STREAM:
413 return "RST_STREAM";
414 case SETTINGS:
415 return "SETTINGS";
416 case NOOP:
417 return "NOOP";
418 case PING:
419 return "PING";
420 case GOAWAY:
421 return "GOAWAY";
422 case HEADERS:
423 return "HEADERS";
424 case WINDOW_UPDATE:
425 return "WINDOW_UPDATE";
426 case CREDENTIAL:
427 return "CREDENTIAL";
428 case BLOCKED:
429 return "BLOCKED";
430 case PUSH_PROMISE:
431 return "PUSH_PROMISE";
433 return "UNKNOWN_CONTROL_TYPE";
436 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
437 DCHECK(visitor_);
438 DCHECK(data);
440 size_t original_len = len;
441 do {
442 previous_state_ = state_;
443 switch (state_) {
444 case SPDY_ERROR:
445 goto bottom;
447 case SPDY_AUTO_RESET:
448 case SPDY_RESET:
449 Reset();
450 if (len > 0) {
451 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
453 break;
455 case SPDY_READING_COMMON_HEADER: {
456 size_t bytes_read = ProcessCommonHeader(data, len);
457 len -= bytes_read;
458 data += bytes_read;
459 break;
462 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
463 // Control frames that contain header blocks
464 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE)
465 // take a different path through the state machine - they
466 // will go:
467 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
468 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
470 // SETTINGS frames take a slightly modified route:
471 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
472 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
474 // All other control frames will use the alternate route directly to
475 // SPDY_CONTROL_FRAME_PAYLOAD
476 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
477 len -= bytes_read;
478 data += bytes_read;
479 break;
482 case SPDY_SETTINGS_FRAME_PAYLOAD: {
483 int bytes_read = ProcessSettingsFramePayload(data, len);
484 len -= bytes_read;
485 data += bytes_read;
486 break;
489 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
490 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
491 len -= bytes_read;
492 data += bytes_read;
493 break;
496 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
497 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
498 len -= bytes_read;
499 data += bytes_read;
500 break;
503 case SPDY_GOAWAY_FRAME_PAYLOAD: {
504 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
505 len -= bytes_read;
506 data += bytes_read;
507 break;
510 case SPDY_CONTROL_FRAME_PAYLOAD: {
511 size_t bytes_read = ProcessControlFramePayload(data, len);
512 len -= bytes_read;
513 data += bytes_read;
514 break;
517 case SPDY_IGNORE_REMAINING_PAYLOAD:
518 // control frame has too-large payload
519 // intentional fallthrough
520 case SPDY_FORWARD_STREAM_FRAME: {
521 size_t bytes_read = ProcessDataFramePayload(data, len);
522 len -= bytes_read;
523 data += bytes_read;
524 break;
526 default:
527 LOG(DFATAL) << "Invalid value for " << display_protocol_
528 << " framer state: " << state_;
529 // This ensures that we don't infinite-loop if state_ gets an
530 // invalid value somehow, such as due to a SpdyFramer getting deleted
531 // from a callback it calls.
532 goto bottom;
534 } while (state_ != previous_state_);
535 bottom:
536 DCHECK(len == 0 || state_ == SPDY_ERROR);
537 if (current_frame_buffer_length_ == 0 &&
538 remaining_data_length_ == 0 &&
539 remaining_control_header_ == 0) {
540 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
541 << "State: " << StateToString(state_);
544 return original_len - len;
547 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
548 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
549 // state.
550 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
552 size_t original_len = len;
554 // Update current frame buffer as needed.
555 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
556 size_t bytes_desired =
557 GetControlFrameHeaderSize() - current_frame_buffer_length_;
558 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
561 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
562 // Not enough information to do anything meaningful.
563 return original_len - len;
566 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
567 // when processing DATA frames below.
568 scoped_ptr<SpdyFrameReader> reader(
569 new SpdyFrameReader(current_frame_buffer_.get(),
570 current_frame_buffer_length_));
572 uint16 version = 0;
573 bool is_control_frame = false;
575 uint16 control_frame_type_field = DATA;
576 // ProcessControlFrameHeader() will set current_frame_type_ to the
577 // correct value if this is a valid control frame.
578 current_frame_type_ = DATA;
579 if (protocol_version() < 4) {
580 bool successful_read = reader->ReadUInt16(&version);
581 DCHECK(successful_read);
582 is_control_frame = (version & kControlFlagMask) != 0;
583 version &= ~kControlFlagMask; // Only valid for control frames.
585 if (is_control_frame) {
586 // We check control_frame_type_field's validity in
587 // ProcessControlFrameHeader().
588 successful_read = reader->ReadUInt16(&control_frame_type_field);
589 } else {
590 reader->Rewind();
591 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
593 DCHECK(successful_read);
595 successful_read = reader->ReadUInt8(&current_frame_flags_);
596 DCHECK(successful_read);
598 uint32 length_field = 0;
599 successful_read = reader->ReadUInt24(&length_field);
600 DCHECK(successful_read);
601 remaining_data_length_ = length_field;
602 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
603 } else {
604 version = protocol_version();
605 uint16 length_field = 0;
606 bool successful_read = reader->ReadUInt16(&length_field);
607 DCHECK(successful_read);
608 current_frame_length_ = length_field;
610 uint8 control_frame_type_field_uint8 = DATA;
611 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
612 DCHECK(successful_read);
613 // We check control_frame_type_field's validity in
614 // ProcessControlFrameHeader().
615 control_frame_type_field = control_frame_type_field_uint8;
616 is_control_frame = (control_frame_type_field != DATA);
618 successful_read = reader->ReadUInt8(&current_frame_flags_);
619 DCHECK(successful_read);
621 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
622 DCHECK(successful_read);
624 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
626 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
627 : GetDataFrameMinimumSize(),
628 reader->GetBytesConsumed());
629 DCHECK_EQ(current_frame_length_,
630 remaining_data_length_ + reader->GetBytesConsumed());
632 // This is just a sanity check for help debugging early frame errors.
633 if (remaining_data_length_ > 1000000u) {
634 // The strncmp for 5 is safe because we only hit this point if we
635 // have kMinCommonHeader (8) bytes
636 if (!syn_frame_processed_ &&
637 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
638 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
639 << " request";
640 probable_http_response_ = true;
641 } else {
642 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
643 << " session is likely corrupt.";
647 // if we're here, then we have the common header all received.
648 if (!is_control_frame) {
649 if (current_frame_flags_ & ~DATA_FLAG_FIN) {
650 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
651 } else {
652 visitor_->OnDataFrameHeader(current_frame_stream_id_,
653 remaining_data_length_,
654 current_frame_flags_ & DATA_FLAG_FIN);
655 if (remaining_data_length_ > 0) {
656 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
657 } else {
658 // Empty data frame.
659 if (current_frame_flags_ & DATA_FLAG_FIN) {
660 visitor_->OnStreamFrameData(
661 current_frame_stream_id_, NULL, 0, true);
663 CHANGE_STATE(SPDY_AUTO_RESET);
666 } else if (version != spdy_version_) {
667 // We check version before we check validity: version can never be
668 // 'invalid', it can only be unsupported.
669 DVLOG(1) << "Unsupported SPDY version " << version
670 << " (expected " << spdy_version_ << ")";
671 set_error(SPDY_UNSUPPORTED_VERSION);
672 } else {
673 ProcessControlFrameHeader(control_frame_type_field);
676 return original_len - len;
679 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
680 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
681 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
683 if (control_frame_type_field < FIRST_CONTROL_TYPE ||
684 control_frame_type_field > LAST_CONTROL_TYPE) {
685 set_error(SPDY_INVALID_CONTROL_FRAME);
686 return;
689 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
691 if (current_frame_type_ == NOOP) {
692 DVLOG(1) << "NOOP control frame found. Ignoring.";
693 CHANGE_STATE(SPDY_AUTO_RESET);
694 return;
697 if (current_frame_type_ == CREDENTIAL) {
698 DCHECK_EQ(3, protocol_version());
699 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
700 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
701 return;
704 // Do some sanity checking on the control frame sizes and flags.
705 switch (current_frame_type_) {
706 case SYN_STREAM:
707 DCHECK_GT(4, spdy_version_);
708 if (current_frame_length_ < GetSynStreamMinimumSize()) {
709 set_error(SPDY_INVALID_CONTROL_FRAME);
710 } else if (current_frame_flags_ &
711 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
712 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
714 break;
715 case SYN_REPLY:
716 if (current_frame_length_ < GetSynReplyMinimumSize()) {
717 set_error(SPDY_INVALID_CONTROL_FRAME);
718 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
719 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
721 break;
722 case RST_STREAM:
723 // For SPDY versions < 4, the header has a fixed length.
724 // For SPDY version 4 and up, the RST_STREAM frame may include optional
725 // opaque data, so we only have a lower limit on the frame size.
726 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
727 protocol_version() < 4) ||
728 (current_frame_length_ < GetRstStreamMinimumSize() &&
729 protocol_version() >= 4)) {
730 set_error(SPDY_INVALID_CONTROL_FRAME);
731 } else if (current_frame_flags_ != 0) {
732 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
734 break;
735 case SETTINGS:
736 // Make sure that we have an integral number of 8-byte key/value pairs,
737 // plus a 4-byte length field.
738 if (current_frame_length_ < GetSettingsMinimumSize() ||
739 (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
740 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
741 << current_frame_length_;
742 set_error(SPDY_INVALID_CONTROL_FRAME);
743 } else if (current_frame_flags_ &
744 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
745 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
747 break;
748 case PING:
749 if (current_frame_length_ != GetPingSize()) {
750 set_error(SPDY_INVALID_CONTROL_FRAME);
751 } else if (current_frame_flags_ != 0) {
752 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
754 break;
755 case GOAWAY:
757 // For SPDY version < 4, there are only mandatory fields and the header
758 // has a fixed length. For SPDY version >= 4, optional opaque data may
759 // be appended to the GOAWAY frame, thus there is only a minimal length
760 // restriction.
761 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
762 protocol_version() < 4) ||
763 (current_frame_length_ < GetGoAwayMinimumSize() &&
764 protocol_version() >= 4)) {
765 set_error(SPDY_INVALID_CONTROL_FRAME);
766 } else if (current_frame_flags_ != 0) {
767 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
769 break;
771 case HEADERS:
773 size_t min_size = GetHeadersMinimumSize();
774 if (spdy_version_ > 3 &&
775 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
776 min_size += 4;
778 if (current_frame_length_ < min_size) {
779 set_error(SPDY_INVALID_CONTROL_FRAME);
780 } else if (spdy_version_ < 4 &&
781 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
782 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
783 } else if (spdy_version_ > 3 && current_frame_flags_ &
784 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY)) {
785 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
788 break;
789 case WINDOW_UPDATE:
790 if (current_frame_length_ != GetWindowUpdateSize()) {
791 set_error(SPDY_INVALID_CONTROL_FRAME);
792 } else if (current_frame_flags_ != 0) {
793 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
795 break;
796 case BLOCKED:
797 if (current_frame_length_ != GetBlockedSize()) {
798 set_error(SPDY_INVALID_CONTROL_FRAME);
799 } else if (current_frame_flags_ != 0) {
800 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
802 break;
803 case PUSH_PROMISE:
804 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
805 set_error(SPDY_INVALID_CONTROL_FRAME);
806 } else if (current_frame_flags_ != 0) {
807 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
809 break;
810 default:
811 LOG(WARNING) << "Valid " << display_protocol_
812 << " control frame with unhandled type: "
813 << current_frame_type_;
814 // This branch should be unreachable because of the frame type bounds
815 // check above. However, we DLOG(FATAL) here in an effort to painfully
816 // club the head of the developer who failed to keep this file in sync
817 // with spdy_protocol.h.
818 DLOG(FATAL);
819 set_error(SPDY_INVALID_CONTROL_FRAME);
820 break;
823 if (state_ == SPDY_ERROR) {
824 return;
827 if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
828 DLOG(WARNING) << "Received control frame with way too big of a payload: "
829 << current_frame_length_;
830 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
831 return;
834 if (current_frame_type_ == GOAWAY) {
835 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
836 return;
839 if (current_frame_type_ == RST_STREAM) {
840 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
841 return;
844 // Determine the frame size without variable-length data.
845 int32 frame_size_without_variable_data;
846 switch (current_frame_type_) {
847 case SYN_STREAM:
848 syn_frame_processed_ = true;
849 frame_size_without_variable_data = GetSynStreamMinimumSize();
850 break;
851 case SYN_REPLY:
852 syn_frame_processed_ = true;
853 frame_size_without_variable_data = GetSynReplyMinimumSize();
854 break;
855 case SETTINGS:
856 frame_size_without_variable_data = GetSettingsMinimumSize();
857 break;
858 case HEADERS:
859 frame_size_without_variable_data = GetHeadersMinimumSize();
860 if (spdy_version_ > 3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
861 frame_size_without_variable_data += 4; // priority
863 break;
864 case PUSH_PROMISE:
865 frame_size_without_variable_data = GetPushPromiseMinimumSize();
866 break;
867 default:
868 frame_size_without_variable_data = -1;
869 break;
872 if ((frame_size_without_variable_data == -1) &&
873 (current_frame_length_ > kControlFrameBufferSize)) {
874 // We should already be in an error state. Double-check.
875 DCHECK_EQ(SPDY_ERROR, state_);
876 if (state_ != SPDY_ERROR) {
877 LOG(DFATAL) << display_protocol_
878 << " control frame buffer too small for fixed-length frame.";
879 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
881 return;
884 if (frame_size_without_variable_data > 0) {
885 // We have a control frame with a header block. We need to parse the
886 // remainder of the control frame's header before we can parse the header
887 // block. The start of the header block varies with the control type.
888 DCHECK_GE(frame_size_without_variable_data,
889 static_cast<int32>(current_frame_buffer_length_));
890 remaining_control_header_ = frame_size_without_variable_data -
891 current_frame_buffer_length_;
893 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
894 return;
897 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
900 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
901 size_t max_bytes) {
902 size_t bytes_to_read = std::min(*len, max_bytes);
903 if (bytes_to_read > 0) {
904 DCHECK_GE(kControlFrameBufferSize,
905 current_frame_buffer_length_ + bytes_to_read);
906 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
907 *data,
908 bytes_to_read);
909 current_frame_buffer_length_ += bytes_to_read;
910 *data += bytes_to_read;
911 *len -= bytes_to_read;
913 return bytes_to_read;
916 size_t SpdyFramer::GetSerializedLength(const int spdy_version,
917 const SpdyHeaderBlock* headers) {
918 const size_t num_name_value_pairs_size
919 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
920 const size_t length_of_name_size = num_name_value_pairs_size;
921 const size_t length_of_value_size = num_name_value_pairs_size;
923 size_t total_length = num_name_value_pairs_size;
924 for (SpdyHeaderBlock::const_iterator it = headers->begin();
925 it != headers->end();
926 ++it) {
927 // We add space for the length of the name and the length of the value as
928 // well as the length of the name and the length of the value.
929 total_length += length_of_name_size + it->first.size() +
930 length_of_value_size + it->second.size();
932 return total_length;
935 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
936 const int spdy_version,
937 const SpdyHeaderBlock* headers) {
938 if (spdy_version < 3) {
939 frame->WriteUInt16(headers->size()); // Number of headers.
940 } else {
941 frame->WriteUInt32(headers->size()); // Number of headers.
943 SpdyHeaderBlock::const_iterator it;
944 for (it = headers->begin(); it != headers->end(); ++it) {
945 if (spdy_version < 3) {
946 frame->WriteString(it->first);
947 frame->WriteString(it->second);
948 } else {
949 frame->WriteStringPiece32(it->first);
950 frame->WriteStringPiece32(it->second);
955 // TODO(phajdan.jr): Clean up after we no longer need
956 // to workaround http://crbug.com/139744.
957 #if !defined(USE_SYSTEM_ZLIB)
959 // These constants are used by zlib to differentiate between normal data and
960 // cookie data. Cookie data is handled specially by zlib when compressing.
961 enum ZDataClass {
962 // kZStandardData is compressed normally, save that it will never match
963 // against any other class of data in the window.
964 kZStandardData = Z_CLASS_STANDARD,
965 // kZCookieData is compressed in its own Huffman blocks and only matches in
966 // its entirety and only against other kZCookieData blocks. Any matches must
967 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
968 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
969 // prefix matches.
970 kZCookieData = Z_CLASS_COOKIE,
971 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
972 // against the window.
973 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
976 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
977 // needed when switching between classes of data.
978 static void WriteZ(const base::StringPiece& data,
979 ZDataClass clas,
980 z_stream* out) {
981 int rv;
983 // If we are switching from standard to non-standard data then we need to end
984 // the current Huffman context to avoid it leaking between them.
985 if (out->clas == kZStandardData &&
986 clas != kZStandardData) {
987 out->avail_in = 0;
988 rv = deflate(out, Z_PARTIAL_FLUSH);
989 DCHECK_EQ(Z_OK, rv);
990 DCHECK_EQ(0u, out->avail_in);
991 DCHECK_LT(0u, out->avail_out);
994 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
995 out->avail_in = data.size();
996 out->clas = clas;
997 if (clas == kZStandardData) {
998 rv = deflate(out, Z_NO_FLUSH);
999 } else {
1000 rv = deflate(out, Z_PARTIAL_FLUSH);
1002 if (!data.empty()) {
1003 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1004 DCHECK_EQ(Z_OK, rv);
1006 DCHECK_EQ(0u, out->avail_in);
1007 DCHECK_LT(0u, out->avail_out);
1010 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1011 static void WriteLengthZ(size_t n,
1012 unsigned length,
1013 ZDataClass clas,
1014 z_stream* out) {
1015 char buf[4];
1016 DCHECK_LE(length, sizeof(buf));
1017 for (unsigned i = 1; i <= length; i++) {
1018 buf[length - i] = n;
1019 n >>= 8;
1021 WriteZ(base::StringPiece(buf, length), clas, out);
1024 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1025 // manner that resists the length of the compressed data from compromising
1026 // cookie data.
1027 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1028 z_stream* z) const {
1029 unsigned length_length = 4;
1030 if (spdy_version_ < 3)
1031 length_length = 2;
1033 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1035 std::map<std::string, std::string>::const_iterator it;
1036 for (it = headers->begin(); it != headers->end(); ++it) {
1037 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1038 WriteZ(it->first, kZStandardData, z);
1040 if (it->first == "cookie") {
1041 // We require the cookie values (save for the last) to end with a
1042 // semicolon and (save for the first) to start with a space. This is
1043 // typically the format that we are given them in but we reserialize them
1044 // to be sure.
1046 std::vector<base::StringPiece> cookie_values;
1047 size_t cookie_length = 0;
1048 base::StringPiece cookie_data(it->second);
1050 for (;;) {
1051 while (!cookie_data.empty() &&
1052 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1053 cookie_data.remove_prefix(1);
1055 if (cookie_data.empty())
1056 break;
1058 size_t i;
1059 for (i = 0; i < cookie_data.size(); i++) {
1060 if (cookie_data[i] == ';')
1061 break;
1063 if (i < cookie_data.size()) {
1064 cookie_values.push_back(cookie_data.substr(0, i));
1065 cookie_length += i + 2 /* semicolon and space */;
1066 cookie_data.remove_prefix(i + 1);
1067 } else {
1068 cookie_values.push_back(cookie_data);
1069 cookie_length += cookie_data.size();
1070 cookie_data.remove_prefix(i);
1074 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1075 for (size_t i = 0; i < cookie_values.size(); i++) {
1076 std::string cookie;
1077 // Since zlib will only back-reference complete cookies, a cookie that
1078 // is currently last (and so doesn't have a trailing semicolon) won't
1079 // match if it's later in a non-final position. The same is true of
1080 // the first cookie.
1081 if (i == 0 && cookie_values.size() == 1) {
1082 cookie = cookie_values[i].as_string();
1083 } else if (i == 0) {
1084 cookie = cookie_values[i].as_string() + ";";
1085 } else if (i < cookie_values.size() - 1) {
1086 cookie = " " + cookie_values[i].as_string() + ";";
1087 } else {
1088 cookie = " " + cookie_values[i].as_string();
1090 WriteZ(cookie, kZCookieData, z);
1092 } else if (it->first == "accept" ||
1093 it->first == "accept-charset" ||
1094 it->first == "accept-encoding" ||
1095 it->first == "accept-language" ||
1096 it->first == "host" ||
1097 it->first == "version" ||
1098 it->first == "method" ||
1099 it->first == "scheme" ||
1100 it->first == ":host" ||
1101 it->first == ":version" ||
1102 it->first == ":method" ||
1103 it->first == ":scheme" ||
1104 it->first == "user-agent") {
1105 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1106 WriteZ(it->second, kZStandardData, z);
1107 } else {
1108 // Non-whitelisted headers are Huffman compressed in their own block, but
1109 // don't match against the window.
1110 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1111 WriteZ(it->second, kZHuffmanOnlyData, z);
1115 z->avail_in = 0;
1116 int rv = deflate(z, Z_SYNC_FLUSH);
1117 DCHECK_EQ(Z_OK, rv);
1118 z->clas = kZStandardData;
1120 #endif // !defined(USE_SYSTEM_ZLIB)
1122 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1123 size_t len) {
1124 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1125 const size_t original_len = len;
1127 if (remaining_control_header_ > 0) {
1128 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1129 remaining_control_header_);
1130 remaining_control_header_ -= bytes_read;
1131 remaining_data_length_ -= bytes_read;
1134 if (remaining_control_header_ == 0) {
1135 SpdyFrameReader reader(current_frame_buffer_.get(),
1136 current_frame_buffer_length_);
1137 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1139 switch (current_frame_type_) {
1140 case SYN_STREAM:
1142 DCHECK_GT(4, spdy_version_);
1143 bool successful_read = true;
1144 if (spdy_version_ < 4) {
1145 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1146 DCHECK(successful_read);
1148 if (current_frame_stream_id_ == 0) {
1149 set_error(SPDY_INVALID_CONTROL_FRAME);
1150 break;
1153 SpdyStreamId associated_to_stream_id = kInvalidStream;
1154 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1155 DCHECK(successful_read);
1157 SpdyPriority priority = 0;
1158 successful_read = reader.ReadUInt8(&priority);
1159 DCHECK(successful_read);
1160 if (protocol_version() < 3) {
1161 priority = priority >> 6;
1162 } else {
1163 priority = priority >> 5;
1166 // Seek past unused byte; used to be credential slot in SPDY 3.
1167 reader.Seek(1);
1169 DCHECK(reader.IsDoneReading());
1170 if (debug_visitor_) {
1171 debug_visitor_->OnReceiveCompressedFrame(
1172 current_frame_stream_id_,
1173 current_frame_type_,
1174 current_frame_length_);
1176 visitor_->OnSynStream(
1177 current_frame_stream_id_,
1178 associated_to_stream_id,
1179 priority,
1180 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1181 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1183 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1184 break;
1185 case SETTINGS:
1186 visitor_->OnSettings(current_frame_flags_ &
1187 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1188 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1189 break;
1190 case SYN_REPLY:
1191 case HEADERS:
1192 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1194 if (spdy_version_ > 3) {
1195 DCHECK_EQ(HEADERS, current_frame_type_);
1197 bool successful_read = true;
1198 if (spdy_version_ < 4) {
1199 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1200 DCHECK(successful_read);
1202 if (current_frame_stream_id_ == 0) {
1203 set_error(SPDY_INVALID_CONTROL_FRAME);
1204 break;
1206 if (protocol_version() < 3) {
1207 // SPDY 2 had two unused bytes here. Seek past them.
1208 reader.Seek(2);
1210 const bool has_priority =
1211 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1212 uint32 priority = 0;
1213 if (protocol_version() > 3 && has_priority) {
1214 successful_read = reader.ReadUInt31(&priority);
1215 DCHECK(successful_read);
1217 DCHECK(reader.IsDoneReading());
1218 if (debug_visitor_) {
1219 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1220 SpdyFrameType reported_type = current_frame_type_;
1221 if (protocol_version() > 3 && has_priority) {
1222 reported_type = SYN_STREAM;
1224 debug_visitor_->OnReceiveCompressedFrame(
1225 current_frame_stream_id_,
1226 reported_type,
1227 current_frame_length_);
1229 if (current_frame_type_ == SYN_REPLY) {
1230 visitor_->OnSynReply(
1231 current_frame_stream_id_,
1232 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1233 } else if (spdy_version_ > 3 &&
1234 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1235 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1236 // can be made independent of wire changes.
1237 visitor_->OnSynStream(
1238 current_frame_stream_id_,
1239 0, // associated_to_stream_id
1240 priority,
1241 current_frame_flags_ & CONTROL_FLAG_FIN,
1242 false); // unidirectional
1243 } else {
1244 visitor_->OnHeaders(
1245 current_frame_stream_id_,
1246 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1249 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1250 break;
1251 case PUSH_PROMISE:
1253 DCHECK_LE(4, protocol_version());
1254 if (current_frame_stream_id_ == 0) {
1255 set_error(SPDY_INVALID_CONTROL_FRAME);
1256 break;
1258 SpdyStreamId promised_stream_id = kInvalidStream;
1259 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1260 DCHECK(successful_read);
1261 DCHECK(reader.IsDoneReading());
1262 if (promised_stream_id == 0) {
1263 set_error(SPDY_INVALID_CONTROL_FRAME);
1264 break;
1266 if (debug_visitor_) {
1267 debug_visitor_->OnReceiveCompressedFrame(
1268 current_frame_stream_id_,
1269 current_frame_type_,
1270 current_frame_length_);
1272 visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id);
1274 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1275 break;
1276 default:
1277 DCHECK(false);
1280 return original_len - len;
1283 // Does not buffer the control payload. Instead, either passes directly to the
1284 // visitor or decompresses and then passes directly to the visitor, via
1285 // IncrementallyDeliverControlFrameHeaderData() or
1286 // IncrementallyDecompressControlFrameHeaderData() respectively.
1287 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1288 size_t data_len) {
1289 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1291 bool processed_successfully = true;
1292 if (current_frame_type_ != SYN_STREAM &&
1293 current_frame_type_ != SYN_REPLY &&
1294 current_frame_type_ != HEADERS &&
1295 current_frame_type_ != PUSH_PROMISE) {
1296 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1298 size_t process_bytes = std::min(data_len, remaining_data_length_);
1299 if (process_bytes > 0) {
1300 if (enable_compression_) {
1301 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1302 current_frame_stream_id_, data, process_bytes);
1303 } else {
1304 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1305 current_frame_stream_id_, data, process_bytes);
1308 remaining_data_length_ -= process_bytes;
1311 // Handle the case that there is no futher data in this frame.
1312 if (remaining_data_length_ == 0 && processed_successfully) {
1313 // The complete header block has been delivered. We send a zero-length
1314 // OnControlFrameHeaderData() to indicate this.
1315 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1317 // If this is a FIN, tell the caller.
1318 if (current_frame_flags_ & CONTROL_FLAG_FIN) {
1319 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1322 CHANGE_STATE(SPDY_AUTO_RESET);
1325 // Handle error.
1326 if (!processed_successfully) {
1327 return data_len;
1330 // Return amount processed.
1331 return process_bytes;
1334 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1335 size_t data_len) {
1336 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1337 DCHECK_EQ(SETTINGS, current_frame_type_);
1338 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1339 size_t processed_bytes = 0;
1341 // Loop over our incoming data.
1342 while (unprocessed_bytes > 0) {
1343 // Process up to one setting at a time.
1344 size_t processing = std::min(
1345 unprocessed_bytes,
1346 static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
1348 // Check if we have a complete setting in our input.
1349 if (processing == 8) {
1350 // Parse the setting directly out of the input without buffering.
1351 if (!ProcessSetting(data + processed_bytes)) {
1352 set_error(SPDY_INVALID_CONTROL_FRAME);
1353 return processed_bytes;
1355 } else {
1356 // Continue updating settings_scratch_.setting_buf.
1357 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1358 data + processed_bytes,
1359 processing);
1360 settings_scratch_.setting_buf_len += processing;
1362 // Check if we have a complete setting buffered.
1363 if (settings_scratch_.setting_buf_len == 8) {
1364 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1365 set_error(SPDY_INVALID_CONTROL_FRAME);
1366 return processed_bytes;
1368 // Reset settings_scratch_.setting_buf for our next setting.
1369 settings_scratch_.setting_buf_len = 0;
1373 // Iterate.
1374 unprocessed_bytes -= processing;
1375 processed_bytes += processing;
1378 // Check if we're done handling this SETTINGS frame.
1379 remaining_data_length_ -= processed_bytes;
1380 if (remaining_data_length_ == 0) {
1381 CHANGE_STATE(SPDY_AUTO_RESET);
1384 return processed_bytes;
1387 bool SpdyFramer::ProcessSetting(const char* data) {
1388 // Extract fields.
1389 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1390 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1391 SettingsFlagsAndId id_and_flags =
1392 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
1393 uint8 flags = id_and_flags.flags();
1394 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1396 // Validate id.
1397 switch (id_and_flags.id()) {
1398 case SETTINGS_UPLOAD_BANDWIDTH:
1399 case SETTINGS_DOWNLOAD_BANDWIDTH:
1400 case SETTINGS_ROUND_TRIP_TIME:
1401 case SETTINGS_MAX_CONCURRENT_STREAMS:
1402 case SETTINGS_CURRENT_CWND:
1403 case SETTINGS_DOWNLOAD_RETRANS_RATE:
1404 case SETTINGS_INITIAL_WINDOW_SIZE:
1405 // Valid values.
1406 break;
1407 default:
1408 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
1409 return false;
1411 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
1413 // Detect duplciates.
1414 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
1415 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1416 << " in " << display_protocol_ << " SETTINGS frame "
1417 << "(last settikng id was "
1418 << settings_scratch_.last_setting_id << ").";
1419 return false;
1421 settings_scratch_.last_setting_id = id;
1423 // Validate flags.
1424 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1425 if ((flags & ~(kFlagsMask)) != 0) {
1426 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1427 << flags;
1428 return false;
1431 // Validation succeeded. Pass on to visitor.
1432 visitor_->OnSetting(id, flags, value);
1433 return true;
1436 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1437 size_t original_len = len;
1438 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1439 remaining_data_length_);
1440 remaining_data_length_ -= bytes_read;
1441 if (remaining_data_length_ == 0) {
1442 SpdyFrameReader reader(current_frame_buffer_.get(),
1443 current_frame_buffer_length_);
1444 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1446 // Use frame-specific handlers.
1447 switch (current_frame_type_) {
1448 case RST_STREAM:
1449 // TODO(jgraettinger): Leaving this here for future, saner patching.
1450 // RST_STREAM is separately handled by ProcessRstStreamFramePayload().
1451 NOTREACHED();
1452 if (false
1453 /*!FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1454 bool successful_read = true;
1455 if (spdy_version_ < 4) {
1456 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1457 DCHECK(successful_read);
1459 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1460 uint32 status_raw = status;
1461 successful_read = reader.ReadUInt32(&status_raw);
1462 DCHECK(successful_read);
1463 if (status_raw > RST_STREAM_INVALID &&
1464 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1465 status = static_cast<SpdyRstStreamStatus>(status_raw);
1466 } else {
1467 // TODO(hkhalil): Probably best to OnError here, depending on
1468 // our interpretation of the spec. Keeping with existing liberal
1469 // behavior for now.
1471 DCHECK(reader.IsDoneReading());
1472 visitor_->OnRstStream(current_frame_stream_id_, status);
1474 break;
1475 case PING: {
1476 SpdyPingId id = 0;
1477 bool successful_read = reader.ReadUInt32(&id);
1478 DCHECK(successful_read);
1479 DCHECK(reader.IsDoneReading());
1480 visitor_->OnPing(id);
1482 break;
1483 case WINDOW_UPDATE: {
1484 uint32 delta_window_size = 0;
1485 bool successful_read = true;
1486 if (spdy_version_ < 4) {
1487 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1488 DCHECK(successful_read);
1490 successful_read = reader.ReadUInt32(&delta_window_size);
1491 DCHECK(successful_read);
1492 DCHECK(reader.IsDoneReading());
1493 visitor_->OnWindowUpdate(current_frame_stream_id_,
1494 delta_window_size);
1496 break;
1497 case BLOCKED: {
1498 DCHECK_LE(4, protocol_version());
1499 DCHECK(reader.IsDoneReading());
1500 visitor_->OnBlocked(current_frame_stream_id_);
1502 break;
1503 default:
1504 // Unreachable.
1505 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1508 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1510 return original_len - len;
1513 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1514 if (len == 0) {
1515 return 0;
1517 // Clamp to the actual remaining payload.
1518 if (len > remaining_data_length_) {
1519 len = remaining_data_length_;
1521 size_t original_len = len;
1523 // Check if we had already read enough bytes to parse the GOAWAY header.
1524 const size_t header_size = GetGoAwayMinimumSize();
1525 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1526 bool already_parsed_header = (unread_header_bytes == 0);
1527 if (!already_parsed_header) {
1528 // Buffer the new GOAWAY header bytes we got.
1529 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1531 // Do we have enough to parse the constant size GOAWAY header?
1532 if (current_frame_buffer_length_ == header_size) {
1533 // Parse out the last good stream id.
1534 SpdyFrameReader reader(current_frame_buffer_.get(),
1535 current_frame_buffer_length_);
1536 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1537 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1538 DCHECK(successful_read);
1540 // In SPDYv3 and up, frames also specify a status code - parse it out.
1541 SpdyGoAwayStatus status = GOAWAY_OK;
1542 if (spdy_version_ >= 3) {
1543 uint32 status_raw = GOAWAY_OK;
1544 successful_read = reader.ReadUInt32(&status_raw);
1545 DCHECK(successful_read);
1546 // We've read an unsigned integer, so it's enough to only check
1547 // upper bound to ensure the value is in valid range.
1548 if (status_raw < GOAWAY_NUM_STATUS_CODES) {
1549 status = static_cast<SpdyGoAwayStatus>(status_raw);
1550 } else {
1551 // TODO(hkhalil): Probably best to OnError here, depending on
1552 // our interpretation of the spec. Keeping with existing liberal
1553 // behavior for now.
1554 DCHECK(false);
1557 // Finished parsing the GOAWAY header, call frame handler.
1558 visitor_->OnGoAway(current_frame_stream_id_, status);
1562 // Handle remaining data as opaque.
1563 bool processed_successfully = true;
1564 if (len > 0) {
1565 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1567 remaining_data_length_ -= original_len;
1568 if (!processed_successfully) {
1569 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1570 } else if (remaining_data_length_ == 0) {
1571 // Signal that there is not more opaque data.
1572 visitor_->OnGoAwayFrameData(NULL, 0);
1573 CHANGE_STATE(SPDY_AUTO_RESET);
1575 return original_len;
1578 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1579 if (len == 0) {
1580 return 0;
1582 // Clamp to the actual remaining payload.
1583 if (len > remaining_data_length_) {
1584 len = remaining_data_length_;
1586 size_t original_len = len;
1588 // Check if we had already read enough bytes to parse the fixed-length portion
1589 // of the RST_STREAM frame.
1590 const size_t header_size = GetRstStreamMinimumSize();
1591 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1592 bool already_parsed_header = (unread_header_bytes == 0);
1593 if (!already_parsed_header) {
1594 // Buffer the new RST_STREAM header bytes we got.
1595 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1597 // Do we have enough to parse the constant size RST_STREAM header?
1598 if (current_frame_buffer_length_ == header_size) {
1599 // Parse out the last good stream id.
1600 SpdyFrameReader reader(current_frame_buffer_.get(),
1601 current_frame_buffer_length_);
1602 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1603 if (protocol_version() < 4) {
1604 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1605 DCHECK(successful_read);
1608 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1609 uint32 status_raw = status;
1610 bool successful_read = reader.ReadUInt32(&status_raw);
1611 DCHECK(successful_read);
1612 // We've read an unsigned integer, so it's enough to only check
1613 // upper bound to ensure the value is in valid range.
1614 if (status_raw > RST_STREAM_INVALID &&
1615 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1616 status = static_cast<SpdyRstStreamStatus>(status_raw);
1617 } else {
1618 // TODO(hkhalil): Probably best to OnError here, depending on
1619 // our interpretation of the spec. Keeping with existing liberal
1620 // behavior for now.
1622 // Finished parsing the RST_STREAM header, call frame handler.
1623 visitor_->OnRstStream(current_frame_stream_id_, status);
1627 // Handle remaining data as opaque.
1628 bool processed_successfully = true;
1629 if (len > 0) {
1630 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
1632 remaining_data_length_ -= original_len;
1633 if (!processed_successfully) {
1634 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
1635 } else if (remaining_data_length_ == 0) {
1636 // Signal that there is not more opaque data.
1637 visitor_->OnRstStreamFrameData(NULL, 0);
1638 CHANGE_STATE(SPDY_AUTO_RESET);
1640 return original_len;
1643 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
1644 size_t original_len = len;
1646 if (remaining_data_length_ > 0) {
1647 size_t amount_to_forward = std::min(remaining_data_length_, len);
1648 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1649 // Only inform the visitor if there is data.
1650 if (amount_to_forward) {
1651 visitor_->OnStreamFrameData(
1652 current_frame_stream_id_, data, amount_to_forward, false);
1655 data += amount_to_forward;
1656 len -= amount_to_forward;
1657 remaining_data_length_ -= amount_to_forward;
1659 // If the FIN flag is set, and there is no more data in this data
1660 // frame, inform the visitor of EOF via a 0-length data frame.
1661 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
1662 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1666 if (remaining_data_length_ == 0) {
1667 CHANGE_STATE(SPDY_AUTO_RESET);
1669 return original_len - len;
1672 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
1673 size_t header_length,
1674 SpdyHeaderBlock* block) const {
1675 SpdyFrameReader reader(header_data, header_length);
1677 // Read number of headers.
1678 uint32 num_headers;
1679 if (spdy_version_ < 3) {
1680 uint16 temp;
1681 if (!reader.ReadUInt16(&temp)) {
1682 DVLOG(1) << "Unable to read number of headers.";
1683 return 0;
1685 num_headers = temp;
1686 } else {
1687 if (!reader.ReadUInt32(&num_headers)) {
1688 DVLOG(1) << "Unable to read number of headers.";
1689 return 0;
1693 // Read each header.
1694 for (uint32 index = 0; index < num_headers; ++index) {
1695 base::StringPiece temp;
1697 // Read header name.
1698 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1699 : !reader.ReadStringPiece32(&temp)) {
1700 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
1701 << num_headers << ").";
1702 return 0;
1704 std::string name = temp.as_string();
1706 // Read header value.
1707 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1708 : !reader.ReadStringPiece32(&temp)) {
1709 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
1710 << num_headers << ").";
1711 return 0;
1713 std::string value = temp.as_string();
1715 // Ensure no duplicates.
1716 if (block->find(name) != block->end()) {
1717 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1718 << num_headers << ").";
1719 return 0;
1722 // Store header.
1723 (*block)[name] = value;
1725 return reader.GetBytesConsumed();
1728 SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
1729 const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
1731 SpdyDataFlags flags = DATA_FLAG_NONE;
1732 if (data.fin()) {
1733 flags = DATA_FLAG_FIN;
1736 SpdyFrameBuilder builder(kSize);
1737 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1738 builder.WriteBytes(data.data().data(), data.data().length());
1739 DCHECK_EQ(kSize, builder.length());
1740 return builder.take();
1743 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
1744 const SpdyDataIR& data) const {
1745 const size_t kSize = GetDataFrameMinimumSize();
1747 SpdyDataFlags flags = DATA_FLAG_NONE;
1748 if (data.fin()) {
1749 flags = DATA_FLAG_FIN;
1752 SpdyFrameBuilder builder(kSize);
1753 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1754 if (protocol_version() < 4) {
1755 builder.OverwriteLength(*this, data.data().length());
1756 } else {
1757 builder.OverwriteLength(*this, data.data().length() + kSize);
1759 DCHECK_EQ(kSize, builder.length());
1760 return builder.take();
1763 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
1764 const SpdySynStreamIR& syn_stream) {
1765 uint8 flags = 0;
1766 if (syn_stream.fin()) {
1767 flags |= CONTROL_FLAG_FIN;
1769 if (syn_stream.unidirectional()) {
1770 // TODO(hkhalil): invalid for HTTP2.
1771 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
1773 if (spdy_version_ >= 4) {
1774 flags |= HEADERS_FLAG_PRIORITY;
1777 // Sanitize priority.
1778 uint8 priority = syn_stream.priority();
1779 if (priority > GetLowestPriority()) {
1780 DLOG(DFATAL) << "Priority out-of-bounds.";
1781 priority = GetLowestPriority();
1784 // The size of this frame, including variable-length name-value block.
1785 const size_t size = GetSynStreamMinimumSize()
1786 + GetSerializedLength(syn_stream.name_value_block());
1788 SpdyFrameBuilder builder(size);
1789 if (spdy_version_ < 4) {
1790 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
1791 builder.WriteUInt32(syn_stream.stream_id());
1792 builder.WriteUInt32(syn_stream.associated_to_stream_id());
1793 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
1794 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
1795 } else {
1796 builder.WriteFramePrefix(*this,
1797 HEADERS,
1798 flags,
1799 syn_stream.stream_id());
1800 builder.WriteUInt32(priority);
1802 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
1803 SerializeNameValueBlock(&builder, syn_stream);
1805 if (debug_visitor_) {
1806 const size_t payload_len = GetSerializedLength(
1807 protocol_version(), &(syn_stream.name_value_block()));
1808 // SPDY 4 reports this compression as a SYN_STREAM compression.
1809 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
1810 SYN_STREAM,
1811 payload_len,
1812 builder.length());
1815 return builder.take();
1818 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
1819 const SpdySynReplyIR& syn_reply) {
1820 uint8 flags = 0;
1821 if (syn_reply.fin()) {
1822 flags |= CONTROL_FLAG_FIN;
1825 // The size of this frame, including variable-length name-value block.
1826 size_t size = GetSynReplyMinimumSize()
1827 + GetSerializedLength(syn_reply.name_value_block());
1829 SpdyFrameBuilder builder(size);
1830 if (spdy_version_ < 4) {
1831 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
1832 builder.WriteUInt32(syn_reply.stream_id());
1833 } else {
1834 builder.WriteFramePrefix(*this,
1835 HEADERS,
1836 flags,
1837 syn_reply.stream_id());
1839 if (protocol_version() < 3) {
1840 builder.WriteUInt16(0); // Unused.
1842 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
1843 SerializeNameValueBlock(&builder, syn_reply);
1845 if (debug_visitor_) {
1846 const size_t payload_len = GetSerializedLength(
1847 protocol_version(), &(syn_reply.name_value_block()));
1848 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
1849 SYN_REPLY,
1850 payload_len,
1851 builder.length());
1854 return builder.take();
1857 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
1858 const SpdyRstStreamIR& rst_stream) const {
1859 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
1860 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
1861 // which doesn't currently include RST_STREAM payloads. GFE flags have been
1862 // commented but left in place to simplify future patching.
1863 // Compute the output buffer size, taking opaque data into account.
1864 uint16 expected_length = GetRstStreamMinimumSize();
1865 if (protocol_version() >= 4 &&
1866 false /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1867 expected_length += rst_stream.description().size();
1869 SpdyFrameBuilder builder(expected_length);
1871 // Serialize the RST_STREAM frame.
1872 if (protocol_version() < 4) {
1873 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
1874 builder.WriteUInt32(rst_stream.stream_id());
1875 } else {
1876 builder.WriteFramePrefix(*this, RST_STREAM, 0, rst_stream.stream_id());
1879 builder.WriteUInt32(rst_stream.status());
1881 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
1882 if (protocol_version() >= 4 && rst_stream.description().size() > 0 &&
1883 false /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1884 builder.WriteBytes(rst_stream.description().data(),
1885 rst_stream.description().size());
1888 DCHECK_EQ(expected_length, builder.length());
1889 return builder.take();
1892 SpdySerializedFrame* SpdyFramer::SerializeSettings(
1893 const SpdySettingsIR& settings) const {
1894 uint8 flags = 0;
1895 if (settings.clear_settings()) {
1896 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1898 const SpdySettingsIR::ValueMap* values = &(settings.values());
1900 // Size, in bytes, of this SETTINGS frame.
1901 const size_t size = GetSettingsMinimumSize() + (values->size() * 8);
1903 SpdyFrameBuilder builder(size);
1904 if (spdy_version_ < 4) {
1905 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
1906 } else {
1907 builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
1909 builder.WriteUInt32(values->size());
1910 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
1911 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
1912 it != values->end();
1913 ++it) {
1914 uint8 setting_flags = 0;
1915 if (it->second.persist_value) {
1916 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
1918 if (it->second.persisted) {
1919 setting_flags |= SETTINGS_FLAG_PERSISTED;
1921 SettingsFlagsAndId flags_and_id(setting_flags, it->first);
1922 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
1923 builder.WriteBytes(&id_and_flags_wire, 4);
1924 builder.WriteUInt32(it->second.value);
1926 DCHECK_EQ(size, builder.length());
1927 return builder.take();
1930 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
1931 DCHECK_LE(4, protocol_version());
1932 SpdyFrameBuilder builder(GetBlockedSize());
1933 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
1934 return builder.take();
1937 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
1938 SpdyFrameBuilder builder(GetPingSize());
1939 if (spdy_version_ < 4) {
1940 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
1941 } else {
1942 builder.WriteFramePrefix(*this, PING, 0, 0);
1944 builder.WriteUInt32(ping.id());
1945 DCHECK_EQ(GetPingSize(), builder.length());
1946 return builder.take();
1949 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
1950 const SpdyGoAwayIR& goaway) const {
1952 // Compute the output buffer size, take opaque data into account.
1953 uint16 expected_length = GetGoAwayMinimumSize();
1954 if (protocol_version() >= 4) {
1955 expected_length += goaway.description().size();
1957 SpdyFrameBuilder builder(expected_length);
1959 // Serialize the GOAWAY frame.
1960 if (spdy_version_ < 4) {
1961 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
1962 } else {
1963 builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
1966 // GOAWAY frames specify the last good stream id for all SPDY versions.
1967 builder.WriteUInt32(goaway.last_good_stream_id());
1969 // In SPDY3 and up, GOAWAY frames also specify the error status code.
1970 if (protocol_version() >= 3) {
1971 builder.WriteUInt32(goaway.status());
1974 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
1975 if ((protocol_version() >= 4) && (goaway.description().size() > 0)) {
1976 builder.WriteBytes(goaway.description().data(),
1977 goaway.description().size());
1980 DCHECK_EQ(expected_length, builder.length());
1981 return builder.take();
1984 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
1985 const SpdyHeadersIR& headers) {
1986 uint8 flags = 0;
1987 if (headers.fin()) {
1988 flags |= CONTROL_FLAG_FIN;
1991 // The size of this frame, including variable-length name-value block.
1992 size_t size = GetHeadersMinimumSize()
1993 + GetSerializedLength(headers.name_value_block());
1995 SpdyFrameBuilder builder(size);
1996 if (spdy_version_ < 4) {
1997 builder.WriteControlFrameHeader(*this, HEADERS, flags);
1998 builder.WriteUInt32(headers.stream_id());
1999 } else {
2000 builder.WriteFramePrefix(*this,
2001 HEADERS,
2002 flags,
2003 headers.stream_id());
2005 if (protocol_version() < 3) {
2006 builder.WriteUInt16(0); // Unused.
2008 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2010 SerializeNameValueBlock(&builder, headers);
2012 if (debug_visitor_) {
2013 const size_t payload_len = GetSerializedLength(
2014 protocol_version(), &(headers.name_value_block()));
2015 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2016 HEADERS,
2017 payload_len,
2018 builder.length());
2021 return builder.take();
2024 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2025 const SpdyWindowUpdateIR& window_update) const {
2026 SpdyFrameBuilder builder(GetWindowUpdateSize());
2027 if (spdy_version_ < 4) {
2028 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2029 builder.WriteUInt32(window_update.stream_id());
2030 } else {
2031 builder.WriteFramePrefix(*this,
2032 WINDOW_UPDATE,
2033 kNoFlags,
2034 window_update.stream_id());
2036 builder.WriteUInt32(window_update.delta());
2037 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2038 return builder.take();
2041 SpdyFrame* SpdyFramer::SerializePushPromise(
2042 const SpdyPushPromiseIR& push_promise) {
2043 DCHECK_LE(4, protocol_version());
2044 // The size of this frame, including variable-length name-value block.
2045 size_t size = GetPushPromiseMinimumSize()
2046 + GetSerializedLength(push_promise.name_value_block());
2048 SpdyFrameBuilder builder(size);
2049 builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags,
2050 push_promise.stream_id());
2051 builder.WriteUInt32(push_promise.promised_stream_id());
2052 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2054 SerializeNameValueBlock(&builder, push_promise);
2056 if (debug_visitor_) {
2057 const size_t payload_len = GetSerializedLength(
2058 protocol_version(), &(push_promise.name_value_block()));
2059 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2060 PUSH_PROMISE, payload_len, builder.length());
2063 return builder.take();
2066 namespace {
2068 class FrameSerializationVisitor : public SpdyFrameVisitor {
2069 public:
2070 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2071 virtual ~FrameSerializationVisitor() {}
2073 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2075 virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2076 frame_.reset(framer_->SerializeData(data));
2078 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2079 frame_.reset(framer_->SerializeSynStream(syn_stream));
2081 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2082 frame_.reset(framer_->SerializeSynReply(syn_reply));
2084 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2085 frame_.reset(framer_->SerializeRstStream(rst_stream));
2087 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2088 frame_.reset(framer_->SerializeSettings(settings));
2090 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2091 frame_.reset(framer_->SerializePing(ping));
2093 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2094 frame_.reset(framer_->SerializeGoAway(goaway));
2096 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2097 frame_.reset(framer_->SerializeHeaders(headers));
2099 virtual void VisitWindowUpdate(
2100 const SpdyWindowUpdateIR& window_update) OVERRIDE {
2101 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2103 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2104 frame_.reset(framer_->SerializeBlocked(blocked));
2106 virtual void VisitPushPromise(
2107 const SpdyPushPromiseIR& push_promise) OVERRIDE {
2108 frame_.reset(framer_->SerializePushPromise(push_promise));
2111 private:
2112 SpdyFramer* framer_;
2113 scoped_ptr<SpdySerializedFrame> frame_;
2116 } // namespace
2118 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2119 FrameSerializationVisitor visitor(this);
2120 frame.Visit(&visitor);
2121 return visitor.ReleaseSerializedFrame();
2124 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2125 const size_t uncompressed_length =
2126 GetSerializedLength(protocol_version(), &headers);
2127 if (!enable_compression_) {
2128 return uncompressed_length;
2130 z_stream* compressor = GetHeaderCompressor();
2131 // Since we'll be performing lots of flushes when compressing the data,
2132 // zlib's lower bounds may be insufficient.
2133 return 2 * deflateBound(compressor, uncompressed_length);
2136 // The following compression setting are based on Brian Olson's analysis. See
2137 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2138 // for more details.
2139 #if defined(USE_SYSTEM_ZLIB)
2140 // System zlib is not expected to have workaround for http://crbug.com/139744,
2141 // so disable compression in that case.
2142 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2143 static const int kCompressorLevel = 0;
2144 #else // !defined(USE_SYSTEM_ZLIB)
2145 static const int kCompressorLevel = 9;
2146 #endif // !defined(USE_SYSTEM_ZLIB)
2147 static const int kCompressorWindowSizeInBits = 11;
2148 static const int kCompressorMemLevel = 1;
2150 z_stream* SpdyFramer::GetHeaderCompressor() {
2151 if (header_compressor_.get())
2152 return header_compressor_.get(); // Already initialized.
2154 header_compressor_.reset(new z_stream);
2155 memset(header_compressor_.get(), 0, sizeof(z_stream));
2157 int success = deflateInit2(header_compressor_.get(),
2158 kCompressorLevel,
2159 Z_DEFLATED,
2160 kCompressorWindowSizeInBits,
2161 kCompressorMemLevel,
2162 Z_DEFAULT_STRATEGY);
2163 if (success == Z_OK) {
2164 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2165 : kV3Dictionary;
2166 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2167 : kV3DictionarySize;
2168 success = deflateSetDictionary(header_compressor_.get(),
2169 reinterpret_cast<const Bytef*>(dictionary),
2170 dictionary_size);
2172 if (success != Z_OK) {
2173 LOG(WARNING) << "deflateSetDictionary failure: " << success;
2174 header_compressor_.reset(NULL);
2175 return NULL;
2177 return header_compressor_.get();
2180 z_stream* SpdyFramer::GetHeaderDecompressor() {
2181 if (header_decompressor_.get())
2182 return header_decompressor_.get(); // Already initialized.
2184 header_decompressor_.reset(new z_stream);
2185 memset(header_decompressor_.get(), 0, sizeof(z_stream));
2187 int success = inflateInit(header_decompressor_.get());
2188 if (success != Z_OK) {
2189 LOG(WARNING) << "inflateInit failure: " << success;
2190 header_decompressor_.reset(NULL);
2191 return NULL;
2193 return header_decompressor_.get();
2196 // Incrementally decompress the control frame's header block, feeding the
2197 // result to the visitor in chunks. Continue this until the visitor
2198 // indicates that it cannot process any more data, or (more commonly) we
2199 // run out of data to deliver.
2200 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
2201 SpdyStreamId stream_id,
2202 const char* data,
2203 size_t len) {
2204 // Get a decompressor or set error.
2205 z_stream* decomp = GetHeaderDecompressor();
2206 if (decomp == NULL) {
2207 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
2208 set_error(SPDY_DECOMPRESS_FAILURE);
2209 return false;
2212 bool processed_successfully = true;
2213 char buffer[kHeaderDataChunkMaxSize];
2215 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
2216 decomp->avail_in = len;
2217 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
2218 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
2219 // reached this method successfully, stream_id should be nonzero.
2220 DCHECK_LT(0u, stream_id);
2221 while (decomp->avail_in > 0 && processed_successfully) {
2222 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
2223 decomp->avail_out = arraysize(buffer);
2225 int rv = inflate(decomp, Z_SYNC_FLUSH);
2226 if (rv == Z_NEED_DICT) {
2227 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2228 : kV3Dictionary;
2229 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2230 : kV3DictionarySize;
2231 const DictionaryIds& ids = g_dictionary_ids.Get();
2232 const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
2233 : ids.v3_dictionary_id;
2234 // Need to try again with the right dictionary.
2235 if (decomp->adler == dictionary_id) {
2236 rv = inflateSetDictionary(decomp,
2237 reinterpret_cast<const Bytef*>(dictionary),
2238 dictionary_size);
2239 if (rv == Z_OK)
2240 rv = inflate(decomp, Z_SYNC_FLUSH);
2244 // Inflate will generate a Z_BUF_ERROR if it runs out of input
2245 // without producing any output. The input is consumed and
2246 // buffered internally by zlib so we can detect this condition by
2247 // checking if avail_in is 0 after the call to inflate.
2248 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
2249 if ((rv == Z_OK) || input_exhausted) {
2250 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
2251 if (decompressed_len > 0) {
2252 processed_successfully = visitor_->OnControlFrameHeaderData(
2253 stream_id, buffer, decompressed_len);
2255 if (!processed_successfully) {
2256 // Assume that the problem was the header block was too large for the
2257 // visitor.
2258 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2260 } else {
2261 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
2262 set_error(SPDY_DECOMPRESS_FAILURE);
2263 processed_successfully = false;
2266 return processed_successfully;
2269 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
2270 SpdyStreamId stream_id, const char* data, size_t len) {
2271 bool read_successfully = true;
2272 while (read_successfully && len > 0) {
2273 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
2274 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
2275 bytes_to_deliver);
2276 data += bytes_to_deliver;
2277 len -= bytes_to_deliver;
2278 if (!read_successfully) {
2279 // Assume that the problem was the header block was too large for the
2280 // visitor.
2281 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2284 return read_successfully;
2287 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
2288 SpdyFrameBuilder* builder,
2289 const SpdyNameValueBlock& name_value_block) const {
2290 // Serialize number of headers.
2291 if (protocol_version() < 3) {
2292 builder->WriteUInt16(name_value_block.size());
2293 } else {
2294 builder->WriteUInt32(name_value_block.size());
2297 // Serialize each header.
2298 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
2299 it != name_value_block.end();
2300 ++it) {
2301 if (protocol_version() < 3) {
2302 builder->WriteString(it->first);
2303 builder->WriteString(it->second);
2304 } else {
2305 builder->WriteStringPiece32(it->first);
2306 builder->WriteStringPiece32(it->second);
2311 void SpdyFramer::SerializeNameValueBlock(
2312 SpdyFrameBuilder* builder,
2313 const SpdyFrameWithNameValueBlockIR& frame) {
2314 if (!enable_compression_) {
2315 return SerializeNameValueBlockWithoutCompression(builder,
2316 frame.name_value_block());
2319 // First build an uncompressed version to be fed into the compressor.
2320 const size_t uncompressed_len = GetSerializedLength(
2321 protocol_version(), &(frame.name_value_block()));
2322 SpdyFrameBuilder uncompressed_builder(uncompressed_len);
2323 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
2324 frame.name_value_block());
2325 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
2327 z_stream* compressor = GetHeaderCompressor();
2328 if (!compressor) {
2329 LOG(DFATAL) << "Could not obtain compressor.";
2330 return;
2333 base::StatsCounter compressed_frames("spdy.CompressedFrames");
2334 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
2335 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
2337 // Create an output frame.
2338 // Since we'll be performing lots of flushes when compressing the data,
2339 // zlib's lower bounds may be insufficient.
2341 // TODO(akalin): Avoid the duplicate calculation with
2342 // GetSerializedLength(const SpdyHeaderBlock&).
2343 const int compressed_max_size =
2344 2 * deflateBound(compressor, uncompressed_len);
2346 // TODO(phajdan.jr): Clean up after we no longer need
2347 // to workaround http://crbug.com/139744.
2348 #if defined(USE_SYSTEM_ZLIB)
2349 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
2350 compressor->avail_in = uncompressed_len;
2351 #endif // defined(USE_SYSTEM_ZLIB)
2352 compressor->next_out = reinterpret_cast<Bytef*>(
2353 builder->GetWritableBuffer(compressed_max_size));
2354 compressor->avail_out = compressed_max_size;
2356 // TODO(phajdan.jr): Clean up after we no longer need
2357 // to workaround http://crbug.com/139744.
2358 #if defined(USE_SYSTEM_ZLIB)
2359 int rv = deflate(compressor, Z_SYNC_FLUSH);
2360 if (rv != Z_OK) { // How can we know that it compressed everything?
2361 // This shouldn't happen, right?
2362 LOG(WARNING) << "deflate failure: " << rv;
2363 // TODO(akalin): Upstream this return.
2364 return;
2366 #else
2367 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
2368 #endif // defined(USE_SYSTEM_ZLIB)
2370 int compressed_size = compressed_max_size - compressor->avail_out;
2371 builder->Seek(compressed_size);
2372 builder->RewriteLength(*this);
2374 pre_compress_bytes.Add(uncompressed_len);
2375 post_compress_bytes.Add(compressed_size);
2377 compressed_frames.Increment();
2380 } // namespace net