rAc - revert invalid suggestions to edit mode
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blobf2ec0f3aad9414559a93827654add82b7fc3a4f8
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.
236 if (spdy_version_ < 4) {
237 // Calculated as:
238 // control frame header + 4 (id)
239 return GetControlFrameHeaderSize() + 4;
240 } else {
241 // Calculated as:
242 // control frame header + 8 (id)
243 return GetControlFrameHeaderSize() + 8;
247 size_t SpdyFramer::GetGoAwayMinimumSize() const {
248 // Size, in bytes, of this GOAWAY frame. Calculated as:
249 // 1. Control frame header size
250 size_t size = GetControlFrameHeaderSize();
252 // 2. Last good stream id (4 bytes)
253 size += 4;
255 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
256 if (protocol_version() >= 3) {
257 size += 4;
260 return size;
263 size_t SpdyFramer::GetHeadersMinimumSize() const {
264 // Size, in bytes, of a HEADERS frame not including the variable-length
265 // name-value block.
266 size_t size = GetControlFrameHeaderSize();
267 if (spdy_version_ < 4) {
268 // Calculated as:
269 // control frame header + 4 (stream IDs)
270 size += 4;
273 // In SPDY 2, there were 2 unused bytes before payload.
274 if (protocol_version() < 3) {
275 size += 2;
278 return size;
281 size_t SpdyFramer::GetWindowUpdateSize() const {
282 // Size, in bytes, of a WINDOW_UPDATE frame.
283 if (spdy_version_ < 4) {
284 // Calculated as:
285 // control frame header + 4 (stream id) + 4 (delta)
286 return GetControlFrameHeaderSize() + 8;
287 } else {
288 // Calculated as:
289 // frame prefix + 4 (delta)
290 return GetControlFrameHeaderSize() + 4;
294 size_t SpdyFramer::GetBlockedSize() const {
295 DCHECK_LE(4, protocol_version());
296 // Size, in bytes, of a BLOCKED frame.
297 // The BLOCKED frame has no payload beyond the control frame header.
298 return GetControlFrameHeaderSize();
301 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
302 DCHECK_LE(4, protocol_version());
303 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
304 // Calculated as frame prefix + 4 (promised stream id).
305 return GetControlFrameHeaderSize() + 4;
308 size_t SpdyFramer::GetFrameMinimumSize() const {
309 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
312 size_t SpdyFramer::GetFrameMaximumSize() const {
313 return (protocol_version() < 4) ? 0xffffff : 0xffff;
316 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
317 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
320 const char* SpdyFramer::StateToString(int state) {
321 switch (state) {
322 case SPDY_ERROR:
323 return "ERROR";
324 case SPDY_AUTO_RESET:
325 return "AUTO_RESET";
326 case SPDY_RESET:
327 return "RESET";
328 case SPDY_READING_COMMON_HEADER:
329 return "READING_COMMON_HEADER";
330 case SPDY_CONTROL_FRAME_PAYLOAD:
331 return "CONTROL_FRAME_PAYLOAD";
332 case SPDY_IGNORE_REMAINING_PAYLOAD:
333 return "IGNORE_REMAINING_PAYLOAD";
334 case SPDY_FORWARD_STREAM_FRAME:
335 return "FORWARD_STREAM_FRAME";
336 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
337 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
338 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
339 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
340 case SPDY_GOAWAY_FRAME_PAYLOAD:
341 return "SPDY_GOAWAY_FRAME_PAYLOAD";
342 case SPDY_RST_STREAM_FRAME_PAYLOAD:
343 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
344 case SPDY_SETTINGS_FRAME_PAYLOAD:
345 return "SPDY_SETTINGS_FRAME_PAYLOAD";
347 return "UNKNOWN_STATE";
350 void SpdyFramer::set_error(SpdyError error) {
351 DCHECK(visitor_);
352 error_code_ = error;
353 CHANGE_STATE(SPDY_ERROR);
354 visitor_->OnError(this);
357 const char* SpdyFramer::ErrorCodeToString(int error_code) {
358 switch (error_code) {
359 case SPDY_NO_ERROR:
360 return "NO_ERROR";
361 case SPDY_INVALID_CONTROL_FRAME:
362 return "INVALID_CONTROL_FRAME";
363 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
364 return "CONTROL_PAYLOAD_TOO_LARGE";
365 case SPDY_ZLIB_INIT_FAILURE:
366 return "ZLIB_INIT_FAILURE";
367 case SPDY_UNSUPPORTED_VERSION:
368 return "UNSUPPORTED_VERSION";
369 case SPDY_DECOMPRESS_FAILURE:
370 return "DECOMPRESS_FAILURE";
371 case SPDY_COMPRESS_FAILURE:
372 return "COMPRESS_FAILURE";
373 case SPDY_INVALID_DATA_FRAME_FLAGS:
374 return "SPDY_INVALID_DATA_FRAME_FLAGS";
375 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
376 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
378 return "UNKNOWN_ERROR";
381 const char* SpdyFramer::StatusCodeToString(int status_code) {
382 switch (status_code) {
383 case RST_STREAM_INVALID:
384 return "INVALID";
385 case RST_STREAM_PROTOCOL_ERROR:
386 return "PROTOCOL_ERROR";
387 case RST_STREAM_INVALID_STREAM:
388 return "INVALID_STREAM";
389 case RST_STREAM_REFUSED_STREAM:
390 return "REFUSED_STREAM";
391 case RST_STREAM_UNSUPPORTED_VERSION:
392 return "UNSUPPORTED_VERSION";
393 case RST_STREAM_CANCEL:
394 return "CANCEL";
395 case RST_STREAM_INTERNAL_ERROR:
396 return "INTERNAL_ERROR";
397 case RST_STREAM_FLOW_CONTROL_ERROR:
398 return "FLOW_CONTROL_ERROR";
399 case RST_STREAM_STREAM_IN_USE:
400 return "STREAM_IN_USE";
401 case RST_STREAM_STREAM_ALREADY_CLOSED:
402 return "STREAM_ALREADY_CLOSED";
403 case RST_STREAM_INVALID_CREDENTIALS:
404 return "INVALID_CREDENTIALS";
405 case RST_STREAM_FRAME_TOO_LARGE:
406 return "FRAME_TOO_LARGE";
408 return "UNKNOWN_STATUS";
411 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
412 switch (type) {
413 case DATA:
414 return "DATA";
415 case SYN_STREAM:
416 return "SYN_STREAM";
417 case SYN_REPLY:
418 return "SYN_REPLY";
419 case RST_STREAM:
420 return "RST_STREAM";
421 case SETTINGS:
422 return "SETTINGS";
423 case NOOP:
424 return "NOOP";
425 case PING:
426 return "PING";
427 case GOAWAY:
428 return "GOAWAY";
429 case HEADERS:
430 return "HEADERS";
431 case WINDOW_UPDATE:
432 return "WINDOW_UPDATE";
433 case CREDENTIAL:
434 return "CREDENTIAL";
435 case BLOCKED:
436 return "BLOCKED";
437 case PUSH_PROMISE:
438 return "PUSH_PROMISE";
440 return "UNKNOWN_CONTROL_TYPE";
443 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
444 DCHECK(visitor_);
445 DCHECK(data);
447 size_t original_len = len;
448 do {
449 previous_state_ = state_;
450 switch (state_) {
451 case SPDY_ERROR:
452 goto bottom;
454 case SPDY_AUTO_RESET:
455 case SPDY_RESET:
456 Reset();
457 if (len > 0) {
458 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
460 break;
462 case SPDY_READING_COMMON_HEADER: {
463 size_t bytes_read = ProcessCommonHeader(data, len);
464 len -= bytes_read;
465 data += bytes_read;
466 break;
469 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
470 // Control frames that contain header blocks
471 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE)
472 // take a different path through the state machine - they
473 // will go:
474 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
475 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
477 // SETTINGS frames take a slightly modified route:
478 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
479 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
481 // All other control frames will use the alternate route directly to
482 // SPDY_CONTROL_FRAME_PAYLOAD
483 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
484 len -= bytes_read;
485 data += bytes_read;
486 break;
489 case SPDY_SETTINGS_FRAME_PAYLOAD: {
490 int bytes_read = ProcessSettingsFramePayload(data, len);
491 len -= bytes_read;
492 data += bytes_read;
493 break;
496 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
497 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
498 len -= bytes_read;
499 data += bytes_read;
500 break;
503 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
504 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
505 len -= bytes_read;
506 data += bytes_read;
507 break;
510 case SPDY_GOAWAY_FRAME_PAYLOAD: {
511 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
512 len -= bytes_read;
513 data += bytes_read;
514 break;
517 case SPDY_CONTROL_FRAME_PAYLOAD: {
518 size_t bytes_read = ProcessControlFramePayload(data, len);
519 len -= bytes_read;
520 data += bytes_read;
521 break;
524 case SPDY_IGNORE_REMAINING_PAYLOAD:
525 // control frame has too-large payload
526 // intentional fallthrough
527 case SPDY_FORWARD_STREAM_FRAME: {
528 size_t bytes_read = ProcessDataFramePayload(data, len);
529 len -= bytes_read;
530 data += bytes_read;
531 break;
533 default:
534 LOG(DFATAL) << "Invalid value for " << display_protocol_
535 << " framer state: " << state_;
536 // This ensures that we don't infinite-loop if state_ gets an
537 // invalid value somehow, such as due to a SpdyFramer getting deleted
538 // from a callback it calls.
539 goto bottom;
541 } while (state_ != previous_state_);
542 bottom:
543 DCHECK(len == 0 || state_ == SPDY_ERROR);
544 if (current_frame_buffer_length_ == 0 &&
545 remaining_data_length_ == 0 &&
546 remaining_control_header_ == 0) {
547 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
548 << "State: " << StateToString(state_);
551 return original_len - len;
554 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
555 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
556 // state.
557 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
559 size_t original_len = len;
561 // Update current frame buffer as needed.
562 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
563 size_t bytes_desired =
564 GetControlFrameHeaderSize() - current_frame_buffer_length_;
565 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
568 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
569 // Not enough information to do anything meaningful.
570 return original_len - len;
573 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
574 // when processing DATA frames below.
575 scoped_ptr<SpdyFrameReader> reader(
576 new SpdyFrameReader(current_frame_buffer_.get(),
577 current_frame_buffer_length_));
579 uint16 version = 0;
580 bool is_control_frame = false;
582 uint16 control_frame_type_field = DATA;
583 // ProcessControlFrameHeader() will set current_frame_type_ to the
584 // correct value if this is a valid control frame.
585 current_frame_type_ = DATA;
586 if (protocol_version() < 4) {
587 bool successful_read = reader->ReadUInt16(&version);
588 DCHECK(successful_read);
589 is_control_frame = (version & kControlFlagMask) != 0;
590 version &= ~kControlFlagMask; // Only valid for control frames.
592 if (is_control_frame) {
593 // We check control_frame_type_field's validity in
594 // ProcessControlFrameHeader().
595 successful_read = reader->ReadUInt16(&control_frame_type_field);
596 } else {
597 reader->Rewind();
598 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
600 DCHECK(successful_read);
602 successful_read = reader->ReadUInt8(&current_frame_flags_);
603 DCHECK(successful_read);
605 uint32 length_field = 0;
606 successful_read = reader->ReadUInt24(&length_field);
607 DCHECK(successful_read);
608 remaining_data_length_ = length_field;
609 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
610 } else {
611 version = protocol_version();
612 uint16 length_field = 0;
613 bool successful_read = reader->ReadUInt16(&length_field);
614 DCHECK(successful_read);
615 current_frame_length_ = length_field;
617 uint8 control_frame_type_field_uint8 = DATA;
618 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
619 DCHECK(successful_read);
620 // We check control_frame_type_field's validity in
621 // ProcessControlFrameHeader().
622 control_frame_type_field = control_frame_type_field_uint8;
623 is_control_frame = (control_frame_type_field != DATA);
625 successful_read = reader->ReadUInt8(&current_frame_flags_);
626 DCHECK(successful_read);
628 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
629 DCHECK(successful_read);
631 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
633 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
634 : GetDataFrameMinimumSize(),
635 reader->GetBytesConsumed());
636 DCHECK_EQ(current_frame_length_,
637 remaining_data_length_ + reader->GetBytesConsumed());
639 // This is just a sanity check for help debugging early frame errors.
640 if (remaining_data_length_ > 1000000u) {
641 // The strncmp for 5 is safe because we only hit this point if we
642 // have kMinCommonHeader (8) bytes
643 if (!syn_frame_processed_ &&
644 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
645 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
646 << " request";
647 probable_http_response_ = true;
648 } else {
649 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
650 << " session is likely corrupt.";
654 // if we're here, then we have the common header all received.
655 if (!is_control_frame) {
656 if (current_frame_flags_ & ~DATA_FLAG_FIN) {
657 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
658 } else {
659 visitor_->OnDataFrameHeader(current_frame_stream_id_,
660 remaining_data_length_,
661 current_frame_flags_ & DATA_FLAG_FIN);
662 if (remaining_data_length_ > 0) {
663 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
664 } else {
665 // Empty data frame.
666 if (current_frame_flags_ & DATA_FLAG_FIN) {
667 visitor_->OnStreamFrameData(
668 current_frame_stream_id_, NULL, 0, true);
670 CHANGE_STATE(SPDY_AUTO_RESET);
673 } else if (version != spdy_version_) {
674 // We check version before we check validity: version can never be
675 // 'invalid', it can only be unsupported.
676 DVLOG(1) << "Unsupported SPDY version " << version
677 << " (expected " << spdy_version_ << ")";
678 set_error(SPDY_UNSUPPORTED_VERSION);
679 } else {
680 ProcessControlFrameHeader(control_frame_type_field);
683 return original_len - len;
686 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
687 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
688 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
690 if (control_frame_type_field < FIRST_CONTROL_TYPE ||
691 control_frame_type_field > LAST_CONTROL_TYPE) {
692 set_error(SPDY_INVALID_CONTROL_FRAME);
693 return;
696 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
698 if (current_frame_type_ == NOOP) {
699 DVLOG(1) << "NOOP control frame found. Ignoring.";
700 CHANGE_STATE(SPDY_AUTO_RESET);
701 return;
704 if (current_frame_type_ == CREDENTIAL) {
705 DCHECK_EQ(3, protocol_version());
706 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
707 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
708 return;
711 // Do some sanity checking on the control frame sizes and flags.
712 switch (current_frame_type_) {
713 case SYN_STREAM:
714 DCHECK_GT(4, spdy_version_);
715 if (current_frame_length_ < GetSynStreamMinimumSize()) {
716 set_error(SPDY_INVALID_CONTROL_FRAME);
717 } else if (current_frame_flags_ &
718 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
719 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
721 break;
722 case SYN_REPLY:
723 if (current_frame_length_ < GetSynReplyMinimumSize()) {
724 set_error(SPDY_INVALID_CONTROL_FRAME);
725 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
726 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
728 break;
729 case RST_STREAM:
730 // For SPDY versions < 4, the header has a fixed length.
731 // For SPDY version 4 and up, the RST_STREAM frame may include optional
732 // opaque data, so we only have a lower limit on the frame size.
733 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
734 protocol_version() < 4) ||
735 (current_frame_length_ < GetRstStreamMinimumSize() &&
736 protocol_version() >= 4)) {
737 set_error(SPDY_INVALID_CONTROL_FRAME);
738 } else if (current_frame_flags_ != 0) {
739 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
741 break;
742 case SETTINGS:
743 // Make sure that we have an integral number of 8-byte key/value pairs,
744 // plus a 4-byte length field.
745 if (current_frame_length_ < GetSettingsMinimumSize() ||
746 (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
747 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
748 << current_frame_length_;
749 set_error(SPDY_INVALID_CONTROL_FRAME);
750 } else if (current_frame_flags_ &
751 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
752 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
754 break;
755 case PING:
756 if (current_frame_length_ != GetPingSize()) {
757 set_error(SPDY_INVALID_CONTROL_FRAME);
758 } else if ((protocol_version() < 4 && current_frame_flags_ != 0) ||
759 (current_frame_flags_ & ~PING_FLAG_ACK)) {
760 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
762 break;
763 case GOAWAY:
765 // For SPDY version < 4, there are only mandatory fields and the header
766 // has a fixed length. For SPDY version >= 4, optional opaque data may
767 // be appended to the GOAWAY frame, thus there is only a minimal length
768 // restriction.
769 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
770 protocol_version() < 4) ||
771 (current_frame_length_ < GetGoAwayMinimumSize() &&
772 protocol_version() >= 4)) {
773 set_error(SPDY_INVALID_CONTROL_FRAME);
774 } else if (current_frame_flags_ != 0) {
775 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
777 break;
779 case HEADERS:
781 size_t min_size = GetHeadersMinimumSize();
782 if (spdy_version_ > 3 &&
783 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
784 min_size += 4;
786 if (current_frame_length_ < min_size) {
787 set_error(SPDY_INVALID_CONTROL_FRAME);
788 } else if (spdy_version_ < 4 &&
789 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
790 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
791 } else if (spdy_version_ > 3 && current_frame_flags_ &
792 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY)) {
793 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
796 break;
797 case WINDOW_UPDATE:
798 if (current_frame_length_ != GetWindowUpdateSize()) {
799 set_error(SPDY_INVALID_CONTROL_FRAME);
800 } else if (current_frame_flags_ != 0) {
801 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
803 break;
804 case BLOCKED:
805 if (current_frame_length_ != GetBlockedSize()) {
806 set_error(SPDY_INVALID_CONTROL_FRAME);
807 } else if (current_frame_flags_ != 0) {
808 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
810 break;
811 case PUSH_PROMISE:
812 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
813 set_error(SPDY_INVALID_CONTROL_FRAME);
814 } else if (current_frame_flags_ != 0) {
815 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
817 break;
818 default:
819 LOG(WARNING) << "Valid " << display_protocol_
820 << " control frame with unhandled type: "
821 << current_frame_type_;
822 // This branch should be unreachable because of the frame type bounds
823 // check above. However, we DLOG(FATAL) here in an effort to painfully
824 // club the head of the developer who failed to keep this file in sync
825 // with spdy_protocol.h.
826 DLOG(FATAL);
827 set_error(SPDY_INVALID_CONTROL_FRAME);
828 break;
831 if (state_ == SPDY_ERROR) {
832 return;
835 if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
836 DLOG(WARNING) << "Received control frame with way too big of a payload: "
837 << current_frame_length_;
838 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
839 return;
842 if (current_frame_type_ == GOAWAY) {
843 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
844 return;
847 if (current_frame_type_ == RST_STREAM) {
848 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
849 return;
852 // Determine the frame size without variable-length data.
853 int32 frame_size_without_variable_data;
854 switch (current_frame_type_) {
855 case SYN_STREAM:
856 syn_frame_processed_ = true;
857 frame_size_without_variable_data = GetSynStreamMinimumSize();
858 break;
859 case SYN_REPLY:
860 syn_frame_processed_ = true;
861 frame_size_without_variable_data = GetSynReplyMinimumSize();
862 break;
863 case SETTINGS:
864 frame_size_without_variable_data = GetSettingsMinimumSize();
865 break;
866 case HEADERS:
867 frame_size_without_variable_data = GetHeadersMinimumSize();
868 if (spdy_version_ > 3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
869 frame_size_without_variable_data += 4; // priority
871 break;
872 case PUSH_PROMISE:
873 frame_size_without_variable_data = GetPushPromiseMinimumSize();
874 break;
875 default:
876 frame_size_without_variable_data = -1;
877 break;
880 if ((frame_size_without_variable_data == -1) &&
881 (current_frame_length_ > kControlFrameBufferSize)) {
882 // We should already be in an error state. Double-check.
883 DCHECK_EQ(SPDY_ERROR, state_);
884 if (state_ != SPDY_ERROR) {
885 LOG(DFATAL) << display_protocol_
886 << " control frame buffer too small for fixed-length frame.";
887 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
889 return;
892 if (frame_size_without_variable_data > 0) {
893 // We have a control frame with a header block. We need to parse the
894 // remainder of the control frame's header before we can parse the header
895 // block. The start of the header block varies with the control type.
896 DCHECK_GE(frame_size_without_variable_data,
897 static_cast<int32>(current_frame_buffer_length_));
898 remaining_control_header_ = frame_size_without_variable_data -
899 current_frame_buffer_length_;
901 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
902 return;
905 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
908 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
909 size_t max_bytes) {
910 size_t bytes_to_read = std::min(*len, max_bytes);
911 if (bytes_to_read > 0) {
912 DCHECK_GE(kControlFrameBufferSize,
913 current_frame_buffer_length_ + bytes_to_read);
914 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
915 *data,
916 bytes_to_read);
917 current_frame_buffer_length_ += bytes_to_read;
918 *data += bytes_to_read;
919 *len -= bytes_to_read;
921 return bytes_to_read;
924 size_t SpdyFramer::GetSerializedLength(const int spdy_version,
925 const SpdyHeaderBlock* headers) {
926 const size_t num_name_value_pairs_size
927 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
928 const size_t length_of_name_size = num_name_value_pairs_size;
929 const size_t length_of_value_size = num_name_value_pairs_size;
931 size_t total_length = num_name_value_pairs_size;
932 for (SpdyHeaderBlock::const_iterator it = headers->begin();
933 it != headers->end();
934 ++it) {
935 // We add space for the length of the name and the length of the value as
936 // well as the length of the name and the length of the value.
937 total_length += length_of_name_size + it->first.size() +
938 length_of_value_size + it->second.size();
940 return total_length;
943 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
944 const int spdy_version,
945 const SpdyHeaderBlock* headers) {
946 if (spdy_version < 3) {
947 frame->WriteUInt16(headers->size()); // Number of headers.
948 } else {
949 frame->WriteUInt32(headers->size()); // Number of headers.
951 SpdyHeaderBlock::const_iterator it;
952 for (it = headers->begin(); it != headers->end(); ++it) {
953 if (spdy_version < 3) {
954 frame->WriteString(it->first);
955 frame->WriteString(it->second);
956 } else {
957 frame->WriteStringPiece32(it->first);
958 frame->WriteStringPiece32(it->second);
963 // TODO(phajdan.jr): Clean up after we no longer need
964 // to workaround http://crbug.com/139744.
965 #if !defined(USE_SYSTEM_ZLIB)
967 // These constants are used by zlib to differentiate between normal data and
968 // cookie data. Cookie data is handled specially by zlib when compressing.
969 enum ZDataClass {
970 // kZStandardData is compressed normally, save that it will never match
971 // against any other class of data in the window.
972 kZStandardData = Z_CLASS_STANDARD,
973 // kZCookieData is compressed in its own Huffman blocks and only matches in
974 // its entirety and only against other kZCookieData blocks. Any matches must
975 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
976 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
977 // prefix matches.
978 kZCookieData = Z_CLASS_COOKIE,
979 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
980 // against the window.
981 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
984 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
985 // needed when switching between classes of data.
986 static void WriteZ(const base::StringPiece& data,
987 ZDataClass clas,
988 z_stream* out) {
989 int rv;
991 // If we are switching from standard to non-standard data then we need to end
992 // the current Huffman context to avoid it leaking between them.
993 if (out->clas == kZStandardData &&
994 clas != kZStandardData) {
995 out->avail_in = 0;
996 rv = deflate(out, Z_PARTIAL_FLUSH);
997 DCHECK_EQ(Z_OK, rv);
998 DCHECK_EQ(0u, out->avail_in);
999 DCHECK_LT(0u, out->avail_out);
1002 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1003 out->avail_in = data.size();
1004 out->clas = clas;
1005 if (clas == kZStandardData) {
1006 rv = deflate(out, Z_NO_FLUSH);
1007 } else {
1008 rv = deflate(out, Z_PARTIAL_FLUSH);
1010 if (!data.empty()) {
1011 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1012 DCHECK_EQ(Z_OK, rv);
1014 DCHECK_EQ(0u, out->avail_in);
1015 DCHECK_LT(0u, out->avail_out);
1018 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1019 static void WriteLengthZ(size_t n,
1020 unsigned length,
1021 ZDataClass clas,
1022 z_stream* out) {
1023 char buf[4];
1024 DCHECK_LE(length, sizeof(buf));
1025 for (unsigned i = 1; i <= length; i++) {
1026 buf[length - i] = n;
1027 n >>= 8;
1029 WriteZ(base::StringPiece(buf, length), clas, out);
1032 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1033 // manner that resists the length of the compressed data from compromising
1034 // cookie data.
1035 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1036 z_stream* z) const {
1037 unsigned length_length = 4;
1038 if (spdy_version_ < 3)
1039 length_length = 2;
1041 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1043 std::map<std::string, std::string>::const_iterator it;
1044 for (it = headers->begin(); it != headers->end(); ++it) {
1045 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1046 WriteZ(it->first, kZStandardData, z);
1048 if (it->first == "cookie") {
1049 // We require the cookie values (save for the last) to end with a
1050 // semicolon and (save for the first) to start with a space. This is
1051 // typically the format that we are given them in but we reserialize them
1052 // to be sure.
1054 std::vector<base::StringPiece> cookie_values;
1055 size_t cookie_length = 0;
1056 base::StringPiece cookie_data(it->second);
1058 for (;;) {
1059 while (!cookie_data.empty() &&
1060 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1061 cookie_data.remove_prefix(1);
1063 if (cookie_data.empty())
1064 break;
1066 size_t i;
1067 for (i = 0; i < cookie_data.size(); i++) {
1068 if (cookie_data[i] == ';')
1069 break;
1071 if (i < cookie_data.size()) {
1072 cookie_values.push_back(cookie_data.substr(0, i));
1073 cookie_length += i + 2 /* semicolon and space */;
1074 cookie_data.remove_prefix(i + 1);
1075 } else {
1076 cookie_values.push_back(cookie_data);
1077 cookie_length += cookie_data.size();
1078 cookie_data.remove_prefix(i);
1082 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1083 for (size_t i = 0; i < cookie_values.size(); i++) {
1084 std::string cookie;
1085 // Since zlib will only back-reference complete cookies, a cookie that
1086 // is currently last (and so doesn't have a trailing semicolon) won't
1087 // match if it's later in a non-final position. The same is true of
1088 // the first cookie.
1089 if (i == 0 && cookie_values.size() == 1) {
1090 cookie = cookie_values[i].as_string();
1091 } else if (i == 0) {
1092 cookie = cookie_values[i].as_string() + ";";
1093 } else if (i < cookie_values.size() - 1) {
1094 cookie = " " + cookie_values[i].as_string() + ";";
1095 } else {
1096 cookie = " " + cookie_values[i].as_string();
1098 WriteZ(cookie, kZCookieData, z);
1100 } else if (it->first == "accept" ||
1101 it->first == "accept-charset" ||
1102 it->first == "accept-encoding" ||
1103 it->first == "accept-language" ||
1104 it->first == "host" ||
1105 it->first == "version" ||
1106 it->first == "method" ||
1107 it->first == "scheme" ||
1108 it->first == ":host" ||
1109 it->first == ":version" ||
1110 it->first == ":method" ||
1111 it->first == ":scheme" ||
1112 it->first == "user-agent") {
1113 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1114 WriteZ(it->second, kZStandardData, z);
1115 } else {
1116 // Non-whitelisted headers are Huffman compressed in their own block, but
1117 // don't match against the window.
1118 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1119 WriteZ(it->second, kZHuffmanOnlyData, z);
1123 z->avail_in = 0;
1124 int rv = deflate(z, Z_SYNC_FLUSH);
1125 DCHECK_EQ(Z_OK, rv);
1126 z->clas = kZStandardData;
1128 #endif // !defined(USE_SYSTEM_ZLIB)
1130 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1131 size_t len) {
1132 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1133 const size_t original_len = len;
1135 if (remaining_control_header_ > 0) {
1136 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1137 remaining_control_header_);
1138 remaining_control_header_ -= bytes_read;
1139 remaining_data_length_ -= bytes_read;
1142 if (remaining_control_header_ == 0) {
1143 SpdyFrameReader reader(current_frame_buffer_.get(),
1144 current_frame_buffer_length_);
1145 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1147 switch (current_frame_type_) {
1148 case SYN_STREAM:
1150 DCHECK_GT(4, spdy_version_);
1151 bool successful_read = true;
1152 if (spdy_version_ < 4) {
1153 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1154 DCHECK(successful_read);
1156 if (current_frame_stream_id_ == 0) {
1157 set_error(SPDY_INVALID_CONTROL_FRAME);
1158 break;
1161 SpdyStreamId associated_to_stream_id = kInvalidStream;
1162 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1163 DCHECK(successful_read);
1165 SpdyPriority priority = 0;
1166 successful_read = reader.ReadUInt8(&priority);
1167 DCHECK(successful_read);
1168 if (protocol_version() < 3) {
1169 priority = priority >> 6;
1170 } else {
1171 priority = priority >> 5;
1174 // Seek past unused byte; used to be credential slot in SPDY 3.
1175 reader.Seek(1);
1177 DCHECK(reader.IsDoneReading());
1178 if (debug_visitor_) {
1179 debug_visitor_->OnReceiveCompressedFrame(
1180 current_frame_stream_id_,
1181 current_frame_type_,
1182 current_frame_length_);
1184 visitor_->OnSynStream(
1185 current_frame_stream_id_,
1186 associated_to_stream_id,
1187 priority,
1188 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1189 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1191 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1192 break;
1193 case SETTINGS:
1194 visitor_->OnSettings(current_frame_flags_ &
1195 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1196 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1197 break;
1198 case SYN_REPLY:
1199 case HEADERS:
1200 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1202 if (spdy_version_ > 3) {
1203 DCHECK_EQ(HEADERS, current_frame_type_);
1205 bool successful_read = true;
1206 if (spdy_version_ < 4) {
1207 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1208 DCHECK(successful_read);
1210 if (current_frame_stream_id_ == 0) {
1211 set_error(SPDY_INVALID_CONTROL_FRAME);
1212 break;
1214 if (protocol_version() < 3) {
1215 // SPDY 2 had two unused bytes here. Seek past them.
1216 reader.Seek(2);
1218 const bool has_priority =
1219 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1220 uint32 priority = 0;
1221 if (protocol_version() > 3 && has_priority) {
1222 successful_read = reader.ReadUInt31(&priority);
1223 DCHECK(successful_read);
1225 DCHECK(reader.IsDoneReading());
1226 if (debug_visitor_) {
1227 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1228 SpdyFrameType reported_type = current_frame_type_;
1229 if (protocol_version() > 3 && has_priority) {
1230 reported_type = SYN_STREAM;
1232 debug_visitor_->OnReceiveCompressedFrame(
1233 current_frame_stream_id_,
1234 reported_type,
1235 current_frame_length_);
1237 if (current_frame_type_ == SYN_REPLY) {
1238 visitor_->OnSynReply(
1239 current_frame_stream_id_,
1240 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1241 } else if (spdy_version_ > 3 &&
1242 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1243 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1244 // can be made independent of wire changes.
1245 visitor_->OnSynStream(
1246 current_frame_stream_id_,
1247 0, // associated_to_stream_id
1248 priority,
1249 current_frame_flags_ & CONTROL_FLAG_FIN,
1250 false); // unidirectional
1251 } else {
1252 visitor_->OnHeaders(
1253 current_frame_stream_id_,
1254 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1257 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1258 break;
1259 case PUSH_PROMISE:
1261 DCHECK_LE(4, protocol_version());
1262 if (current_frame_stream_id_ == 0) {
1263 set_error(SPDY_INVALID_CONTROL_FRAME);
1264 break;
1266 SpdyStreamId promised_stream_id = kInvalidStream;
1267 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1268 DCHECK(successful_read);
1269 DCHECK(reader.IsDoneReading());
1270 if (promised_stream_id == 0) {
1271 set_error(SPDY_INVALID_CONTROL_FRAME);
1272 break;
1274 if (debug_visitor_) {
1275 debug_visitor_->OnReceiveCompressedFrame(
1276 current_frame_stream_id_,
1277 current_frame_type_,
1278 current_frame_length_);
1280 visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id);
1282 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1283 break;
1284 default:
1285 DCHECK(false);
1288 return original_len - len;
1291 // Does not buffer the control payload. Instead, either passes directly to the
1292 // visitor or decompresses and then passes directly to the visitor, via
1293 // IncrementallyDeliverControlFrameHeaderData() or
1294 // IncrementallyDecompressControlFrameHeaderData() respectively.
1295 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1296 size_t data_len) {
1297 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1299 bool processed_successfully = true;
1300 if (current_frame_type_ != SYN_STREAM &&
1301 current_frame_type_ != SYN_REPLY &&
1302 current_frame_type_ != HEADERS &&
1303 current_frame_type_ != PUSH_PROMISE) {
1304 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1306 size_t process_bytes = std::min(data_len, remaining_data_length_);
1307 if (process_bytes > 0) {
1308 if (enable_compression_) {
1309 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1310 current_frame_stream_id_, data, process_bytes);
1311 } else {
1312 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1313 current_frame_stream_id_, data, process_bytes);
1316 remaining_data_length_ -= process_bytes;
1319 // Handle the case that there is no futher data in this frame.
1320 if (remaining_data_length_ == 0 && processed_successfully) {
1321 // The complete header block has been delivered. We send a zero-length
1322 // OnControlFrameHeaderData() to indicate this.
1323 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1325 // If this is a FIN, tell the caller.
1326 if (current_frame_flags_ & CONTROL_FLAG_FIN) {
1327 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1330 CHANGE_STATE(SPDY_AUTO_RESET);
1333 // Handle error.
1334 if (!processed_successfully) {
1335 return data_len;
1338 // Return amount processed.
1339 return process_bytes;
1342 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1343 size_t data_len) {
1344 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1345 DCHECK_EQ(SETTINGS, current_frame_type_);
1346 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1347 size_t processed_bytes = 0;
1349 // Loop over our incoming data.
1350 while (unprocessed_bytes > 0) {
1351 // Process up to one setting at a time.
1352 size_t processing = std::min(
1353 unprocessed_bytes,
1354 static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
1356 // Check if we have a complete setting in our input.
1357 if (processing == 8) {
1358 // Parse the setting directly out of the input without buffering.
1359 if (!ProcessSetting(data + processed_bytes)) {
1360 set_error(SPDY_INVALID_CONTROL_FRAME);
1361 return processed_bytes;
1363 } else {
1364 // Continue updating settings_scratch_.setting_buf.
1365 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1366 data + processed_bytes,
1367 processing);
1368 settings_scratch_.setting_buf_len += processing;
1370 // Check if we have a complete setting buffered.
1371 if (settings_scratch_.setting_buf_len == 8) {
1372 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1373 set_error(SPDY_INVALID_CONTROL_FRAME);
1374 return processed_bytes;
1376 // Reset settings_scratch_.setting_buf for our next setting.
1377 settings_scratch_.setting_buf_len = 0;
1381 // Iterate.
1382 unprocessed_bytes -= processing;
1383 processed_bytes += processing;
1386 // Check if we're done handling this SETTINGS frame.
1387 remaining_data_length_ -= processed_bytes;
1388 if (remaining_data_length_ == 0) {
1389 CHANGE_STATE(SPDY_AUTO_RESET);
1392 return processed_bytes;
1395 bool SpdyFramer::ProcessSetting(const char* data) {
1396 // Extract fields.
1397 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1398 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1399 SettingsFlagsAndId id_and_flags =
1400 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
1401 uint8 flags = id_and_flags.flags();
1402 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1404 // Validate id.
1405 switch (id_and_flags.id()) {
1406 case SETTINGS_UPLOAD_BANDWIDTH:
1407 case SETTINGS_DOWNLOAD_BANDWIDTH:
1408 case SETTINGS_ROUND_TRIP_TIME:
1409 case SETTINGS_MAX_CONCURRENT_STREAMS:
1410 case SETTINGS_CURRENT_CWND:
1411 case SETTINGS_DOWNLOAD_RETRANS_RATE:
1412 case SETTINGS_INITIAL_WINDOW_SIZE:
1413 // Valid values.
1414 break;
1415 default:
1416 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
1417 return false;
1419 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
1421 // Detect duplciates.
1422 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
1423 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1424 << " in " << display_protocol_ << " SETTINGS frame "
1425 << "(last settikng id was "
1426 << settings_scratch_.last_setting_id << ").";
1427 return false;
1429 settings_scratch_.last_setting_id = id;
1431 // Validate flags.
1432 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1433 if ((flags & ~(kFlagsMask)) != 0) {
1434 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1435 << flags;
1436 return false;
1439 // Validation succeeded. Pass on to visitor.
1440 visitor_->OnSetting(id, flags, value);
1441 return true;
1444 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1445 size_t original_len = len;
1446 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1447 remaining_data_length_);
1448 remaining_data_length_ -= bytes_read;
1449 if (remaining_data_length_ == 0) {
1450 SpdyFrameReader reader(current_frame_buffer_.get(),
1451 current_frame_buffer_length_);
1452 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1454 // Use frame-specific handlers.
1455 switch (current_frame_type_) {
1456 case RST_STREAM:
1457 // TODO(jgraettinger): Leaving this here for future, saner patching.
1458 // RST_STREAM is separately handled by ProcessRstStreamFramePayload().
1459 NOTREACHED();
1460 if (false
1461 /*!FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1462 bool successful_read = true;
1463 if (spdy_version_ < 4) {
1464 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1465 DCHECK(successful_read);
1467 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1468 uint32 status_raw = status;
1469 successful_read = reader.ReadUInt32(&status_raw);
1470 DCHECK(successful_read);
1471 if (status_raw > RST_STREAM_INVALID &&
1472 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1473 status = static_cast<SpdyRstStreamStatus>(status_raw);
1474 } else {
1475 // TODO(hkhalil): Probably best to OnError here, depending on
1476 // our interpretation of the spec. Keeping with existing liberal
1477 // behavior for now.
1479 DCHECK(reader.IsDoneReading());
1480 visitor_->OnRstStream(current_frame_stream_id_, status);
1482 break;
1483 case PING: {
1484 SpdyPingId id = 0;
1485 bool is_ack =
1486 spdy_version_ >= 4 && (current_frame_flags_ & PING_FLAG_ACK);
1487 bool successful_read = true;
1488 if (spdy_version_ < 4) {
1489 uint32 id32 = 0;
1490 successful_read = reader.ReadUInt32(&id32);
1491 id = id32;
1492 } else {
1493 successful_read = reader.ReadUInt64(&id);
1495 DCHECK(successful_read);
1496 DCHECK(reader.IsDoneReading());
1497 visitor_->OnPing(id, is_ack);
1499 break;
1500 case WINDOW_UPDATE: {
1501 uint32 delta_window_size = 0;
1502 bool successful_read = true;
1503 if (spdy_version_ < 4) {
1504 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1505 DCHECK(successful_read);
1507 successful_read = reader.ReadUInt32(&delta_window_size);
1508 DCHECK(successful_read);
1509 DCHECK(reader.IsDoneReading());
1510 visitor_->OnWindowUpdate(current_frame_stream_id_,
1511 delta_window_size);
1513 break;
1514 case BLOCKED: {
1515 DCHECK_LE(4, protocol_version());
1516 DCHECK(reader.IsDoneReading());
1517 visitor_->OnBlocked(current_frame_stream_id_);
1519 break;
1520 default:
1521 // Unreachable.
1522 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1525 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1527 return original_len - len;
1530 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1531 if (len == 0) {
1532 return 0;
1534 // Clamp to the actual remaining payload.
1535 if (len > remaining_data_length_) {
1536 len = remaining_data_length_;
1538 size_t original_len = len;
1540 // Check if we had already read enough bytes to parse the GOAWAY header.
1541 const size_t header_size = GetGoAwayMinimumSize();
1542 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1543 bool already_parsed_header = (unread_header_bytes == 0);
1544 if (!already_parsed_header) {
1545 // Buffer the new GOAWAY header bytes we got.
1546 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1548 // Do we have enough to parse the constant size GOAWAY header?
1549 if (current_frame_buffer_length_ == header_size) {
1550 // Parse out the last good stream id.
1551 SpdyFrameReader reader(current_frame_buffer_.get(),
1552 current_frame_buffer_length_);
1553 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1554 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1555 DCHECK(successful_read);
1557 // In SPDYv3 and up, frames also specify a status code - parse it out.
1558 SpdyGoAwayStatus status = GOAWAY_OK;
1559 if (spdy_version_ >= 3) {
1560 uint32 status_raw = GOAWAY_OK;
1561 successful_read = reader.ReadUInt32(&status_raw);
1562 DCHECK(successful_read);
1563 // We've read an unsigned integer, so it's enough to only check
1564 // upper bound to ensure the value is in valid range.
1565 if (status_raw < GOAWAY_NUM_STATUS_CODES) {
1566 status = static_cast<SpdyGoAwayStatus>(status_raw);
1567 } else {
1568 // TODO(hkhalil): Probably best to OnError here, depending on
1569 // our interpretation of the spec. Keeping with existing liberal
1570 // behavior for now.
1571 DCHECK(false);
1574 // Finished parsing the GOAWAY header, call frame handler.
1575 visitor_->OnGoAway(current_frame_stream_id_, status);
1579 // Handle remaining data as opaque.
1580 bool processed_successfully = true;
1581 if (len > 0) {
1582 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1584 remaining_data_length_ -= original_len;
1585 if (!processed_successfully) {
1586 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1587 } else if (remaining_data_length_ == 0) {
1588 // Signal that there is not more opaque data.
1589 visitor_->OnGoAwayFrameData(NULL, 0);
1590 CHANGE_STATE(SPDY_AUTO_RESET);
1592 return original_len;
1595 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1596 if (len == 0) {
1597 return 0;
1599 // Clamp to the actual remaining payload.
1600 if (len > remaining_data_length_) {
1601 len = remaining_data_length_;
1603 size_t original_len = len;
1605 // Check if we had already read enough bytes to parse the fixed-length portion
1606 // of the RST_STREAM frame.
1607 const size_t header_size = GetRstStreamMinimumSize();
1608 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1609 bool already_parsed_header = (unread_header_bytes == 0);
1610 if (!already_parsed_header) {
1611 // Buffer the new RST_STREAM header bytes we got.
1612 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1614 // Do we have enough to parse the constant size RST_STREAM header?
1615 if (current_frame_buffer_length_ == header_size) {
1616 // Parse out the last good stream id.
1617 SpdyFrameReader reader(current_frame_buffer_.get(),
1618 current_frame_buffer_length_);
1619 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1620 if (protocol_version() < 4) {
1621 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1622 DCHECK(successful_read);
1625 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1626 uint32 status_raw = status;
1627 bool successful_read = reader.ReadUInt32(&status_raw);
1628 DCHECK(successful_read);
1629 // We've read an unsigned integer, so it's enough to only check
1630 // upper bound to ensure the value is in valid range.
1631 if (status_raw > RST_STREAM_INVALID &&
1632 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1633 status = static_cast<SpdyRstStreamStatus>(status_raw);
1634 } else {
1635 // TODO(hkhalil): Probably best to OnError here, depending on
1636 // our interpretation of the spec. Keeping with existing liberal
1637 // behavior for now.
1639 // Finished parsing the RST_STREAM header, call frame handler.
1640 visitor_->OnRstStream(current_frame_stream_id_, status);
1644 // Handle remaining data as opaque.
1645 bool processed_successfully = true;
1646 if (len > 0) {
1647 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
1649 remaining_data_length_ -= original_len;
1650 if (!processed_successfully) {
1651 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
1652 } else if (remaining_data_length_ == 0) {
1653 // Signal that there is not more opaque data.
1654 visitor_->OnRstStreamFrameData(NULL, 0);
1655 CHANGE_STATE(SPDY_AUTO_RESET);
1657 return original_len;
1660 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
1661 size_t original_len = len;
1663 if (remaining_data_length_ > 0) {
1664 size_t amount_to_forward = std::min(remaining_data_length_, len);
1665 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1666 // Only inform the visitor if there is data.
1667 if (amount_to_forward) {
1668 visitor_->OnStreamFrameData(
1669 current_frame_stream_id_, data, amount_to_forward, false);
1672 data += amount_to_forward;
1673 len -= amount_to_forward;
1674 remaining_data_length_ -= amount_to_forward;
1676 // If the FIN flag is set, and there is no more data in this data
1677 // frame, inform the visitor of EOF via a 0-length data frame.
1678 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
1679 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1683 if (remaining_data_length_ == 0) {
1684 CHANGE_STATE(SPDY_AUTO_RESET);
1686 return original_len - len;
1689 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
1690 size_t header_length,
1691 SpdyHeaderBlock* block) const {
1692 SpdyFrameReader reader(header_data, header_length);
1694 // Read number of headers.
1695 uint32 num_headers;
1696 if (spdy_version_ < 3) {
1697 uint16 temp;
1698 if (!reader.ReadUInt16(&temp)) {
1699 DVLOG(1) << "Unable to read number of headers.";
1700 return 0;
1702 num_headers = temp;
1703 } else {
1704 if (!reader.ReadUInt32(&num_headers)) {
1705 DVLOG(1) << "Unable to read number of headers.";
1706 return 0;
1710 // Read each header.
1711 for (uint32 index = 0; index < num_headers; ++index) {
1712 base::StringPiece temp;
1714 // Read header name.
1715 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1716 : !reader.ReadStringPiece32(&temp)) {
1717 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
1718 << num_headers << ").";
1719 return 0;
1721 std::string name = temp.as_string();
1723 // Read header value.
1724 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1725 : !reader.ReadStringPiece32(&temp)) {
1726 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
1727 << num_headers << ").";
1728 return 0;
1730 std::string value = temp.as_string();
1732 // Ensure no duplicates.
1733 if (block->find(name) != block->end()) {
1734 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1735 << num_headers << ").";
1736 return 0;
1739 // Store header.
1740 (*block)[name] = value;
1742 return reader.GetBytesConsumed();
1745 SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
1746 const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
1748 SpdyDataFlags flags = DATA_FLAG_NONE;
1749 if (data.fin()) {
1750 flags = DATA_FLAG_FIN;
1753 SpdyFrameBuilder builder(kSize);
1754 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1755 builder.WriteBytes(data.data().data(), data.data().length());
1756 DCHECK_EQ(kSize, builder.length());
1757 return builder.take();
1760 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
1761 const SpdyDataIR& data) const {
1762 const size_t kSize = GetDataFrameMinimumSize();
1764 SpdyDataFlags flags = DATA_FLAG_NONE;
1765 if (data.fin()) {
1766 flags = DATA_FLAG_FIN;
1769 SpdyFrameBuilder builder(kSize);
1770 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1771 if (protocol_version() < 4) {
1772 builder.OverwriteLength(*this, data.data().length());
1773 } else {
1774 builder.OverwriteLength(*this, data.data().length() + kSize);
1776 DCHECK_EQ(kSize, builder.length());
1777 return builder.take();
1780 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
1781 const SpdySynStreamIR& syn_stream) {
1782 uint8 flags = 0;
1783 if (syn_stream.fin()) {
1784 flags |= CONTROL_FLAG_FIN;
1786 if (syn_stream.unidirectional()) {
1787 // TODO(hkhalil): invalid for HTTP2.
1788 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
1790 if (spdy_version_ >= 4) {
1791 flags |= HEADERS_FLAG_PRIORITY;
1794 // Sanitize priority.
1795 uint8 priority = syn_stream.priority();
1796 if (priority > GetLowestPriority()) {
1797 DLOG(DFATAL) << "Priority out-of-bounds.";
1798 priority = GetLowestPriority();
1801 // The size of this frame, including variable-length name-value block.
1802 const size_t size = GetSynStreamMinimumSize()
1803 + GetSerializedLength(syn_stream.name_value_block());
1805 SpdyFrameBuilder builder(size);
1806 if (spdy_version_ < 4) {
1807 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
1808 builder.WriteUInt32(syn_stream.stream_id());
1809 builder.WriteUInt32(syn_stream.associated_to_stream_id());
1810 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
1811 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
1812 } else {
1813 builder.WriteFramePrefix(*this,
1814 HEADERS,
1815 flags,
1816 syn_stream.stream_id());
1817 builder.WriteUInt32(priority);
1819 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
1820 SerializeNameValueBlock(&builder, syn_stream);
1822 if (debug_visitor_) {
1823 const size_t payload_len = GetSerializedLength(
1824 protocol_version(), &(syn_stream.name_value_block()));
1825 // SPDY 4 reports this compression as a SYN_STREAM compression.
1826 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
1827 SYN_STREAM,
1828 payload_len,
1829 builder.length());
1832 return builder.take();
1835 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
1836 const SpdySynReplyIR& syn_reply) {
1837 uint8 flags = 0;
1838 if (syn_reply.fin()) {
1839 flags |= CONTROL_FLAG_FIN;
1842 // The size of this frame, including variable-length name-value block.
1843 size_t size = GetSynReplyMinimumSize()
1844 + GetSerializedLength(syn_reply.name_value_block());
1846 SpdyFrameBuilder builder(size);
1847 if (spdy_version_ < 4) {
1848 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
1849 builder.WriteUInt32(syn_reply.stream_id());
1850 } else {
1851 builder.WriteFramePrefix(*this,
1852 HEADERS,
1853 flags,
1854 syn_reply.stream_id());
1856 if (protocol_version() < 3) {
1857 builder.WriteUInt16(0); // Unused.
1859 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
1860 SerializeNameValueBlock(&builder, syn_reply);
1862 if (debug_visitor_) {
1863 const size_t payload_len = GetSerializedLength(
1864 protocol_version(), &(syn_reply.name_value_block()));
1865 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
1866 SYN_REPLY,
1867 payload_len,
1868 builder.length());
1871 return builder.take();
1874 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
1875 const SpdyRstStreamIR& rst_stream) const {
1876 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
1877 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
1878 // which doesn't currently include RST_STREAM payloads. GFE flags have been
1879 // commented but left in place to simplify future patching.
1880 // Compute the output buffer size, taking opaque data into account.
1881 uint16 expected_length = GetRstStreamMinimumSize();
1882 if (protocol_version() >= 4 &&
1883 false /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1884 expected_length += rst_stream.description().size();
1886 SpdyFrameBuilder builder(expected_length);
1888 // Serialize the RST_STREAM frame.
1889 if (protocol_version() < 4) {
1890 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
1891 builder.WriteUInt32(rst_stream.stream_id());
1892 } else {
1893 builder.WriteFramePrefix(*this, RST_STREAM, 0, rst_stream.stream_id());
1896 builder.WriteUInt32(rst_stream.status());
1898 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
1899 if (protocol_version() >= 4 && rst_stream.description().size() > 0 &&
1900 false /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1901 builder.WriteBytes(rst_stream.description().data(),
1902 rst_stream.description().size());
1905 DCHECK_EQ(expected_length, builder.length());
1906 return builder.take();
1909 SpdySerializedFrame* SpdyFramer::SerializeSettings(
1910 const SpdySettingsIR& settings) const {
1911 uint8 flags = 0;
1912 if (settings.clear_settings()) {
1913 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1915 const SpdySettingsIR::ValueMap* values = &(settings.values());
1917 // Size, in bytes, of this SETTINGS frame.
1918 const size_t size = GetSettingsMinimumSize() + (values->size() * 8);
1920 SpdyFrameBuilder builder(size);
1921 if (spdy_version_ < 4) {
1922 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
1923 } else {
1924 builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
1926 builder.WriteUInt32(values->size());
1927 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
1928 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
1929 it != values->end();
1930 ++it) {
1931 uint8 setting_flags = 0;
1932 if (it->second.persist_value) {
1933 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
1935 if (it->second.persisted) {
1936 setting_flags |= SETTINGS_FLAG_PERSISTED;
1938 SettingsFlagsAndId flags_and_id(setting_flags, it->first);
1939 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
1940 builder.WriteBytes(&id_and_flags_wire, 4);
1941 builder.WriteUInt32(it->second.value);
1943 DCHECK_EQ(size, builder.length());
1944 return builder.take();
1947 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
1948 DCHECK_LE(4, protocol_version());
1949 SpdyFrameBuilder builder(GetBlockedSize());
1950 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
1951 return builder.take();
1954 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
1955 SpdyFrameBuilder builder(GetPingSize());
1956 if (spdy_version_ < 4) {
1957 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
1958 builder.WriteUInt32(static_cast<uint32>(ping.id()));
1959 } else {
1960 uint8 flags = 0;
1961 if (ping.is_ack()) {
1962 flags |= PING_FLAG_ACK;
1964 builder.WriteFramePrefix(*this, PING, flags, 0);
1965 builder.WriteUInt64(ping.id());
1967 DCHECK_EQ(GetPingSize(), builder.length());
1968 return builder.take();
1971 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
1972 const SpdyGoAwayIR& goaway) const {
1974 // Compute the output buffer size, take opaque data into account.
1975 uint16 expected_length = GetGoAwayMinimumSize();
1976 if (protocol_version() >= 4) {
1977 expected_length += goaway.description().size();
1979 SpdyFrameBuilder builder(expected_length);
1981 // Serialize the GOAWAY frame.
1982 if (spdy_version_ < 4) {
1983 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
1984 } else {
1985 builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
1988 // GOAWAY frames specify the last good stream id for all SPDY versions.
1989 builder.WriteUInt32(goaway.last_good_stream_id());
1991 // In SPDY3 and up, GOAWAY frames also specify the error status code.
1992 if (protocol_version() >= 3) {
1993 builder.WriteUInt32(goaway.status());
1996 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
1997 if ((protocol_version() >= 4) && (goaway.description().size() > 0)) {
1998 builder.WriteBytes(goaway.description().data(),
1999 goaway.description().size());
2002 DCHECK_EQ(expected_length, builder.length());
2003 return builder.take();
2006 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2007 const SpdyHeadersIR& headers) {
2008 uint8 flags = 0;
2009 if (headers.fin()) {
2010 flags |= CONTROL_FLAG_FIN;
2013 // The size of this frame, including variable-length name-value block.
2014 size_t size = GetHeadersMinimumSize()
2015 + GetSerializedLength(headers.name_value_block());
2017 SpdyFrameBuilder builder(size);
2018 if (spdy_version_ < 4) {
2019 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2020 builder.WriteUInt32(headers.stream_id());
2021 } else {
2022 builder.WriteFramePrefix(*this,
2023 HEADERS,
2024 flags,
2025 headers.stream_id());
2027 if (protocol_version() < 3) {
2028 builder.WriteUInt16(0); // Unused.
2030 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2032 SerializeNameValueBlock(&builder, headers);
2034 if (debug_visitor_) {
2035 const size_t payload_len = GetSerializedLength(
2036 protocol_version(), &(headers.name_value_block()));
2037 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2038 HEADERS,
2039 payload_len,
2040 builder.length());
2043 return builder.take();
2046 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2047 const SpdyWindowUpdateIR& window_update) const {
2048 SpdyFrameBuilder builder(GetWindowUpdateSize());
2049 if (spdy_version_ < 4) {
2050 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2051 builder.WriteUInt32(window_update.stream_id());
2052 } else {
2053 builder.WriteFramePrefix(*this,
2054 WINDOW_UPDATE,
2055 kNoFlags,
2056 window_update.stream_id());
2058 builder.WriteUInt32(window_update.delta());
2059 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2060 return builder.take();
2063 SpdyFrame* SpdyFramer::SerializePushPromise(
2064 const SpdyPushPromiseIR& push_promise) {
2065 DCHECK_LE(4, protocol_version());
2066 // The size of this frame, including variable-length name-value block.
2067 size_t size = GetPushPromiseMinimumSize()
2068 + GetSerializedLength(push_promise.name_value_block());
2070 SpdyFrameBuilder builder(size);
2071 builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags,
2072 push_promise.stream_id());
2073 builder.WriteUInt32(push_promise.promised_stream_id());
2074 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2076 SerializeNameValueBlock(&builder, push_promise);
2078 if (debug_visitor_) {
2079 const size_t payload_len = GetSerializedLength(
2080 protocol_version(), &(push_promise.name_value_block()));
2081 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2082 PUSH_PROMISE, payload_len, builder.length());
2085 return builder.take();
2088 namespace {
2090 class FrameSerializationVisitor : public SpdyFrameVisitor {
2091 public:
2092 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2093 virtual ~FrameSerializationVisitor() {}
2095 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2097 virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2098 frame_.reset(framer_->SerializeData(data));
2100 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2101 frame_.reset(framer_->SerializeSynStream(syn_stream));
2103 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2104 frame_.reset(framer_->SerializeSynReply(syn_reply));
2106 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2107 frame_.reset(framer_->SerializeRstStream(rst_stream));
2109 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2110 frame_.reset(framer_->SerializeSettings(settings));
2112 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2113 frame_.reset(framer_->SerializePing(ping));
2115 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2116 frame_.reset(framer_->SerializeGoAway(goaway));
2118 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2119 frame_.reset(framer_->SerializeHeaders(headers));
2121 virtual void VisitWindowUpdate(
2122 const SpdyWindowUpdateIR& window_update) OVERRIDE {
2123 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2125 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2126 frame_.reset(framer_->SerializeBlocked(blocked));
2128 virtual void VisitPushPromise(
2129 const SpdyPushPromiseIR& push_promise) OVERRIDE {
2130 frame_.reset(framer_->SerializePushPromise(push_promise));
2133 private:
2134 SpdyFramer* framer_;
2135 scoped_ptr<SpdySerializedFrame> frame_;
2138 } // namespace
2140 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2141 FrameSerializationVisitor visitor(this);
2142 frame.Visit(&visitor);
2143 return visitor.ReleaseSerializedFrame();
2146 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2147 const size_t uncompressed_length =
2148 GetSerializedLength(protocol_version(), &headers);
2149 if (!enable_compression_) {
2150 return uncompressed_length;
2152 z_stream* compressor = GetHeaderCompressor();
2153 // Since we'll be performing lots of flushes when compressing the data,
2154 // zlib's lower bounds may be insufficient.
2155 return 2 * deflateBound(compressor, uncompressed_length);
2158 // The following compression setting are based on Brian Olson's analysis. See
2159 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2160 // for more details.
2161 #if defined(USE_SYSTEM_ZLIB)
2162 // System zlib is not expected to have workaround for http://crbug.com/139744,
2163 // so disable compression in that case.
2164 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2165 static const int kCompressorLevel = 0;
2166 #else // !defined(USE_SYSTEM_ZLIB)
2167 static const int kCompressorLevel = 9;
2168 #endif // !defined(USE_SYSTEM_ZLIB)
2169 static const int kCompressorWindowSizeInBits = 11;
2170 static const int kCompressorMemLevel = 1;
2172 z_stream* SpdyFramer::GetHeaderCompressor() {
2173 if (header_compressor_.get())
2174 return header_compressor_.get(); // Already initialized.
2176 header_compressor_.reset(new z_stream);
2177 memset(header_compressor_.get(), 0, sizeof(z_stream));
2179 int success = deflateInit2(header_compressor_.get(),
2180 kCompressorLevel,
2181 Z_DEFLATED,
2182 kCompressorWindowSizeInBits,
2183 kCompressorMemLevel,
2184 Z_DEFAULT_STRATEGY);
2185 if (success == Z_OK) {
2186 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2187 : kV3Dictionary;
2188 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2189 : kV3DictionarySize;
2190 success = deflateSetDictionary(header_compressor_.get(),
2191 reinterpret_cast<const Bytef*>(dictionary),
2192 dictionary_size);
2194 if (success != Z_OK) {
2195 LOG(WARNING) << "deflateSetDictionary failure: " << success;
2196 header_compressor_.reset(NULL);
2197 return NULL;
2199 return header_compressor_.get();
2202 z_stream* SpdyFramer::GetHeaderDecompressor() {
2203 if (header_decompressor_.get())
2204 return header_decompressor_.get(); // Already initialized.
2206 header_decompressor_.reset(new z_stream);
2207 memset(header_decompressor_.get(), 0, sizeof(z_stream));
2209 int success = inflateInit(header_decompressor_.get());
2210 if (success != Z_OK) {
2211 LOG(WARNING) << "inflateInit failure: " << success;
2212 header_decompressor_.reset(NULL);
2213 return NULL;
2215 return header_decompressor_.get();
2218 // Incrementally decompress the control frame's header block, feeding the
2219 // result to the visitor in chunks. Continue this until the visitor
2220 // indicates that it cannot process any more data, or (more commonly) we
2221 // run out of data to deliver.
2222 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
2223 SpdyStreamId stream_id,
2224 const char* data,
2225 size_t len) {
2226 // Get a decompressor or set error.
2227 z_stream* decomp = GetHeaderDecompressor();
2228 if (decomp == NULL) {
2229 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
2230 set_error(SPDY_DECOMPRESS_FAILURE);
2231 return false;
2234 bool processed_successfully = true;
2235 char buffer[kHeaderDataChunkMaxSize];
2237 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
2238 decomp->avail_in = len;
2239 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
2240 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
2241 // reached this method successfully, stream_id should be nonzero.
2242 DCHECK_LT(0u, stream_id);
2243 while (decomp->avail_in > 0 && processed_successfully) {
2244 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
2245 decomp->avail_out = arraysize(buffer);
2247 int rv = inflate(decomp, Z_SYNC_FLUSH);
2248 if (rv == Z_NEED_DICT) {
2249 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2250 : kV3Dictionary;
2251 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2252 : kV3DictionarySize;
2253 const DictionaryIds& ids = g_dictionary_ids.Get();
2254 const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
2255 : ids.v3_dictionary_id;
2256 // Need to try again with the right dictionary.
2257 if (decomp->adler == dictionary_id) {
2258 rv = inflateSetDictionary(decomp,
2259 reinterpret_cast<const Bytef*>(dictionary),
2260 dictionary_size);
2261 if (rv == Z_OK)
2262 rv = inflate(decomp, Z_SYNC_FLUSH);
2266 // Inflate will generate a Z_BUF_ERROR if it runs out of input
2267 // without producing any output. The input is consumed and
2268 // buffered internally by zlib so we can detect this condition by
2269 // checking if avail_in is 0 after the call to inflate.
2270 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
2271 if ((rv == Z_OK) || input_exhausted) {
2272 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
2273 if (decompressed_len > 0) {
2274 processed_successfully = visitor_->OnControlFrameHeaderData(
2275 stream_id, buffer, decompressed_len);
2277 if (!processed_successfully) {
2278 // Assume that the problem was the header block was too large for the
2279 // visitor.
2280 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2282 } else {
2283 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
2284 set_error(SPDY_DECOMPRESS_FAILURE);
2285 processed_successfully = false;
2288 return processed_successfully;
2291 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
2292 SpdyStreamId stream_id, const char* data, size_t len) {
2293 bool read_successfully = true;
2294 while (read_successfully && len > 0) {
2295 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
2296 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
2297 bytes_to_deliver);
2298 data += bytes_to_deliver;
2299 len -= bytes_to_deliver;
2300 if (!read_successfully) {
2301 // Assume that the problem was the header block was too large for the
2302 // visitor.
2303 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2306 return read_successfully;
2309 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
2310 SpdyFrameBuilder* builder,
2311 const SpdyNameValueBlock& name_value_block) const {
2312 // Serialize number of headers.
2313 if (protocol_version() < 3) {
2314 builder->WriteUInt16(name_value_block.size());
2315 } else {
2316 builder->WriteUInt32(name_value_block.size());
2319 // Serialize each header.
2320 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
2321 it != name_value_block.end();
2322 ++it) {
2323 if (protocol_version() < 3) {
2324 builder->WriteString(it->first);
2325 builder->WriteString(it->second);
2326 } else {
2327 builder->WriteStringPiece32(it->first);
2328 builder->WriteStringPiece32(it->second);
2333 void SpdyFramer::SerializeNameValueBlock(
2334 SpdyFrameBuilder* builder,
2335 const SpdyFrameWithNameValueBlockIR& frame) {
2336 if (!enable_compression_) {
2337 return SerializeNameValueBlockWithoutCompression(builder,
2338 frame.name_value_block());
2341 // First build an uncompressed version to be fed into the compressor.
2342 const size_t uncompressed_len = GetSerializedLength(
2343 protocol_version(), &(frame.name_value_block()));
2344 SpdyFrameBuilder uncompressed_builder(uncompressed_len);
2345 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
2346 frame.name_value_block());
2347 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
2349 z_stream* compressor = GetHeaderCompressor();
2350 if (!compressor) {
2351 LOG(DFATAL) << "Could not obtain compressor.";
2352 return;
2355 base::StatsCounter compressed_frames("spdy.CompressedFrames");
2356 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
2357 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
2359 // Create an output frame.
2360 // Since we'll be performing lots of flushes when compressing the data,
2361 // zlib's lower bounds may be insufficient.
2363 // TODO(akalin): Avoid the duplicate calculation with
2364 // GetSerializedLength(const SpdyHeaderBlock&).
2365 const int compressed_max_size =
2366 2 * deflateBound(compressor, uncompressed_len);
2368 // TODO(phajdan.jr): Clean up after we no longer need
2369 // to workaround http://crbug.com/139744.
2370 #if defined(USE_SYSTEM_ZLIB)
2371 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
2372 compressor->avail_in = uncompressed_len;
2373 #endif // defined(USE_SYSTEM_ZLIB)
2374 compressor->next_out = reinterpret_cast<Bytef*>(
2375 builder->GetWritableBuffer(compressed_max_size));
2376 compressor->avail_out = compressed_max_size;
2378 // TODO(phajdan.jr): Clean up after we no longer need
2379 // to workaround http://crbug.com/139744.
2380 #if defined(USE_SYSTEM_ZLIB)
2381 int rv = deflate(compressor, Z_SYNC_FLUSH);
2382 if (rv != Z_OK) { // How can we know that it compressed everything?
2383 // This shouldn't happen, right?
2384 LOG(WARNING) << "deflate failure: " << rv;
2385 // TODO(akalin): Upstream this return.
2386 return;
2388 #else
2389 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
2390 #endif // defined(USE_SYSTEM_ZLIB)
2392 int compressed_size = compressed_max_size - compressor->avail_out;
2393 builder->Seek(compressed_size);
2394 builder->RewriteLength(*this);
2396 pre_compress_bytes.Add(uncompressed_len);
2397 post_compress_bytes.Add(compressed_size);
2399 compressed_frames.Increment();
2402 } // namespace net