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-
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"
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
),
36 struct 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;
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) \
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_; \
73 #define CHANGE_STATE(newstate) \
75 DCHECK(state_ != SPDY_ERROR); \
76 DCHECK_EQ(previous_state_, state_); \
77 previous_state_ = state_; \
82 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(int version
,
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);
98 ConvertFlagsAndIdForSpdy2(&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
,
119 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
120 const char* rst_stream_data
,
125 SpdyFramer::SpdyFramer(SpdyMajorVersion version
)
126 : current_frame_buffer_(new char[kControlFrameBufferSize
]),
127 enable_compression_(true),
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
);
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() {
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.
169 // Size, in bytes, of the control frame header.
170 size_t SpdyFramer::GetControlFrameHeaderSize() const {
171 switch (protocol_version()) {
177 LOG(DFATAL
) << "Unhandled SPDY version.";
181 size_t SpdyFramer::GetSynStreamMinimumSize() const {
182 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
184 if (spdy_version_
< 4) {
186 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
187 // + 1 (unused, was credential slot)
188 return GetControlFrameHeaderSize() + 10;
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
199 size_t size
= GetControlFrameHeaderSize();
200 if (spdy_version_
< 4) {
202 // control frame header + 4 (stream IDs)
206 // In SPDY 2, there were 2 unused bytes before payload.
207 if (protocol_version() < 3) {
214 size_t SpdyFramer::GetRstStreamMinimumSize() const {
215 // Size, in bytes, of a RST_STREAM frame.
216 if (spdy_version_
< 4) {
218 // control frame header + 4 (stream id) + 4 (status code)
219 return GetControlFrameHeaderSize() + 8;
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)
248 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
249 if (protocol_version() >= 3) {
256 size_t SpdyFramer::GetHeadersMinimumSize() const {
257 // Size, in bytes, of a HEADERS frame not including the variable-length
259 size_t size
= GetControlFrameHeaderSize();
260 if (spdy_version_
< 4) {
262 // control frame header + 4 (stream IDs)
266 // In SPDY 2, there were 2 unused bytes before payload.
267 if (protocol_version() < 3) {
274 size_t SpdyFramer::GetWindowUpdateSize() const {
275 // Size, in bytes, of a WINDOW_UPDATE frame.
276 if (spdy_version_
< 4) {
278 // control frame header + 4 (stream id) + 4 (delta)
279 return GetControlFrameHeaderSize() + 8;
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
) {
317 case SPDY_AUTO_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
) {
346 CHANGE_STATE(SPDY_ERROR
);
347 visitor_
->OnError(this);
350 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
351 switch (error_code
) {
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
:
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
:
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
) {
425 return "WINDOW_UPDATE";
431 return "PUSH_PROMISE";
433 return "UNKNOWN_CONTROL_TYPE";
436 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
440 size_t original_len
= len
;
442 previous_state_
= state_
;
447 case SPDY_AUTO_RESET
:
451 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
455 case SPDY_READING_COMMON_HEADER
: {
456 size_t bytes_read
= ProcessCommonHeader(data
, len
);
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
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
);
482 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
483 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
489 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
490 int bytes_read
= ProcessControlFrameHeaderBlock(data
, len
);
496 case SPDY_RST_STREAM_FRAME_PAYLOAD
: {
497 size_t bytes_read
= ProcessRstStreamFramePayload(data
, len
);
503 case SPDY_GOAWAY_FRAME_PAYLOAD
: {
504 size_t bytes_read
= ProcessGoAwayFramePayload(data
, len
);
510 case SPDY_CONTROL_FRAME_PAYLOAD
: {
511 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
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
);
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.
534 } while (state_
!= previous_state_
);
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
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_
));
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
);
591 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
593 DCHECK(successful_read
);
595 successful_read
= reader
->ReadUInt8(¤t_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();
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(¤t_frame_flags_
);
619 DCHECK(successful_read
);
621 successful_read
= reader
->ReadUInt31(¤t_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_
640 probable_http_response_
= true;
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
);
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
);
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
);
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
);
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
);
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
);
704 // Do some sanity checking on the control frame sizes and flags.
705 switch (current_frame_type_
) {
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
);
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
);
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
);
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
);
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
);
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
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
);
773 size_t min_size
= GetHeadersMinimumSize();
774 if (spdy_version_
> 3 &&
775 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
)) {
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
);
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
);
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
);
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
);
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.
819 set_error(SPDY_INVALID_CONTROL_FRAME
);
823 if (state_
== SPDY_ERROR
) {
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
);
834 if (current_frame_type_
== GOAWAY
) {
835 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD
);
839 if (current_frame_type_
== RST_STREAM
) {
840 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD
);
844 // Determine the frame size without variable-length data.
845 int32 frame_size_without_variable_data
;
846 switch (current_frame_type_
) {
848 syn_frame_processed_
= true;
849 frame_size_without_variable_data
= GetSynStreamMinimumSize();
852 syn_frame_processed_
= true;
853 frame_size_without_variable_data
= GetSynReplyMinimumSize();
856 frame_size_without_variable_data
= GetSettingsMinimumSize();
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
865 frame_size_without_variable_data
= GetPushPromiseMinimumSize();
868 frame_size_without_variable_data
= -1;
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
);
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
);
897 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
900 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
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_
,
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();
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();
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.
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
);
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.
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
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
,
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
) {
988 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
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();
997 if (clas
== kZStandardData
) {
998 rv
= deflate(out
, Z_NO_FLUSH
);
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
,
1016 DCHECK_LE(length
, sizeof(buf
));
1017 for (unsigned i
= 1; i
<= length
; i
++) {
1018 buf
[length
- i
] = n
;
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
1027 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
1028 z_stream
* z
) const {
1029 unsigned length_length
= 4;
1030 if (spdy_version_
< 3)
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
1046 std::vector
<base::StringPiece
> cookie_values
;
1047 size_t cookie_length
= 0;
1048 base::StringPiece
cookie_data(it
->second
);
1051 while (!cookie_data
.empty() &&
1052 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
1053 cookie_data
.remove_prefix(1);
1055 if (cookie_data
.empty())
1059 for (i
= 0; i
< cookie_data
.size(); i
++) {
1060 if (cookie_data
[i
] == ';')
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);
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
++) {
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() + ";";
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
);
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
);
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
,
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_
) {
1142 DCHECK_GT(4, spdy_version_
);
1143 bool successful_read
= true;
1144 if (spdy_version_
< 4) {
1145 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1146 DCHECK(successful_read
);
1148 if (current_frame_stream_id_
== 0) {
1149 set_error(SPDY_INVALID_CONTROL_FRAME
);
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;
1163 priority
= priority
>> 5;
1166 // Seek past unused byte; used to be credential slot in SPDY 3.
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
,
1180 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1181 (current_frame_flags_
& CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
1183 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1186 visitor_
->OnSettings(current_frame_flags_
&
1187 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
);
1188 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
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(¤t_frame_stream_id_
);
1200 DCHECK(successful_read
);
1202 if (current_frame_stream_id_
== 0) {
1203 set_error(SPDY_INVALID_CONTROL_FRAME
);
1206 if (protocol_version() < 3) {
1207 // SPDY 2 had two unused bytes here. Seek past them.
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_
,
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
1241 current_frame_flags_
& CONTROL_FLAG_FIN
,
1242 false); // unidirectional
1244 visitor_
->OnHeaders(
1245 current_frame_stream_id_
,
1246 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0);
1249 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1253 DCHECK_LE(4, protocol_version());
1254 if (current_frame_stream_id_
== 0) {
1255 set_error(SPDY_INVALID_CONTROL_FRAME
);
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
);
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
);
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
,
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
);
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
);
1326 if (!processed_successfully
) {
1330 // Return amount processed.
1331 return process_bytes
;
1334 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
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(
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
;
1356 // Continue updating settings_scratch_.setting_buf.
1357 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
1358 data
+ processed_bytes
,
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;
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
) {
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)));
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
:
1408 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_and_flags
.id();
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
<< ").";
1421 settings_scratch_
.last_setting_id
= id
;
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
<< ": "
1431 // Validation succeeded. Pass on to visitor.
1432 visitor_
->OnSetting(id
, flags
, value
);
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_
) {
1449 // TODO(jgraettinger): Leaving this here for future, saner patching.
1450 // RST_STREAM is separately handled by ProcessRstStreamFramePayload().
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(¤t_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
);
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
);
1477 bool successful_read
= reader
.ReadUInt32(&id
);
1478 DCHECK(successful_read
);
1479 DCHECK(reader
.IsDoneReading());
1480 visitor_
->OnPing(id
);
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(¤t_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_
,
1498 DCHECK_LE(4, protocol_version());
1499 DCHECK(reader
.IsDoneReading());
1500 visitor_
->OnBlocked(current_frame_stream_id_
);
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
) {
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(¤t_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
);
1551 // TODO(hkhalil): Probably best to OnError here, depending on
1552 // our interpretation of the spec. Keeping with existing liberal
1553 // behavior for now.
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;
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
) {
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(¤t_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
);
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;
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.
1679 if (spdy_version_
< 3) {
1681 if (!reader
.ReadUInt16(&temp
)) {
1682 DVLOG(1) << "Unable to read number of headers.";
1687 if (!reader
.ReadUInt32(&num_headers
)) {
1688 DVLOG(1) << "Unable to read number of headers.";
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
<< ").";
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
<< ").";
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
<< ").";
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
;
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
;
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());
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
) {
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.
1796 builder
.WriteFramePrefix(*this,
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(),
1815 return builder
.take();
1818 SpdySerializedFrame
* SpdyFramer::SerializeSynReply(
1819 const SpdySynReplyIR
& syn_reply
) {
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());
1834 builder
.WriteFramePrefix(*this,
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(),
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());
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 {
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
);
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();
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
);
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
);
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
) {
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());
2000 builder
.WriteFramePrefix(*this,
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(),
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());
2031 builder
.WriteFramePrefix(*this,
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();
2068 class FrameSerializationVisitor
: public SpdyFrameVisitor
{
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
));
2112 SpdyFramer
* framer_
;
2113 scoped_ptr
<SpdySerializedFrame
> frame_
;
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(),
2160 kCompressorWindowSizeInBits
,
2161 kCompressorMemLevel
,
2162 Z_DEFAULT_STRATEGY
);
2163 if (success
== Z_OK
) {
2164 const char* dictionary
= (spdy_version_
< 3) ? kV2Dictionary
2166 const int dictionary_size
= (spdy_version_
< 3) ? kV2DictionarySize
2167 : kV3DictionarySize
;
2168 success
= deflateSetDictionary(header_compressor_
.get(),
2169 reinterpret_cast<const Bytef
*>(dictionary
),
2172 if (success
!= Z_OK
) {
2173 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
2174 header_compressor_
.reset(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
);
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
,
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
);
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
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
),
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
2258 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
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
,
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
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());
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();
2301 if (protocol_version() < 3) {
2302 builder
->WriteString(it
->first
);
2303 builder
->WriteString(it
->second
);
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();
2329 LOG(DFATAL
) << "Could not obtain compressor.";
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.
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();