1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_framer.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/stats_counters.h"
10 #include "base/third_party/valgrind/memcheck.h"
11 #include "net/spdy/spdy_frame_builder.h"
12 #include "net/spdy/spdy_frame_reader.h"
13 #include "net/spdy/spdy_bitmasks.h"
14 #include "third_party/zlib/zlib.h"
16 using base::StringPiece
;
24 // Compute the id of our dictionary so that we know we're using the
25 // right one when asked for it.
26 uLong
CalculateDictionaryId(const char* dictionary
,
27 const size_t dictionary_size
) {
28 uLong initial_value
= adler32(0L, Z_NULL
, 0);
29 return adler32(initial_value
,
30 reinterpret_cast<const Bytef
*>(dictionary
),
34 // Check to see if the name and value of a cookie are both empty.
35 bool IsCookieEmpty(const base::StringPiece
& cookie
) {
36 if (cookie
.size() == 0) {
39 size_t pos
= cookie
.find('=');
40 if (pos
== base::StringPiece::npos
) {
43 // Ignore leading whitespaces of cookie value.
44 size_t value_start
= pos
+ 1;
45 for (; value_start
< cookie
.size(); value_start
++) {
46 if (!(cookie
[value_start
] == ' ' || cookie
[value_start
] == '\t')) {
50 return (pos
== 0) && ((cookie
.size() - value_start
) == 0);
53 struct DictionaryIds
{
55 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary
, kV2DictionarySize
)),
56 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary
, kV3DictionarySize
))
58 const uLong v2_dictionary_id
;
59 const uLong v3_dictionary_id
;
62 // Adler ID for the SPDY header compressor dictionaries. Note that they are
63 // initialized lazily to avoid static initializers.
64 base::LazyInstance
<DictionaryIds
>::Leaky g_dictionary_ids
;
66 // Used to indicate no flags in a SPDY flags field.
67 const uint8 kNoFlags
= 0;
69 // Wire sizes of priority payloads.
70 const size_t kPriorityDependencyPayloadSize
= 4;
71 const size_t kPriorityWeightPayloadSize
= 1;
75 const SpdyStreamId
SpdyFramer::kInvalidStream
= static_cast<SpdyStreamId
>(-1);
76 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
77 // The size of the control frame buffer. Must be >= the minimum size of the
78 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
79 // calculation details.
80 const size_t SpdyFramer::kControlFrameBufferSize
= 19;
82 #ifdef DEBUG_SPDY_STATE_CHANGES
83 #define CHANGE_STATE(newstate) \
85 DVLOG(1) << "Changing state from: " \
86 << StateToString(state_) \
87 << " to " << StateToString(newstate) << "\n"; \
88 DCHECK(state_ != SPDY_ERROR); \
89 DCHECK_EQ(previous_state_, state_); \
90 previous_state_ = state_; \
94 #define CHANGE_STATE(newstate) \
96 DCHECK(state_ != SPDY_ERROR); \
97 DCHECK_EQ(previous_state_, state_); \
98 previous_state_ = state_; \
103 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(
104 SpdyMajorVersion version
, uint32 wire
) {
105 if (version
< SPDY3
) {
106 ConvertFlagsAndIdForSpdy2(&wire
);
108 return SettingsFlagsAndId(ntohl(wire
) >> 24, ntohl(wire
) & 0x00ffffff);
111 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags
, uint32 id
)
112 : flags_(flags
), id_(id
& 0x00ffffff) {
113 LOG_IF(DFATAL
, id
> (1u << 24)) << "SPDY setting ID too large: " << id
;
116 uint32
SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version
)
118 uint32 wire
= htonl(id_
& 0x00ffffff) | htonl(flags_
<< 24);
119 if (version
< SPDY3
) {
120 ConvertFlagsAndIdForSpdy2(&wire
);
125 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
126 // This method is used to preserve buggy behavior and works on both
127 // little-endian and big-endian hosts.
128 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
129 // as well as vice versa).
130 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32
* val
) {
131 uint8
* wire_array
= reinterpret_cast<uint8
*>(val
);
132 std::swap(wire_array
[0], wire_array
[3]);
133 std::swap(wire_array
[1], wire_array
[2]);
136 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
137 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
139 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data
,
144 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
145 const char* rst_stream_data
,
150 SpdyFramer::SpdyFramer(SpdyMajorVersion version
)
151 : current_frame_buffer_(new char[kControlFrameBufferSize
]),
152 enable_compression_(true),
154 debug_visitor_(NULL
),
155 display_protocol_("SPDY"),
156 spdy_version_(version
),
157 syn_frame_processed_(false),
158 probable_http_response_(false),
159 expect_continuation_(0),
160 end_stream_when_done_(false) {
161 DCHECK_GE(spdy_version_
, SPDY_MIN_VERSION
);
162 DCHECK_LE(spdy_version_
, SPDY_MAX_VERSION
);
166 SpdyFramer::~SpdyFramer() {
167 if (header_compressor_
.get()) {
168 deflateEnd(header_compressor_
.get());
170 if (header_decompressor_
.get()) {
171 inflateEnd(header_decompressor_
.get());
175 void SpdyFramer::Reset() {
177 previous_state_
= SPDY_RESET
;
178 error_code_
= SPDY_NO_ERROR
;
179 remaining_data_length_
= 0;
180 remaining_control_header_
= 0;
181 current_frame_buffer_length_
= 0;
182 current_frame_type_
= DATA
;
183 current_frame_flags_
= 0;
184 current_frame_length_
= 0;
185 current_frame_stream_id_
= kInvalidStream
;
186 settings_scratch_
.Reset();
187 altsvc_scratch_
.Reset();
188 remaining_padding_payload_length_
= 0;
191 size_t SpdyFramer::GetDataFrameMinimumSize() const {
192 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
195 // Size, in bytes, of the control frame header.
196 size_t SpdyFramer::GetControlFrameHeaderSize() const {
197 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
200 size_t SpdyFramer::GetSynStreamMinimumSize() const {
201 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
203 if (protocol_version() <= SPDY3
) {
205 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
206 // + 1 (unused, was credential slot)
207 return GetControlFrameHeaderSize() + 10;
209 return GetControlFrameHeaderSize() +
210 kPriorityDependencyPayloadSize
+
211 kPriorityWeightPayloadSize
;
215 size_t SpdyFramer::GetSynReplyMinimumSize() const {
216 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
218 size_t size
= GetControlFrameHeaderSize();
219 if (protocol_version() <= SPDY3
) {
221 // control frame header + 4 (stream IDs)
225 // In SPDY 2, there were 2 unused bytes before payload.
226 if (protocol_version() < SPDY3
) {
233 size_t SpdyFramer::GetRstStreamMinimumSize() const {
234 // Size, in bytes, of a RST_STREAM frame.
235 if (protocol_version() <= SPDY3
) {
237 // control frame header + 4 (stream id) + 4 (status code)
238 return GetControlFrameHeaderSize() + 8;
241 // frame prefix + 4 (status code)
242 return GetControlFrameHeaderSize() + 4;
246 size_t SpdyFramer::GetSettingsMinimumSize() const {
247 // Size, in bytes, of a SETTINGS frame not including the IDs and values
248 // from the variable-length value block. Calculated as:
249 // control frame header + 4 (number of ID/value pairs)
250 if (protocol_version() <= SPDY3
) {
251 return GetControlFrameHeaderSize() + 4;
253 return GetControlFrameHeaderSize();
257 size_t SpdyFramer::GetPingSize() const {
258 // Size, in bytes, of this PING frame.
259 if (protocol_version() <= SPDY3
) {
261 // control frame header + 4 (id)
262 return GetControlFrameHeaderSize() + 4;
265 // control frame header + 8 (id)
266 return GetControlFrameHeaderSize() + 8;
270 size_t SpdyFramer::GetGoAwayMinimumSize() const {
271 // Size, in bytes, of this GOAWAY frame. Calculated as:
272 // 1. Control frame header size
273 size_t size
= GetControlFrameHeaderSize();
275 // 2. Last good stream id (4 bytes)
278 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
279 if (protocol_version() >= SPDY3
) {
286 size_t SpdyFramer::GetHeadersMinimumSize() const {
287 // Size, in bytes, of a HEADERS frame not including the variable-length
289 size_t size
= GetControlFrameHeaderSize();
290 if (protocol_version() <= SPDY3
) {
292 // control frame header + 4 (stream IDs)
296 // In SPDY 2, there were 2 unused bytes before payload.
297 if (protocol_version() <= SPDY2
) {
304 size_t SpdyFramer::GetWindowUpdateSize() const {
305 // Size, in bytes, of a WINDOW_UPDATE frame.
306 if (protocol_version() <= SPDY3
) {
308 // control frame header + 4 (stream id) + 4 (delta)
309 return GetControlFrameHeaderSize() + 8;
312 // frame prefix + 4 (delta)
313 return GetControlFrameHeaderSize() + 4;
317 size_t SpdyFramer::GetBlockedSize() const {
318 DCHECK_LT(SPDY3
, protocol_version());
319 // Size, in bytes, of a BLOCKED frame.
320 // The BLOCKED frame has no payload beyond the control frame header.
321 return GetControlFrameHeaderSize();
324 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
325 DCHECK_LT(SPDY3
, protocol_version());
326 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
327 // Calculated as frame prefix + 4 (promised stream id).
328 return GetControlFrameHeaderSize() + 4;
331 size_t SpdyFramer::GetContinuationMinimumSize() const {
332 // Size, in bytes, of a CONTINUATION frame not including the variable-length
333 // headers fragments.
334 return GetControlFrameHeaderSize();
337 size_t SpdyFramer::GetAltSvcMinimumSize() const {
338 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
339 // (optional) Origin fields, all of which can vary in length.
340 // Note that this gives a lower bound on the frame size rather than a true
341 // minimum; the actual frame should always be larger than this.
342 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
343 // + 1 (pid_len) + 1 (host_len).
344 return GetControlFrameHeaderSize() + 9;
347 size_t SpdyFramer::GetPrioritySize() const {
348 // Size, in bytes, of a PRIORITY frame.
349 return GetControlFrameHeaderSize() +
350 kPriorityDependencyPayloadSize
+
351 kPriorityWeightPayloadSize
;
354 size_t SpdyFramer::GetFrameMinimumSize() const {
355 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
358 size_t SpdyFramer::GetFrameMaximumSize() const {
359 return SpdyConstants::GetFrameMaximumSize(protocol_version());
362 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
363 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
366 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type
) const {
367 return SpdyConstants::GetPrefixLength(type
, protocol_version());
370 const char* SpdyFramer::StateToString(int state
) {
374 case SPDY_AUTO_RESET
:
378 case SPDY_READING_COMMON_HEADER
:
379 return "READING_COMMON_HEADER";
380 case SPDY_CONTROL_FRAME_PAYLOAD
:
381 return "CONTROL_FRAME_PAYLOAD";
382 case SPDY_READ_PADDING_LENGTH
:
383 return "SPDY_READ_PADDING_LENGTH";
384 case SPDY_CONSUME_PADDING
:
385 return "SPDY_CONSUME_PADDING";
386 case SPDY_IGNORE_REMAINING_PAYLOAD
:
387 return "IGNORE_REMAINING_PAYLOAD";
388 case SPDY_FORWARD_STREAM_FRAME
:
389 return "FORWARD_STREAM_FRAME";
390 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
391 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
392 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
393 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
394 case SPDY_GOAWAY_FRAME_PAYLOAD
:
395 return "SPDY_GOAWAY_FRAME_PAYLOAD";
396 case SPDY_RST_STREAM_FRAME_PAYLOAD
:
397 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
398 case SPDY_SETTINGS_FRAME_PAYLOAD
:
399 return "SPDY_SETTINGS_FRAME_PAYLOAD";
400 case SPDY_ALTSVC_FRAME_PAYLOAD
:
401 return "SPDY_ALTSVC_FRAME_PAYLOAD";
403 return "UNKNOWN_STATE";
406 void SpdyFramer::set_error(SpdyError error
) {
409 // These values will usually get reset once we come to the end
410 // of a header block, but if we run into an error that
411 // might not happen, so reset them here.
412 expect_continuation_
= 0;
413 end_stream_when_done_
= false;
415 CHANGE_STATE(SPDY_ERROR
);
416 visitor_
->OnError(this);
419 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
420 switch (error_code
) {
423 case SPDY_INVALID_CONTROL_FRAME
:
424 return "INVALID_CONTROL_FRAME";
425 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
426 return "CONTROL_PAYLOAD_TOO_LARGE";
427 case SPDY_ZLIB_INIT_FAILURE
:
428 return "ZLIB_INIT_FAILURE";
429 case SPDY_UNSUPPORTED_VERSION
:
430 return "UNSUPPORTED_VERSION";
431 case SPDY_DECOMPRESS_FAILURE
:
432 return "DECOMPRESS_FAILURE";
433 case SPDY_COMPRESS_FAILURE
:
434 return "COMPRESS_FAILURE";
435 case SPDY_INVALID_DATA_FRAME_FLAGS
:
436 return "SPDY_INVALID_DATA_FRAME_FLAGS";
437 case SPDY_INVALID_CONTROL_FRAME_FLAGS
:
438 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
439 case SPDY_UNEXPECTED_FRAME
:
440 return "UNEXPECTED_FRAME";
442 return "UNKNOWN_ERROR";
445 const char* SpdyFramer::StatusCodeToString(int status_code
) {
446 switch (status_code
) {
447 case RST_STREAM_INVALID
:
449 case RST_STREAM_PROTOCOL_ERROR
:
450 return "PROTOCOL_ERROR";
451 case RST_STREAM_INVALID_STREAM
:
452 return "INVALID_STREAM";
453 case RST_STREAM_REFUSED_STREAM
:
454 return "REFUSED_STREAM";
455 case RST_STREAM_UNSUPPORTED_VERSION
:
456 return "UNSUPPORTED_VERSION";
457 case RST_STREAM_CANCEL
:
459 case RST_STREAM_INTERNAL_ERROR
:
460 return "INTERNAL_ERROR";
461 case RST_STREAM_FLOW_CONTROL_ERROR
:
462 return "FLOW_CONTROL_ERROR";
463 case RST_STREAM_STREAM_IN_USE
:
464 return "STREAM_IN_USE";
465 case RST_STREAM_STREAM_ALREADY_CLOSED
:
466 return "STREAM_ALREADY_CLOSED";
467 case RST_STREAM_INVALID_CREDENTIALS
:
468 return "INVALID_CREDENTIALS";
469 case RST_STREAM_FRAME_TOO_LARGE
:
470 return "FRAME_TOO_LARGE";
471 case RST_STREAM_CONNECT_ERROR
:
472 return "CONNECT_ERROR";
473 case RST_STREAM_ENHANCE_YOUR_CALM
:
474 return "ENHANCE_YOUR_CALM";
476 return "UNKNOWN_STATUS";
479 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type
) {
498 return "WINDOW_UPDATE";
502 return "PUSH_PROMISE";
504 return "CONTINUATION";
512 return "UNKNOWN_CONTROL_TYPE";
515 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
519 size_t original_len
= len
;
521 previous_state_
= state_
;
526 case SPDY_AUTO_RESET
:
530 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
534 case SPDY_READING_COMMON_HEADER
: {
535 size_t bytes_read
= ProcessCommonHeader(data
, len
);
541 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
542 // Control frames that contain header blocks
543 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
544 // take a different path through the state machine - they
546 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
547 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
549 // SETTINGS frames take a slightly modified route:
550 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
551 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
553 // All other control frames will use the alternate route directly to
554 // SPDY_CONTROL_FRAME_PAYLOAD
555 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
561 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
562 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
568 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
569 int bytes_read
= ProcessControlFrameHeaderBlock(
570 data
, len
, protocol_version() > SPDY3
);
576 case SPDY_RST_STREAM_FRAME_PAYLOAD
: {
577 size_t bytes_read
= ProcessRstStreamFramePayload(data
, len
);
583 case SPDY_GOAWAY_FRAME_PAYLOAD
: {
584 size_t bytes_read
= ProcessGoAwayFramePayload(data
, len
);
590 case SPDY_ALTSVC_FRAME_PAYLOAD
: {
591 size_t bytes_read
= ProcessAltSvcFramePayload(data
, len
);
597 case SPDY_CONTROL_FRAME_PAYLOAD
: {
598 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
604 case SPDY_READ_PADDING_LENGTH
: {
605 size_t bytes_read
= ProcessFramePaddingLength(data
, len
);
611 case SPDY_CONSUME_PADDING
: {
612 size_t bytes_read
= ProcessFramePadding(data
, len
);
618 case SPDY_IGNORE_REMAINING_PAYLOAD
: {
619 size_t bytes_read
= ProcessIgnoredControlFramePayload(/*data,*/ len
);
625 case SPDY_FORWARD_STREAM_FRAME
: {
626 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
633 LOG(DFATAL
) << "Invalid value for " << display_protocol_
634 << " framer state: " << state_
;
635 // This ensures that we don't infinite-loop if state_ gets an
636 // invalid value somehow, such as due to a SpdyFramer getting deleted
637 // from a callback it calls.
640 } while (state_
!= previous_state_
);
642 DCHECK(len
== 0 || state_
== SPDY_ERROR
);
643 if (current_frame_buffer_length_
== 0 &&
644 remaining_data_length_
== 0 &&
645 remaining_control_header_
== 0) {
646 DCHECK(state_
== SPDY_RESET
|| state_
== SPDY_ERROR
)
647 << "State: " << StateToString(state_
);
650 return original_len
- len
;
653 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
654 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
656 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
658 size_t original_len
= len
;
660 // Update current frame buffer as needed.
661 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
662 size_t bytes_desired
=
663 GetControlFrameHeaderSize() - current_frame_buffer_length_
;
664 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
667 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
668 // Not enough information to do anything meaningful.
669 return original_len
- len
;
672 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
673 // when processing DATA frames below.
674 scoped_ptr
<SpdyFrameReader
> reader(
675 new SpdyFrameReader(current_frame_buffer_
.get(),
676 current_frame_buffer_length_
));
679 bool is_control_frame
= false;
681 uint16 control_frame_type_field
=
682 SpdyConstants::DataFrameType(protocol_version());
683 // ProcessControlFrameHeader() will set current_frame_type_ to the
684 // correct value if this is a valid control frame.
685 current_frame_type_
= DATA
;
686 if (protocol_version() <= SPDY3
) {
687 bool successful_read
= reader
->ReadUInt16(&version
);
688 DCHECK(successful_read
);
689 is_control_frame
= (version
& kControlFlagMask
) != 0;
690 version
&= ~kControlFlagMask
; // Only valid for control frames.
691 if (is_control_frame
) {
692 // We check version before we check validity: version can never be
693 // 'invalid', it can only be unsupported.
694 if (version
< SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION
) ||
695 version
> SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION
) ||
696 SpdyConstants::ParseMajorVersion(version
) != protocol_version()) {
697 // Version does not match the version the framer was initialized with.
698 DVLOG(1) << "Unsupported SPDY version "
700 << " (expected " << protocol_version() << ")";
701 set_error(SPDY_UNSUPPORTED_VERSION
);
704 // Convert version from wire format to SpdyMajorVersion.
705 version
= SpdyConstants::ParseMajorVersion(version
);
707 // We check control_frame_type_field's validity in
708 // ProcessControlFrameHeader().
709 successful_read
= reader
->ReadUInt16(&control_frame_type_field
);
712 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
714 DCHECK(successful_read
);
716 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
717 DCHECK(successful_read
);
719 uint32 length_field
= 0;
720 successful_read
= reader
->ReadUInt24(&length_field
);
721 DCHECK(successful_read
);
722 remaining_data_length_
= length_field
;
723 current_frame_length_
= remaining_data_length_
+ reader
->GetBytesConsumed();
725 version
= protocol_version();
726 uint32 length_field
= 0;
727 bool successful_read
= reader
->ReadUInt24(&length_field
);
728 DCHECK(successful_read
);
730 uint8 control_frame_type_field_uint8
=
731 SpdyConstants::DataFrameType(protocol_version());
732 successful_read
= reader
->ReadUInt8(&control_frame_type_field_uint8
);
733 DCHECK(successful_read
);
734 // We check control_frame_type_field's validity in
735 // ProcessControlFrameHeader().
736 control_frame_type_field
= control_frame_type_field_uint8
;
737 is_control_frame
= (protocol_version() > SPDY3
) ?
738 control_frame_type_field
!=
739 SpdyConstants::SerializeFrameType(protocol_version(), DATA
) :
740 control_frame_type_field
!= 0;
742 if (is_control_frame
) {
743 current_frame_length_
= length_field
+ GetControlFrameHeaderSize();
745 current_frame_length_
= length_field
+ GetDataFrameMinimumSize();
748 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
749 DCHECK(successful_read
);
751 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
752 DCHECK(successful_read
);
754 remaining_data_length_
= current_frame_length_
- reader
->GetBytesConsumed();
756 // Before we accept a DATA frame, we need to make sure we're not in the
757 // middle of processing a header block.
758 const bool is_continuation_frame
= (control_frame_type_field
==
759 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION
));
760 if ((expect_continuation_
!= 0) != is_continuation_frame
) {
761 if (expect_continuation_
!= 0) {
762 DLOG(ERROR
) << "The framer was expecting to receive a CONTINUATION "
763 << "frame, but instead received frame type "
764 << control_frame_type_field
;
766 DLOG(ERROR
) << "The framer received an unexpected CONTINUATION frame.";
768 set_error(SPDY_UNEXPECTED_FRAME
);
769 return original_len
- len
;
772 DCHECK_EQ(is_control_frame
? GetControlFrameHeaderSize()
773 : GetDataFrameMinimumSize(),
774 reader
->GetBytesConsumed());
775 DCHECK_EQ(current_frame_length_
,
776 remaining_data_length_
+ reader
->GetBytesConsumed());
778 // This is just a sanity check for help debugging early frame errors.
779 if (remaining_data_length_
> 1000000u) {
780 // The strncmp for 5 is safe because we only hit this point if we
781 // have kMinCommonHeader (8) bytes
782 if (!syn_frame_processed_
&&
783 strncmp(current_frame_buffer_
.get(), "HTTP/", 5) == 0) {
784 LOG(WARNING
) << "Unexpected HTTP response to " << display_protocol_
786 probable_http_response_
= true;
788 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
789 << " session is likely corrupt.";
793 // if we're here, then we have the common header all received.
794 if (!is_control_frame
) {
795 if (protocol_version() > SPDY3
) {
796 // Catch bogus tests sending oversized DATA frames.
797 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_
)
798 << "DATA frame too large for SPDY >= 4.";
801 uint8 valid_data_flags
= 0;
802 if (protocol_version() > SPDY3
) {
804 DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
| DATA_FLAG_PADDED
;
806 valid_data_flags
= DATA_FLAG_FIN
;
809 if (current_frame_flags_
& ~valid_data_flags
) {
810 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
812 visitor_
->OnDataFrameHeader(current_frame_stream_id_
,
813 remaining_data_length_
,
814 current_frame_flags_
& DATA_FLAG_FIN
);
815 if (remaining_data_length_
> 0) {
816 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
819 if (current_frame_flags_
& DATA_FLAG_FIN
) {
820 visitor_
->OnStreamFrameData(
821 current_frame_stream_id_
, NULL
, 0, true);
823 CHANGE_STATE(SPDY_AUTO_RESET
);
827 ProcessControlFrameHeader(control_frame_type_field
);
830 return original_len
- len
;
833 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field
) {
834 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
835 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_
);
837 // TODO(mlavan): Either remove credential frames from the code entirely,
838 // or add them to parsing + serialization methods for SPDY3.
839 // Early detection of deprecated frames that we ignore.
840 if (protocol_version() <= SPDY3
) {
841 if (control_frame_type_field
== CREDENTIAL
) {
842 current_frame_type_
= CREDENTIAL
;
843 DCHECK_EQ(SPDY3
, protocol_version());
844 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
845 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
850 if (!SpdyConstants::IsValidFrameType(protocol_version(),
851 control_frame_type_field
)) {
852 if (protocol_version() <= SPDY3
) {
853 DLOG(WARNING
) << "Invalid control frame type " << control_frame_type_field
854 << " (protocol version: " << protocol_version() << ")";
855 set_error(SPDY_INVALID_CONTROL_FRAME
);
858 // In HTTP2 we ignore unknown frame types for extensibility, as long as
859 // the rest of the control frame header is valid.
860 // We rely on the visitor to check validity of current_frame_stream_id_.
861 bool valid_stream
= visitor_
->OnUnknownFrame(current_frame_stream_id_
,
862 control_frame_type_field
);
864 DVLOG(1) << "Ignoring unknown frame type.";
865 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
867 // Report an invalid frame error and close the stream if the
868 // stream_id is not valid.
869 DLOG(WARNING
) << "Unknown control frame type "
870 << control_frame_type_field
871 << " received on invalid stream "
872 << current_frame_stream_id_
;
873 set_error(SPDY_INVALID_CONTROL_FRAME
);
879 current_frame_type_
= SpdyConstants::ParseFrameType(protocol_version(),
880 control_frame_type_field
);
882 // Do some sanity checking on the control frame sizes and flags.
883 switch (current_frame_type_
) {
885 if (current_frame_length_
< GetSynStreamMinimumSize()) {
886 set_error(SPDY_INVALID_CONTROL_FRAME
);
887 } else if (current_frame_flags_
&
888 ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
889 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
893 if (current_frame_length_
< GetSynReplyMinimumSize()) {
894 set_error(SPDY_INVALID_CONTROL_FRAME
);
895 } else if (current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
896 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
900 // For SPDY versions < 4, the header has a fixed length.
901 // For SPDY version 4 and up, the RST_STREAM frame may include optional
902 // opaque data, so we only have a lower limit on the frame size.
903 if ((current_frame_length_
!= GetRstStreamMinimumSize() &&
904 protocol_version() <= SPDY3
) ||
905 (current_frame_length_
< GetRstStreamMinimumSize() &&
906 protocol_version() > SPDY3
)) {
907 set_error(SPDY_INVALID_CONTROL_FRAME
);
908 } else if (current_frame_flags_
!= 0) {
909 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
914 // Make sure that we have an integral number of 8-byte key/value pairs,
915 // plus a 4-byte length field in SPDY3 and below.
916 size_t values_prefix_size
= (protocol_version() <= SPDY3
? 4 : 0);
917 // Size of each key/value pair in bytes.
918 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
919 if (current_frame_length_
< GetSettingsMinimumSize() ||
920 (current_frame_length_
- GetControlFrameHeaderSize())
921 % setting_size
!= values_prefix_size
) {
922 DLOG(WARNING
) << "Invalid length for SETTINGS frame: "
923 << current_frame_length_
;
924 set_error(SPDY_INVALID_CONTROL_FRAME
);
925 } else if (protocol_version() <= SPDY3
&&
926 current_frame_flags_
&
927 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
928 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
929 } else if (protocol_version() > SPDY3
&&
930 current_frame_flags_
& ~SETTINGS_FLAG_ACK
) {
931 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
932 } else if (protocol_version() > SPDY3
&&
933 current_frame_flags_
& SETTINGS_FLAG_ACK
&&
934 current_frame_length_
> GetSettingsMinimumSize()) {
935 set_error(SPDY_INVALID_CONTROL_FRAME
);
940 if (current_frame_length_
!= GetPingSize()) {
941 set_error(SPDY_INVALID_CONTROL_FRAME
);
942 } else if ((protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) ||
943 (current_frame_flags_
& ~PING_FLAG_ACK
)) {
944 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
949 // For SPDY version < 4, there are only mandatory fields and the header
950 // has a fixed length. For SPDY version >= 4, optional opaque data may
951 // be appended to the GOAWAY frame, thus there is only a minimal length
953 if ((current_frame_length_
!= GetGoAwayMinimumSize() &&
954 protocol_version() <= SPDY3
) ||
955 (current_frame_length_
< GetGoAwayMinimumSize() &&
956 protocol_version() > SPDY3
)) {
957 set_error(SPDY_INVALID_CONTROL_FRAME
);
958 } else if (current_frame_flags_
!= 0) {
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
965 size_t min_size
= GetHeadersMinimumSize();
966 if (protocol_version() > SPDY3
&&
967 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
)) {
970 if (current_frame_length_
< min_size
) {
971 // TODO(mlavan): check here for HEADERS with no payload?
972 // (not allowed in SPDY4)
973 set_error(SPDY_INVALID_CONTROL_FRAME
);
974 } else if (protocol_version() <= SPDY3
&&
975 current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
976 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
977 } else if (protocol_version() > SPDY3
&&
978 current_frame_flags_
&
979 ~(CONTROL_FLAG_FIN
| HEADERS_FLAG_PRIORITY
|
980 HEADERS_FLAG_END_HEADERS
| HEADERS_FLAG_END_SEGMENT
|
981 HEADERS_FLAG_PADDED
)) {
982 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
987 if (current_frame_length_
!= GetWindowUpdateSize()) {
988 set_error(SPDY_INVALID_CONTROL_FRAME
);
989 } else if (current_frame_flags_
!= 0) {
990 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
994 if (current_frame_length_
!= GetBlockedSize() ||
995 protocol_version() <= SPDY3
) {
996 set_error(SPDY_INVALID_CONTROL_FRAME
);
997 } else if (current_frame_flags_
!= 0) {
998 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1002 if (current_frame_length_
< GetPushPromiseMinimumSize()) {
1003 set_error(SPDY_INVALID_CONTROL_FRAME
);
1004 } else if (protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) {
1005 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1006 } else if (protocol_version() > SPDY3
&&
1007 current_frame_flags_
&
1008 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
1009 HEADERS_FLAG_PADDED
)) {
1010 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1014 if (current_frame_length_
< GetContinuationMinimumSize() ||
1015 protocol_version() <= SPDY3
) {
1016 set_error(SPDY_INVALID_CONTROL_FRAME
);
1017 } else if (current_frame_flags_
& ~HEADERS_FLAG_END_HEADERS
) {
1018 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1022 if (current_frame_length_
<= GetAltSvcMinimumSize()) {
1023 set_error(SPDY_INVALID_CONTROL_FRAME
);
1024 } else if (current_frame_flags_
!= 0) {
1025 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1029 if (current_frame_length_
!= GetPrioritySize() ||
1030 protocol_version() <= SPDY3
) {
1031 set_error(SPDY_INVALID_CONTROL_FRAME
);
1032 } else if (current_frame_flags_
!= 0) {
1033 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1037 LOG(WARNING
) << "Valid " << display_protocol_
1038 << " control frame with unhandled type: "
1039 << current_frame_type_
;
1040 // This branch should be unreachable because of the frame type bounds
1041 // check above. However, we DLOG(FATAL) here in an effort to painfully
1042 // club the head of the developer who failed to keep this file in sync
1043 // with spdy_protocol.h.
1045 set_error(SPDY_INVALID_CONTROL_FRAME
);
1049 if (state_
== SPDY_ERROR
) {
1053 if (current_frame_length_
> GetControlFrameBufferMaxSize()) {
1054 DLOG(WARNING
) << "Received control frame with way too big of a payload: "
1055 << current_frame_length_
;
1056 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1060 if (current_frame_type_
== GOAWAY
) {
1061 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD
);
1065 if (current_frame_type_
== RST_STREAM
) {
1066 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD
);
1070 if (current_frame_type_
== ALTSVC
) {
1071 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD
);
1074 // Determine the frame size without variable-length data.
1075 int32 frame_size_without_variable_data
;
1076 switch (current_frame_type_
) {
1078 syn_frame_processed_
= true;
1079 frame_size_without_variable_data
= GetSynStreamMinimumSize();
1082 syn_frame_processed_
= true;
1083 frame_size_without_variable_data
= GetSynReplyMinimumSize();
1086 frame_size_without_variable_data
= GetSettingsMinimumSize();
1089 frame_size_without_variable_data
= GetHeadersMinimumSize();
1090 if (protocol_version() > SPDY3
&&
1091 current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1092 frame_size_without_variable_data
+=
1093 kPriorityDependencyPayloadSize
+
1094 kPriorityWeightPayloadSize
;
1098 frame_size_without_variable_data
= GetPushPromiseMinimumSize();
1101 frame_size_without_variable_data
= GetContinuationMinimumSize();
1104 frame_size_without_variable_data
= -1;
1108 if ((frame_size_without_variable_data
== -1) &&
1109 (current_frame_length_
> kControlFrameBufferSize
)) {
1110 // We should already be in an error state. Double-check.
1111 DCHECK_EQ(SPDY_ERROR
, state_
);
1112 if (state_
!= SPDY_ERROR
) {
1113 LOG(DFATAL
) << display_protocol_
1114 << " control frame buffer too small for fixed-length frame.";
1115 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1120 if (frame_size_without_variable_data
> 0) {
1121 // We have a control frame with a header block. We need to parse the
1122 // remainder of the control frame's header before we can parse the header
1123 // block. The start of the header block varies with the control type.
1124 DCHECK_GE(frame_size_without_variable_data
,
1125 static_cast<int32
>(current_frame_buffer_length_
));
1126 remaining_control_header_
= frame_size_without_variable_data
-
1127 current_frame_buffer_length_
;
1129 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
1133 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
1136 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
1138 size_t bytes_to_read
= std::min(*len
, max_bytes
);
1139 if (bytes_to_read
> 0) {
1140 DCHECK_GE(kControlFrameBufferSize
,
1141 current_frame_buffer_length_
+ bytes_to_read
);
1142 memcpy(current_frame_buffer_
.get() + current_frame_buffer_length_
,
1145 current_frame_buffer_length_
+= bytes_to_read
;
1146 *data
+= bytes_to_read
;
1147 *len
-= bytes_to_read
;
1149 return bytes_to_read
;
1152 size_t SpdyFramer::GetSerializedLength(
1153 const SpdyMajorVersion spdy_version
,
1154 const SpdyHeaderBlock
* headers
) {
1155 const size_t num_name_value_pairs_size
1156 = (spdy_version
< SPDY3
) ? sizeof(uint16
) : sizeof(uint32
);
1157 const size_t length_of_name_size
= num_name_value_pairs_size
;
1158 const size_t length_of_value_size
= num_name_value_pairs_size
;
1160 size_t total_length
= num_name_value_pairs_size
;
1161 for (SpdyHeaderBlock::const_iterator it
= headers
->begin();
1162 it
!= headers
->end();
1164 // We add space for the length of the name and the length of the value as
1165 // well as the length of the name and the length of the value.
1166 total_length
+= length_of_name_size
+ it
->first
.size() +
1167 length_of_value_size
+ it
->second
.size();
1169 return total_length
;
1172 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder
* frame
,
1173 const SpdyMajorVersion spdy_version
,
1174 const SpdyHeaderBlock
* headers
) {
1175 if (spdy_version
< SPDY3
) {
1176 frame
->WriteUInt16(headers
->size()); // Number of headers.
1178 frame
->WriteUInt32(headers
->size()); // Number of headers.
1180 SpdyHeaderBlock::const_iterator it
;
1181 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1182 if (spdy_version
< SPDY3
) {
1183 frame
->WriteString(it
->first
);
1184 frame
->WriteString(it
->second
);
1186 frame
->WriteStringPiece32(it
->first
);
1187 frame
->WriteStringPiece32(it
->second
);
1192 // TODO(phajdan.jr): Clean up after we no longer need
1193 // to workaround http://crbug.com/139744.
1194 #if !defined(USE_SYSTEM_ZLIB)
1196 // These constants are used by zlib to differentiate between normal data and
1197 // cookie data. Cookie data is handled specially by zlib when compressing.
1199 // kZStandardData is compressed normally, save that it will never match
1200 // against any other class of data in the window.
1201 kZStandardData
= Z_CLASS_STANDARD
,
1202 // kZCookieData is compressed in its own Huffman blocks and only matches in
1203 // its entirety and only against other kZCookieData blocks. Any matches must
1204 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1205 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1207 kZCookieData
= Z_CLASS_COOKIE
,
1208 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1209 // against the window.
1210 kZHuffmanOnlyData
= Z_CLASS_HUFFMAN_ONLY
,
1213 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1214 // needed when switching between classes of data.
1215 static void WriteZ(const base::StringPiece
& data
,
1220 // If we are switching from standard to non-standard data then we need to end
1221 // the current Huffman context to avoid it leaking between them.
1222 if (out
->clas
== kZStandardData
&&
1223 clas
!= kZStandardData
) {
1225 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1226 DCHECK_EQ(Z_OK
, rv
);
1227 DCHECK_EQ(0u, out
->avail_in
);
1228 DCHECK_LT(0u, out
->avail_out
);
1231 out
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
.data()));
1232 out
->avail_in
= data
.size();
1234 if (clas
== kZStandardData
) {
1235 rv
= deflate(out
, Z_NO_FLUSH
);
1237 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1239 if (!data
.empty()) {
1240 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1241 DCHECK_EQ(Z_OK
, rv
);
1243 DCHECK_EQ(0u, out
->avail_in
);
1244 DCHECK_LT(0u, out
->avail_out
);
1247 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1248 static void WriteLengthZ(size_t n
,
1253 DCHECK_LE(length
, sizeof(buf
));
1254 for (unsigned i
= 1; i
<= length
; i
++) {
1255 buf
[length
- i
] = n
;
1258 WriteZ(base::StringPiece(buf
, length
), clas
, out
);
1261 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1262 // manner that resists the length of the compressed data from compromising
1264 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
1265 z_stream
* z
) const {
1266 unsigned length_length
= 4;
1267 if (spdy_version_
< 3)
1270 WriteLengthZ(headers
->size(), length_length
, kZStandardData
, z
);
1272 std::map
<std::string
, std::string
>::const_iterator it
;
1273 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1274 WriteLengthZ(it
->first
.size(), length_length
, kZStandardData
, z
);
1275 WriteZ(it
->first
, kZStandardData
, z
);
1277 if (it
->first
== "cookie") {
1278 // We require the cookie values (save for the last) to end with a
1279 // semicolon and (save for the first) to start with a space. This is
1280 // typically the format that we are given them in but we reserialize them
1283 std::vector
<base::StringPiece
> cookie_values
;
1284 size_t cookie_length
= 0;
1285 base::StringPiece
cookie_data(it
->second
);
1288 while (!cookie_data
.empty() &&
1289 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
1290 cookie_data
.remove_prefix(1);
1292 if (cookie_data
.empty())
1296 for (i
= 0; i
< cookie_data
.size(); i
++) {
1297 if (cookie_data
[i
] == ';')
1300 if (i
< cookie_data
.size()) {
1301 if (!IsCookieEmpty(cookie_data
.substr(0, i
))) {
1302 cookie_values
.push_back(cookie_data
.substr(0, i
));
1303 cookie_length
+= i
+ 2 /* semicolon and space */;
1305 cookie_data
.remove_prefix(i
+ 1);
1307 if (!IsCookieEmpty(cookie_data
)) {
1308 cookie_values
.push_back(cookie_data
);
1309 cookie_length
+= cookie_data
.size();
1310 } else if (cookie_length
> 2) {
1311 cookie_length
-= 2 /* compensate for previously added length */;
1313 cookie_data
.remove_prefix(i
);
1317 WriteLengthZ(cookie_length
, length_length
, kZStandardData
, z
);
1318 for (size_t i
= 0; i
< cookie_values
.size(); i
++) {
1320 // Since zlib will only back-reference complete cookies, a cookie that
1321 // is currently last (and so doesn't have a trailing semicolon) won't
1322 // match if it's later in a non-final position. The same is true of
1323 // the first cookie.
1324 if (i
== 0 && cookie_values
.size() == 1) {
1325 cookie
= cookie_values
[i
].as_string();
1326 } else if (i
== 0) {
1327 cookie
= cookie_values
[i
].as_string() + ";";
1328 } else if (i
< cookie_values
.size() - 1) {
1329 cookie
= " " + cookie_values
[i
].as_string() + ";";
1331 cookie
= " " + cookie_values
[i
].as_string();
1333 WriteZ(cookie
, kZCookieData
, z
);
1335 } else if (it
->first
== "accept" ||
1336 it
->first
== "accept-charset" ||
1337 it
->first
== "accept-encoding" ||
1338 it
->first
== "accept-language" ||
1339 it
->first
== "host" ||
1340 it
->first
== "version" ||
1341 it
->first
== "method" ||
1342 it
->first
== "scheme" ||
1343 it
->first
== ":host" ||
1344 it
->first
== ":version" ||
1345 it
->first
== ":method" ||
1346 it
->first
== ":scheme" ||
1347 it
->first
== "user-agent") {
1348 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1349 WriteZ(it
->second
, kZStandardData
, z
);
1351 // Non-whitelisted headers are Huffman compressed in their own block, but
1352 // don't match against the window.
1353 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1354 WriteZ(it
->second
, kZHuffmanOnlyData
, z
);
1359 int rv
= deflate(z
, Z_SYNC_FLUSH
);
1360 DCHECK_EQ(Z_OK
, rv
);
1361 z
->clas
= kZStandardData
;
1364 #endif // !defined(USE_SYSTEM_ZLIB)
1366 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
1368 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
1369 const size_t original_len
= len
;
1371 if (remaining_control_header_
> 0) {
1372 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1373 remaining_control_header_
);
1374 remaining_control_header_
-= bytes_read
;
1375 remaining_data_length_
-= bytes_read
;
1378 if (remaining_control_header_
== 0) {
1379 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1380 current_frame_buffer_length_
);
1381 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1383 switch (current_frame_type_
) {
1386 DCHECK_GE(SPDY3
, protocol_version());
1387 bool successful_read
= true;
1388 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1389 DCHECK(successful_read
);
1390 if (current_frame_stream_id_
== 0) {
1391 set_error(SPDY_INVALID_CONTROL_FRAME
);
1395 SpdyStreamId associated_to_stream_id
= kInvalidStream
;
1396 successful_read
= reader
.ReadUInt31(&associated_to_stream_id
);
1397 DCHECK(successful_read
);
1399 SpdyPriority priority
= 0;
1400 successful_read
= reader
.ReadUInt8(&priority
);
1401 DCHECK(successful_read
);
1402 if (protocol_version() <= SPDY2
) {
1403 priority
= priority
>> 6;
1405 priority
= priority
>> 5;
1408 // Seek past unused byte; used to be credential slot in SPDY 3.
1411 DCHECK(reader
.IsDoneReading());
1412 if (debug_visitor_
) {
1413 debug_visitor_
->OnReceiveCompressedFrame(
1414 current_frame_stream_id_
,
1415 current_frame_type_
,
1416 current_frame_length_
);
1418 visitor_
->OnSynStream(
1419 current_frame_stream_id_
,
1420 associated_to_stream_id
,
1422 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1423 (current_frame_flags_
& CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
1425 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1428 if (protocol_version() > SPDY3
&&
1429 current_frame_flags_
& SETTINGS_FLAG_ACK
) {
1430 visitor_
->OnSettingsAck();
1431 CHANGE_STATE(SPDY_AUTO_RESET
);
1433 visitor_
->OnSettings(current_frame_flags_
&
1434 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
);
1435 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
1440 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1442 if (protocol_version() > SPDY3
) {
1443 DCHECK_EQ(HEADERS
, current_frame_type_
);
1445 bool successful_read
= true;
1446 if (protocol_version() <= SPDY3
) {
1447 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1448 DCHECK(successful_read
);
1450 if (current_frame_stream_id_
== 0) {
1451 set_error(SPDY_INVALID_CONTROL_FRAME
);
1454 if (protocol_version() <= SPDY2
) {
1455 // SPDY 2 had two unused bytes here. Seek past them.
1458 if (protocol_version() > SPDY3
&&
1459 !(current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) &&
1460 current_frame_type_
== HEADERS
) {
1461 expect_continuation_
= current_frame_stream_id_
;
1462 end_stream_when_done_
= current_frame_flags_
& CONTROL_FLAG_FIN
;
1464 const bool has_priority
=
1465 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0;
1466 uint32 priority
= 0;
1467 if (protocol_version() > SPDY3
&& has_priority
) {
1468 // TODO(jgraettinger): Process dependency rather than ignoring it.
1469 reader
.Seek(kPriorityDependencyPayloadSize
);
1471 successful_read
= reader
.ReadUInt8(&weight
);
1472 if (successful_read
) {
1473 priority
= MapWeightToPriority(weight
);
1476 DCHECK(reader
.IsDoneReading());
1477 if (debug_visitor_
) {
1478 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1479 SpdyFrameType reported_type
= current_frame_type_
;
1480 if (protocol_version() > SPDY3
&& has_priority
) {
1481 reported_type
= SYN_STREAM
;
1483 debug_visitor_
->OnReceiveCompressedFrame(
1484 current_frame_stream_id_
,
1486 current_frame_length_
);
1488 if (current_frame_type_
== SYN_REPLY
) {
1489 visitor_
->OnSynReply(
1490 current_frame_stream_id_
,
1491 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0);
1492 } else if (protocol_version() > SPDY3
&&
1493 current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1494 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1495 // can be made independent of wire changes.
1496 visitor_
->OnSynStream(
1497 current_frame_stream_id_
,
1498 0, // associated_to_stream_id
1500 current_frame_flags_
& CONTROL_FLAG_FIN
,
1501 false); // unidirectional
1503 visitor_
->OnHeaders(
1504 current_frame_stream_id_
,
1505 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1506 expect_continuation_
== 0);
1509 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
1513 DCHECK_LT(SPDY3
, protocol_version());
1514 if (current_frame_stream_id_
== 0) {
1515 set_error(SPDY_INVALID_CONTROL_FRAME
);
1518 SpdyStreamId promised_stream_id
= kInvalidStream
;
1519 bool successful_read
= reader
.ReadUInt31(&promised_stream_id
);
1520 DCHECK(successful_read
);
1521 DCHECK(reader
.IsDoneReading());
1522 if (promised_stream_id
== 0) {
1523 set_error(SPDY_INVALID_CONTROL_FRAME
);
1526 if (!(current_frame_flags_
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
1527 expect_continuation_
= current_frame_stream_id_
;
1529 if (debug_visitor_
) {
1530 debug_visitor_
->OnReceiveCompressedFrame(
1531 current_frame_stream_id_
,
1532 current_frame_type_
,
1533 current_frame_length_
);
1535 visitor_
->OnPushPromise(current_frame_stream_id_
,
1537 (current_frame_flags_
&
1538 PUSH_PROMISE_FLAG_END_PUSH_PROMISE
) != 0);
1540 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
1544 // Check to make sure the stream id of the current frame is
1545 // the same as that of the preceding frame.
1546 // If we're at this point we should already know that
1547 // expect_continuation_ != 0, so this doubles as a check
1548 // that current_frame_stream_id != 0.
1549 if (current_frame_stream_id_
!= expect_continuation_
) {
1550 set_error(SPDY_INVALID_CONTROL_FRAME
);
1553 if (current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) {
1554 expect_continuation_
= 0;
1556 if (debug_visitor_
) {
1557 debug_visitor_
->OnReceiveCompressedFrame(
1558 current_frame_stream_id_
,
1559 current_frame_type_
,
1560 current_frame_length_
);
1562 visitor_
->OnContinuation(current_frame_stream_id_
,
1563 (current_frame_flags_
&
1564 HEADERS_FLAG_END_HEADERS
) != 0);
1566 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1572 return original_len
- len
;
1575 // Does not buffer the control payload. Instead, either passes directly to the
1576 // visitor or decompresses and then passes directly to the visitor, via
1577 // IncrementallyDeliverControlFrameHeaderData() or
1578 // IncrementallyDecompressControlFrameHeaderData() respectively.
1579 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
1581 bool is_hpack_header_block
) {
1582 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
1584 bool processed_successfully
= true;
1585 if (current_frame_type_
!= SYN_STREAM
&&
1586 current_frame_type_
!= SYN_REPLY
&&
1587 current_frame_type_
!= HEADERS
&&
1588 current_frame_type_
!= PUSH_PROMISE
&&
1589 current_frame_type_
!= CONTINUATION
) {
1590 LOG(DFATAL
) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1592 size_t process_bytes
= std::min(
1593 data_len
, remaining_data_length_
- remaining_padding_payload_length_
);
1594 if (is_hpack_header_block
) {
1595 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1596 current_frame_stream_id_
, data
, process_bytes
)) {
1597 // TODO(jgraettinger): Finer-grained HPACK error codes.
1598 set_error(SPDY_DECOMPRESS_FAILURE
);
1599 processed_successfully
= false;
1601 } else if (process_bytes
> 0) {
1602 if (enable_compression_
&& protocol_version() <= SPDY3
) {
1603 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
1604 current_frame_stream_id_
, data
, process_bytes
);
1606 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
1607 current_frame_stream_id_
, data
, process_bytes
);
1610 remaining_data_length_
-= process_bytes
;
1612 // Handle the case that there is no futher data in this frame.
1613 if (remaining_data_length_
== remaining_padding_payload_length_
&&
1614 processed_successfully
) {
1615 if (expect_continuation_
== 0) {
1616 if (is_hpack_header_block
) {
1617 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1618 current_frame_stream_id_
)) {
1619 set_error(SPDY_DECOMPRESS_FAILURE
);
1620 processed_successfully
= false;
1622 // TODO(jgraettinger): To be removed with migration to
1623 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1624 // block, delivered via reentrant call to
1625 // ProcessControlFrameHeaderBlock().
1626 DeliverHpackBlockAsSpdy3Block();
1627 return process_bytes
;
1630 // The complete header block has been delivered. We send a zero-length
1631 // OnControlFrameHeaderData() to indicate this.
1632 visitor_
->OnControlFrameHeaderData(current_frame_stream_id_
, NULL
, 0);
1635 if (processed_successfully
) {
1636 CHANGE_STATE(SPDY_CONSUME_PADDING
);
1641 if (!processed_successfully
) {
1645 // Return amount processed.
1646 return process_bytes
;
1649 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
1651 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD
, state_
);
1652 DCHECK_EQ(SETTINGS
, current_frame_type_
);
1653 size_t unprocessed_bytes
= std::min(data_len
, remaining_data_length_
);
1654 size_t processed_bytes
= 0;
1656 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
1658 // Loop over our incoming data.
1659 while (unprocessed_bytes
> 0) {
1660 // Process up to one setting at a time.
1661 size_t processing
= std::min(
1663 static_cast<size_t>(setting_size
- settings_scratch_
.setting_buf_len
));
1665 // Check if we have a complete setting in our input.
1666 if (processing
== setting_size
) {
1667 // Parse the setting directly out of the input without buffering.
1668 if (!ProcessSetting(data
+ processed_bytes
)) {
1669 set_error(SPDY_INVALID_CONTROL_FRAME
);
1670 return processed_bytes
;
1673 // Continue updating settings_scratch_.setting_buf.
1674 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
1675 data
+ processed_bytes
,
1677 settings_scratch_
.setting_buf_len
+= processing
;
1679 // Check if we have a complete setting buffered.
1680 if (settings_scratch_
.setting_buf_len
== setting_size
) {
1681 if (!ProcessSetting(settings_scratch_
.setting_buf
)) {
1682 set_error(SPDY_INVALID_CONTROL_FRAME
);
1683 return processed_bytes
;
1685 // Reset settings_scratch_.setting_buf for our next setting.
1686 settings_scratch_
.setting_buf_len
= 0;
1691 unprocessed_bytes
-= processing
;
1692 processed_bytes
+= processing
;
1695 // Check if we're done handling this SETTINGS frame.
1696 remaining_data_length_
-= processed_bytes
;
1697 if (remaining_data_length_
== 0) {
1698 visitor_
->OnSettingsEnd();
1699 CHANGE_STATE(SPDY_AUTO_RESET
);
1702 return processed_bytes
;
1705 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1706 DCHECK_LT(SPDY3
, protocol_version());
1707 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
1709 const SpdyNameValueBlock
& block
= GetHpackDecoder()->decoded_block();
1710 if (block
.empty()) {
1711 // Special-case this to make tests happy.
1712 ProcessControlFrameHeaderBlock(NULL
, 0, false);
1715 SpdyFrameBuilder
builder(
1716 GetSerializedLength(protocol_version(), &block
),
1719 SerializeNameValueBlockWithoutCompression(&builder
, block
);
1720 scoped_ptr
<SpdyFrame
> frame(builder
.take());
1722 // Preserve padding length, and reset it after the re-entrant call.
1723 size_t remaining_padding
= remaining_padding_payload_length_
;
1725 remaining_padding_payload_length_
= 0;
1726 remaining_data_length_
= frame
->size();
1728 ProcessControlFrameHeaderBlock(frame
->data(), frame
->size(), false);
1730 remaining_padding_payload_length_
= remaining_padding
;
1731 remaining_data_length_
= remaining_padding
;
1734 bool SpdyFramer::ProcessSetting(const char* data
) {
1741 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1742 if (protocol_version() <= SPDY3
) {
1743 const uint32 id_and_flags_wire
= *(reinterpret_cast<const uint32
*>(data
));
1744 SettingsFlagsAndId id_and_flags
=
1745 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire
);
1746 id_field
= id_and_flags
.id();
1747 flags
= id_and_flags
.flags();
1748 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 4)));
1750 id_field
= ntohs(*(reinterpret_cast<const uint16
*>(data
)));
1751 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 2)));
1755 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field
)) {
1756 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_field
;
1757 if (protocol_version() <= SPDY3
) {
1760 // In HTTP2 we ignore unknown settings for extensibility.
1764 id
= SpdyConstants::ParseSettingId(protocol_version(), id_field
);
1766 if (protocol_version() <= SPDY3
) {
1767 // Detect duplicates.
1768 if (id
<= settings_scratch_
.last_setting_id
) {
1769 DLOG(WARNING
) << "Duplicate entry or invalid ordering for id " << id
1770 << " in " << display_protocol_
<< " SETTINGS frame "
1771 << "(last setting id was "
1772 << settings_scratch_
.last_setting_id
<< ").";
1775 settings_scratch_
.last_setting_id
= id
;
1778 uint8 kFlagsMask
= SETTINGS_FLAG_PLEASE_PERSIST
| SETTINGS_FLAG_PERSISTED
;
1779 if ((flags
& ~(kFlagsMask
)) != 0) {
1780 DLOG(WARNING
) << "Unknown SETTINGS flags provided for id " << id
<< ": "
1786 // Validation succeeded. Pass on to visitor.
1787 visitor_
->OnSetting(id
, flags
, value
);
1791 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
1792 size_t original_len
= len
;
1793 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1794 remaining_data_length_
);
1795 remaining_data_length_
-= bytes_read
;
1796 if (remaining_data_length_
== 0) {
1797 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1798 current_frame_buffer_length_
);
1799 reader
.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1801 // Use frame-specific handlers.
1802 switch (current_frame_type_
) {
1805 bool is_ack
= protocol_version() > SPDY3
&&
1806 (current_frame_flags_
& PING_FLAG_ACK
);
1807 bool successful_read
= true;
1808 if (protocol_version() <= SPDY3
) {
1810 successful_read
= reader
.ReadUInt32(&id32
);
1813 successful_read
= reader
.ReadUInt64(&id
);
1815 DCHECK(successful_read
);
1816 DCHECK(reader
.IsDoneReading());
1817 visitor_
->OnPing(id
, is_ack
);
1820 case WINDOW_UPDATE
: {
1821 uint32 delta_window_size
= 0;
1822 bool successful_read
= true;
1823 if (protocol_version() <= SPDY3
) {
1824 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1825 DCHECK(successful_read
);
1827 successful_read
= reader
.ReadUInt32(&delta_window_size
);
1828 DCHECK(successful_read
);
1829 DCHECK(reader
.IsDoneReading());
1830 visitor_
->OnWindowUpdate(current_frame_stream_id_
,
1835 DCHECK_LT(SPDY3
, protocol_version());
1836 DCHECK(reader
.IsDoneReading());
1837 visitor_
->OnBlocked(current_frame_stream_id_
);
1841 DCHECK_LT(SPDY3
, protocol_version());
1842 uint32 parent_stream_id
;
1845 bool successful_read
= true;
1846 successful_read
= reader
.ReadUInt32(&parent_stream_id
);
1847 DCHECK(successful_read
);
1848 // Exclusivity is indicated by a single bit flag.
1849 exclusive
= (parent_stream_id
>> 31) != 0;
1850 // Zero out the highest-order bit to get the parent stream id.
1851 parent_stream_id
&= 0x7fffffff;
1852 successful_read
= reader
.ReadUInt8(&weight
);
1853 DCHECK(successful_read
);
1854 DCHECK(reader
.IsDoneReading());
1855 visitor_
->OnPriority(
1856 current_frame_stream_id_
, parent_stream_id
, weight
, exclusive
);
1861 LOG(FATAL
) << "Unhandled control frame " << current_frame_type_
;
1864 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
1866 return original_len
- len
;
1869 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data
, size_t len
) {
1873 // Clamp to the actual remaining payload.
1874 if (len
> remaining_data_length_
) {
1875 len
= remaining_data_length_
;
1877 size_t original_len
= len
;
1879 // Check if we had already read enough bytes to parse the GOAWAY header.
1880 const size_t header_size
= GetGoAwayMinimumSize();
1881 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1882 bool already_parsed_header
= (unread_header_bytes
== 0);
1883 if (!already_parsed_header
) {
1884 // Buffer the new GOAWAY header bytes we got.
1885 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1887 // Do we have enough to parse the constant size GOAWAY header?
1888 if (current_frame_buffer_length_
== header_size
) {
1889 // Parse out the last good stream id.
1890 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1891 current_frame_buffer_length_
);
1892 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1893 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1894 DCHECK(successful_read
);
1896 // In SPDYv3 and up, frames also specify a status code - parse it out.
1897 SpdyGoAwayStatus status
= GOAWAY_OK
;
1898 if (protocol_version() >= SPDY3
) {
1899 uint32 status_raw
= GOAWAY_OK
;
1900 successful_read
= reader
.ReadUInt32(&status_raw
);
1901 DCHECK(successful_read
);
1902 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1904 status
= SpdyConstants::ParseGoAwayStatus(protocol_version(),
1907 if (protocol_version() > SPDY3
) {
1908 // Treat unrecognized status codes as INTERNAL_ERROR as
1909 // recommended by the HTTP/2 spec.
1910 status
= GOAWAY_INTERNAL_ERROR
;
1914 // Finished parsing the GOAWAY header, call frame handler.
1915 visitor_
->OnGoAway(current_frame_stream_id_
, status
);
1919 // Handle remaining data as opaque.
1920 bool processed_successfully
= true;
1922 processed_successfully
= visitor_
->OnGoAwayFrameData(data
, len
);
1924 remaining_data_length_
-= original_len
;
1925 if (!processed_successfully
) {
1926 set_error(SPDY_GOAWAY_FRAME_CORRUPT
);
1927 } else if (remaining_data_length_
== 0) {
1928 // Signal that there is not more opaque data.
1929 visitor_
->OnGoAwayFrameData(NULL
, 0);
1930 CHANGE_STATE(SPDY_AUTO_RESET
);
1932 return original_len
;
1935 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data
, size_t len
) {
1939 // Clamp to the actual remaining payload.
1940 if (len
> remaining_data_length_
) {
1941 len
= remaining_data_length_
;
1943 size_t original_len
= len
;
1945 // Check if we had already read enough bytes to parse the fixed-length portion
1946 // of the RST_STREAM frame.
1947 const size_t header_size
= GetRstStreamMinimumSize();
1948 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1949 bool already_parsed_header
= (unread_header_bytes
== 0);
1950 if (!already_parsed_header
) {
1951 // Buffer the new RST_STREAM header bytes we got.
1952 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1954 // Do we have enough to parse the constant size RST_STREAM header?
1955 if (current_frame_buffer_length_
== header_size
) {
1956 // Parse out the last good stream id.
1957 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1958 current_frame_buffer_length_
);
1959 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1960 if (protocol_version() <= SPDY3
) {
1961 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1962 DCHECK(successful_read
);
1965 SpdyRstStreamStatus status
= RST_STREAM_INVALID
;
1966 uint32 status_raw
= status
;
1967 bool successful_read
= reader
.ReadUInt32(&status_raw
);
1968 DCHECK(successful_read
);
1969 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1971 status
= static_cast<SpdyRstStreamStatus
>(status_raw
);
1973 if (protocol_version() > SPDY3
) {
1974 // Treat unrecognized status codes as INTERNAL_ERROR as
1975 // recommended by the HTTP/2 spec.
1976 status
= RST_STREAM_INTERNAL_ERROR
;
1979 // Finished parsing the RST_STREAM header, call frame handler.
1980 visitor_
->OnRstStream(current_frame_stream_id_
, status
);
1984 // Handle remaining data as opaque.
1985 bool processed_successfully
= true;
1987 processed_successfully
= visitor_
->OnRstStreamFrameData(data
, len
);
1989 remaining_data_length_
-= original_len
;
1990 if (!processed_successfully
) {
1991 set_error(SPDY_RST_STREAM_FRAME_CORRUPT
);
1992 } else if (remaining_data_length_
== 0) {
1993 // Signal that there is not more opaque data.
1994 visitor_
->OnRstStreamFrameData(NULL
, 0);
1995 CHANGE_STATE(SPDY_AUTO_RESET
);
1997 return original_len
;
2000 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data
, size_t len
) {
2005 // Clamp to the actual remaining payload.
2006 len
= std::min(len
, remaining_data_length_
);
2008 size_t processed_bytes
= 0;
2009 size_t processing
= 0;
2010 size_t bytes_remaining
;
2015 if (altsvc_scratch_
.pid_len
== 0) {
2016 // The size of the frame up to the PID_LEN field.
2017 size_t fixed_len_portion
= GetAltSvcMinimumSize() - 1;
2018 bytes_remaining
= fixed_len_portion
- current_frame_buffer_length_
;
2019 processing
= std::min(len
, bytes_remaining
);
2020 // Buffer the new ALTSVC bytes we got.
2021 UpdateCurrentFrameBuffer(&data
, &len
, processing
);
2023 // Do we have enough to parse the length of the protocol id?
2024 if (current_frame_buffer_length_
== fixed_len_portion
) {
2025 // Parse out the max age, port, and pid_len.
2026 SpdyFrameReader
reader(current_frame_buffer_
.get(),
2027 current_frame_buffer_length_
);
2028 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2029 bool successful_read
= reader
.ReadUInt32(&altsvc_scratch_
.max_age
);
2030 reader
.ReadUInt16(&altsvc_scratch_
.port
);
2031 reader
.Seek(1); // Reserved byte.
2032 successful_read
= successful_read
&&
2033 reader
.ReadUInt8(&altsvc_scratch_
.pid_len
);
2034 DCHECK(successful_read
);
2035 // Sanity check length value.
2036 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
>=
2037 current_frame_length_
) {
2038 set_error(SPDY_INVALID_CONTROL_FRAME
);
2041 altsvc_scratch_
.protocol_id
.reset(
2042 new char[size_t(altsvc_scratch_
.pid_len
)]);
2044 processed_bytes
+= processing
;
2046 } else if (altsvc_scratch_
.pid_buf_len
< altsvc_scratch_
.pid_len
) {
2047 // Buffer protocol id field as in comes in.
2048 buffer
= altsvc_scratch_
.protocol_id
.get();
2049 buffer_len
= &altsvc_scratch_
.pid_buf_len
;
2050 bytes_remaining
= altsvc_scratch_
.pid_len
- altsvc_scratch_
.pid_buf_len
;
2051 } else if (altsvc_scratch_
.host_len
== 0) {
2052 // Parse out the host length.
2054 altsvc_scratch_
.host_len
= *reinterpret_cast<const uint8
*>(data
);
2055 // Sanity check length value.
2056 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
+
2057 altsvc_scratch_
.host_len
> current_frame_length_
) {
2058 set_error(SPDY_INVALID_CONTROL_FRAME
);
2061 altsvc_scratch_
.host
.reset(new char[altsvc_scratch_
.host_len
]);
2062 // Once we have host length, we can also determine the origin length
2063 // by process of elimination.
2064 altsvc_scratch_
.origin_len
= current_frame_length_
-
2065 GetAltSvcMinimumSize() -
2066 altsvc_scratch_
.pid_len
-
2067 altsvc_scratch_
.host_len
;
2068 if (altsvc_scratch_
.origin_len
> 0) {
2069 altsvc_scratch_
.origin
.reset(new char[altsvc_scratch_
.origin_len
]);
2072 processed_bytes
+= processing
;
2075 } else if (altsvc_scratch_
.host_buf_len
< altsvc_scratch_
.host_len
) {
2076 // Buffer host field as it comes in.
2077 // TODO(mlavan): check formatting for host and origin
2078 buffer
= altsvc_scratch_
.host
.get();
2079 buffer_len
= &altsvc_scratch_
.host_buf_len
;
2080 bytes_remaining
= altsvc_scratch_
.host_len
- altsvc_scratch_
.host_buf_len
;
2082 // Buffer (optional) origin field as it comes in.
2083 if (altsvc_scratch_
.origin_len
<= 0) {
2084 set_error(SPDY_INVALID_CONTROL_FRAME
);
2087 buffer
= altsvc_scratch_
.origin
.get();
2088 buffer_len
= &altsvc_scratch_
.origin_buf_len
;
2089 bytes_remaining
= remaining_data_length_
-
2091 altsvc_scratch_
.origin_buf_len
;
2092 if (len
> bytes_remaining
) {
2093 // This is our last field; there shouldn't be any more bytes.
2094 set_error(SPDY_INVALID_CONTROL_FRAME
);
2099 // Copy data bytes into the appropriate field.
2100 processing
= std::min(len
, bytes_remaining
);
2101 memcpy(buffer
+ *buffer_len
,
2104 *buffer_len
+= processing
;
2106 processed_bytes
+= processing
;
2110 remaining_data_length_
-= processed_bytes
;
2111 if (remaining_data_length_
== 0) {
2112 visitor_
->OnAltSvc(current_frame_stream_id_
,
2113 altsvc_scratch_
.max_age
,
2114 altsvc_scratch_
.port
,
2115 StringPiece(altsvc_scratch_
.protocol_id
.get(),
2116 altsvc_scratch_
.pid_len
),
2117 StringPiece(altsvc_scratch_
.host
.get(),
2118 altsvc_scratch_
.host_len
),
2119 StringPiece(altsvc_scratch_
.origin
.get(),
2120 altsvc_scratch_
.origin_len
));
2121 CHANGE_STATE(SPDY_AUTO_RESET
);
2124 return processed_bytes
;
2127 // TODO(raullenchai): ProcessFramePaddingLength should be able to deal with
2128 // HEADERS_FLAG_PADDED and PUSH_PROMISE_FLAG_PADDED as well (see b/15777051).
2129 size_t SpdyFramer::ProcessFramePaddingLength(const char* data
, size_t len
) {
2130 DCHECK_EQ(SPDY_READ_PADDING_LENGTH
, state_
);
2131 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
2133 size_t original_len
= len
;
2134 if (current_frame_flags_
& DATA_FLAG_PADDED
) {
2136 if (remaining_data_length_
< 1) {
2137 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2141 remaining_padding_payload_length_
= *reinterpret_cast<const uint8
*>(data
);
2144 --remaining_data_length_
;
2146 // We don't have the data available for parsing the pad length field. Keep
2152 if (remaining_padding_payload_length_
> remaining_data_length_
) {
2153 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2156 if (current_frame_type_
== DATA
) {
2157 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
2159 DCHECK(current_frame_type_
== HEADERS
||
2160 current_frame_type_
== PUSH_PROMISE
||
2161 current_frame_type_
== SYN_STREAM
||
2162 current_frame_type_
== SYN_REPLY
)
2163 << current_frame_type_
;
2164 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
2166 return original_len
- len
;
2169 size_t SpdyFramer::ProcessFramePadding(const char* data
, size_t len
) {
2170 DCHECK_EQ(SPDY_CONSUME_PADDING
, state_
);
2172 size_t original_len
= len
;
2173 if (remaining_padding_payload_length_
> 0) {
2174 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
2175 size_t amount_to_discard
= std::min(remaining_padding_payload_length_
, len
);
2176 if (current_frame_type_
== DATA
&& amount_to_discard
> 0) {
2177 // The visitor needs to know about padding so it can send window updates.
2178 // Communicate the padding to the visitor through a NULL data pointer,
2179 // with a nonzero size.
2180 visitor_
->OnStreamFrameData(
2181 current_frame_stream_id_
, NULL
, amount_to_discard
, false);
2183 data
+= amount_to_discard
;
2184 len
-= amount_to_discard
;
2185 remaining_padding_payload_length_
-= amount_to_discard
;
2186 remaining_data_length_
-= amount_to_discard
;
2189 if (remaining_data_length_
== 0) {
2190 // If the FIN flag is set, or this ends a header block which set FIN,
2191 // inform the visitor of EOF via a 0-length data frame.
2192 if (expect_continuation_
== 0 &&
2193 ((current_frame_flags_
& CONTROL_FLAG_FIN
) != 0 ||
2194 end_stream_when_done_
)) {
2195 end_stream_when_done_
= false;
2196 visitor_
->OnStreamFrameData(current_frame_stream_id_
, NULL
, 0, true);
2198 CHANGE_STATE(SPDY_AUTO_RESET
);
2200 return original_len
- len
;
2203 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
2204 size_t original_len
= len
;
2205 if (remaining_data_length_
- remaining_padding_payload_length_
> 0) {
2206 size_t amount_to_forward
= std::min(
2207 remaining_data_length_
- remaining_padding_payload_length_
, len
);
2208 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
2209 // Only inform the visitor if there is data.
2210 if (amount_to_forward
) {
2211 visitor_
->OnStreamFrameData(
2212 current_frame_stream_id_
, data
, amount_to_forward
, false);
2215 data
+= amount_to_forward
;
2216 len
-= amount_to_forward
;
2217 remaining_data_length_
-= amount_to_forward
;
2220 if (remaining_data_length_
== remaining_padding_payload_length_
) {
2221 CHANGE_STATE(SPDY_CONSUME_PADDING
);
2223 return original_len
- len
;
2226 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2228 size_t original_len
= len
;
2229 if (remaining_data_length_
> 0) {
2230 size_t amount_to_ignore
= std::min(remaining_data_length_
, len
);
2231 len
-= amount_to_ignore
;
2232 remaining_data_length_
-= amount_to_ignore
;
2235 if (remaining_data_length_
== 0) {
2236 CHANGE_STATE(SPDY_AUTO_RESET
);
2238 return original_len
- len
;
2241 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
2242 size_t header_length
,
2243 SpdyHeaderBlock
* block
) const {
2244 SpdyFrameReader
reader(header_data
, header_length
);
2246 // Read number of headers.
2248 if (protocol_version() <= SPDY2
) {
2250 if (!reader
.ReadUInt16(&temp
)) {
2251 DVLOG(1) << "Unable to read number of headers.";
2256 if (!reader
.ReadUInt32(&num_headers
)) {
2257 DVLOG(1) << "Unable to read number of headers.";
2262 // Read each header.
2263 for (uint32 index
= 0; index
< num_headers
; ++index
) {
2264 base::StringPiece temp
;
2266 // Read header name.
2267 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2268 : !reader
.ReadStringPiece32(&temp
)) {
2269 DVLOG(1) << "Unable to read header name (" << index
+ 1 << " of "
2270 << num_headers
<< ").";
2273 std::string name
= temp
.as_string();
2275 // Read header value.
2276 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2277 : !reader
.ReadStringPiece32(&temp
)) {
2278 DVLOG(1) << "Unable to read header value (" << index
+ 1 << " of "
2279 << num_headers
<< ").";
2282 std::string value
= temp
.as_string();
2284 // Ensure no duplicates.
2285 if (block
->find(name
) != block
->end()) {
2286 DVLOG(1) << "Duplicate header '" << name
<< "' (" << index
+ 1 << " of "
2287 << num_headers
<< ").";
2292 (*block
)[name
] = value
;
2294 return reader
.GetBytesConsumed();
2297 SpdySerializedFrame
* SpdyFramer::SerializeData(
2298 const SpdyDataIR
& data_ir
) const {
2299 uint8 flags
= DATA_FLAG_NONE
;
2300 if (data_ir
.fin()) {
2301 flags
= DATA_FLAG_FIN
;
2304 if (protocol_version() > SPDY3
) {
2305 int num_padding_fields
= 0;
2306 if (data_ir
.padded()) {
2307 flags
|= DATA_FLAG_PADDED
;
2308 ++num_padding_fields
;
2311 const size_t size_with_padding
= num_padding_fields
+
2312 data_ir
.data().length() + data_ir
.padding_payload_len() +
2313 GetDataFrameMinimumSize();
2314 SpdyFrameBuilder
builder(size_with_padding
, protocol_version());
2315 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2316 if (data_ir
.padded()) {
2317 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2319 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2320 if (data_ir
.padding_payload_len() > 0) {
2321 string padding
= string(data_ir
.padding_payload_len(), '0');
2322 builder
.WriteBytes(padding
.data(), padding
.length());
2324 DCHECK_EQ(size_with_padding
, builder
.length());
2325 return builder
.take();
2327 const size_t size
= GetDataFrameMinimumSize() + data_ir
.data().length();
2328 SpdyFrameBuilder
builder(size
, protocol_version());
2329 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2330 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2331 DCHECK_EQ(size
, builder
.length());
2332 return builder
.take();
2336 SpdySerializedFrame
* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2337 const SpdyDataIR
& data_ir
) const {
2338 uint8 flags
= DATA_FLAG_NONE
;
2339 if (data_ir
.fin()) {
2340 flags
= DATA_FLAG_FIN
;
2343 size_t frame_size
= GetDataFrameMinimumSize();
2344 size_t num_padding_fields
= 0;
2345 if (protocol_version() > SPDY3
) {
2346 if (data_ir
.padded()) {
2347 flags
|= DATA_FLAG_PADDED
;
2348 ++num_padding_fields
;
2350 frame_size
+= num_padding_fields
;
2353 SpdyFrameBuilder
builder(frame_size
, protocol_version());
2354 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2355 if (protocol_version() > SPDY3
) {
2356 if (data_ir
.padded()) {
2357 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2359 builder
.OverwriteLength(*this, num_padding_fields
+
2360 data_ir
.data().length() + data_ir
.padding_payload_len());
2362 builder
.OverwriteLength(*this, data_ir
.data().length());
2364 DCHECK_EQ(frame_size
, builder
.length());
2365 return builder
.take();
2368 SpdySerializedFrame
* SpdyFramer::SerializeSynStream(
2369 const SpdySynStreamIR
& syn_stream
) {
2370 DCHECK_GE(SPDY3
, protocol_version());
2372 if (syn_stream
.fin()) {
2373 flags
|= CONTROL_FLAG_FIN
;
2375 if (syn_stream
.unidirectional()) {
2376 // TODO(hkhalil): invalid for HTTP2.
2377 flags
|= CONTROL_FLAG_UNIDIRECTIONAL
;
2380 // Sanitize priority.
2381 uint8 priority
= syn_stream
.priority();
2382 if (priority
> GetLowestPriority()) {
2383 DLOG(DFATAL
) << "Priority out-of-bounds.";
2384 priority
= GetLowestPriority();
2387 // The size of this frame, including variable-length name-value block.
2388 size_t size
= GetSynStreamMinimumSize() +
2389 GetSerializedLength(syn_stream
.name_value_block());
2391 SpdyFrameBuilder
builder(size
, protocol_version());
2392 builder
.WriteControlFrameHeader(*this, SYN_STREAM
, flags
);
2393 builder
.WriteUInt32(syn_stream
.stream_id());
2394 builder
.WriteUInt32(syn_stream
.associated_to_stream_id());
2395 builder
.WriteUInt8(priority
<< ((protocol_version() <= SPDY2
) ? 6 : 5));
2396 builder
.WriteUInt8(0); // Unused byte where credential slot used to be.
2397 DCHECK_EQ(GetSynStreamMinimumSize(), builder
.length());
2398 SerializeNameValueBlock(&builder
, syn_stream
);
2400 if (debug_visitor_
) {
2401 const size_t payload_len
=
2402 GetSerializedLength(protocol_version(),
2403 &(syn_stream
.name_value_block()));
2404 debug_visitor_
->OnSendCompressedFrame(syn_stream
.stream_id(),
2410 return builder
.take();
2413 SpdySerializedFrame
* SpdyFramer::SerializeSynReply(
2414 const SpdySynReplyIR
& syn_reply
) {
2415 DCHECK_GE(SPDY3
, protocol_version());
2417 if (syn_reply
.fin()) {
2418 flags
|= CONTROL_FLAG_FIN
;
2421 // The size of this frame, including variable-length name-value block.
2422 const size_t size
= GetSynReplyMinimumSize() +
2423 GetSerializedLength(syn_reply
.name_value_block());
2425 SpdyFrameBuilder
builder(size
, protocol_version());
2426 if (protocol_version() <= SPDY3
) {
2427 builder
.WriteControlFrameHeader(*this, SYN_REPLY
, flags
);
2428 builder
.WriteUInt32(syn_reply
.stream_id());
2430 builder
.BeginNewFrame(*this,
2433 syn_reply
.stream_id());
2435 if (protocol_version() < SPDY3
) {
2436 builder
.WriteUInt16(0); // Unused.
2438 DCHECK_EQ(GetSynReplyMinimumSize(), builder
.length());
2439 SerializeNameValueBlock(&builder
, syn_reply
);
2441 if (debug_visitor_
) {
2442 const size_t payload_len
= GetSerializedLength(
2443 protocol_version(), &(syn_reply
.name_value_block()));
2444 debug_visitor_
->OnSendCompressedFrame(syn_reply
.stream_id(),
2450 return builder
.take();
2453 SpdySerializedFrame
* SpdyFramer::SerializeRstStream(
2454 const SpdyRstStreamIR
& rst_stream
) const {
2455 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2456 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2457 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2458 // commented but left in place to simplify future patching.
2459 // Compute the output buffer size, taking opaque data into account.
2460 uint16 expected_length
= GetRstStreamMinimumSize();
2461 if (protocol_version() > SPDY3
) {
2462 expected_length
+= rst_stream
.description().size();
2464 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2466 // Serialize the RST_STREAM frame.
2467 if (protocol_version() <= SPDY3
) {
2468 builder
.WriteControlFrameHeader(*this, RST_STREAM
, 0);
2469 builder
.WriteUInt32(rst_stream
.stream_id());
2471 builder
.BeginNewFrame(*this, RST_STREAM
, 0, rst_stream
.stream_id());
2474 builder
.WriteUInt32(rst_stream
.status());
2476 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2477 if (protocol_version() > SPDY3
&& rst_stream
.description().size() > 0) {
2478 builder
.WriteBytes(rst_stream
.description().data(),
2479 rst_stream
.description().size());
2482 DCHECK_EQ(expected_length
, builder
.length());
2483 return builder
.take();
2486 SpdySerializedFrame
* SpdyFramer::SerializeSettings(
2487 const SpdySettingsIR
& settings
) const {
2490 if (protocol_version() <= SPDY3
) {
2491 if (settings
.clear_settings()) {
2492 flags
|= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
2495 if (settings
.is_ack()) {
2496 flags
|= SETTINGS_FLAG_ACK
;
2499 const SpdySettingsIR::ValueMap
* values
= &(settings
.values());
2501 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
2502 // Size, in bytes, of this SETTINGS frame.
2503 const size_t size
= GetSettingsMinimumSize() +
2504 (values
->size() * setting_size
);
2505 SpdyFrameBuilder
builder(size
, protocol_version());
2506 if (protocol_version() <= SPDY3
) {
2507 builder
.WriteControlFrameHeader(*this, SETTINGS
, flags
);
2509 builder
.BeginNewFrame(*this, SETTINGS
, flags
, 0);
2512 // If this is an ACK, payload should be empty.
2513 if (protocol_version() > SPDY3
&& settings
.is_ack()) {
2514 return builder
.take();
2517 if (protocol_version() <= SPDY3
) {
2518 builder
.WriteUInt32(values
->size());
2520 DCHECK_EQ(GetSettingsMinimumSize(), builder
.length());
2521 for (SpdySettingsIR::ValueMap::const_iterator it
= values
->begin();
2522 it
!= values
->end();
2524 if (protocol_version() <= SPDY3
) {
2525 uint8 setting_flags
= 0;
2526 if (it
->second
.persist_value
) {
2527 setting_flags
|= SETTINGS_FLAG_PLEASE_PERSIST
;
2529 if (it
->second
.persisted
) {
2530 setting_flags
|= SETTINGS_FLAG_PERSISTED
;
2532 SettingsFlagsAndId
flags_and_id(
2534 SpdyConstants::SerializeSettingId(protocol_version(), it
->first
));
2535 uint32 id_and_flags_wire
= flags_and_id
.GetWireFormat(protocol_version());
2536 builder
.WriteBytes(&id_and_flags_wire
, 4);
2538 builder
.WriteUInt16(SpdyConstants::SerializeSettingId(protocol_version(),
2541 builder
.WriteUInt32(it
->second
.value
);
2543 DCHECK_EQ(size
, builder
.length());
2544 return builder
.take();
2547 SpdySerializedFrame
* SpdyFramer::SerializePing(const SpdyPingIR
& ping
) const {
2548 SpdyFrameBuilder
builder(GetPingSize(), protocol_version());
2549 if (protocol_version() <= SPDY3
) {
2550 builder
.WriteControlFrameHeader(*this, PING
, kNoFlags
);
2551 builder
.WriteUInt32(static_cast<uint32
>(ping
.id()));
2554 if (ping
.is_ack()) {
2555 flags
|= PING_FLAG_ACK
;
2557 builder
.BeginNewFrame(*this, PING
, flags
, 0);
2558 builder
.WriteUInt64(ping
.id());
2560 DCHECK_EQ(GetPingSize(), builder
.length());
2561 return builder
.take();
2564 SpdySerializedFrame
* SpdyFramer::SerializeGoAway(
2565 const SpdyGoAwayIR
& goaway
) const {
2567 // Compute the output buffer size, take opaque data into account.
2568 uint16 expected_length
= GetGoAwayMinimumSize();
2569 if (protocol_version() > SPDY3
) {
2570 expected_length
+= goaway
.description().size();
2572 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2574 // Serialize the GOAWAY frame.
2575 if (protocol_version() <= SPDY3
) {
2576 builder
.WriteControlFrameHeader(*this, GOAWAY
, kNoFlags
);
2578 builder
.BeginNewFrame(*this, GOAWAY
, 0, 0);
2581 // GOAWAY frames specify the last good stream id for all SPDY versions.
2582 builder
.WriteUInt32(goaway
.last_good_stream_id());
2584 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2585 if (protocol_version() >= SPDY3
) {
2586 // TODO(jgraettinger): Merge back to server-side.
2587 builder
.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2591 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2592 if ((protocol_version() > SPDY3
) && (goaway
.description().size() > 0)) {
2593 builder
.WriteBytes(goaway
.description().data(),
2594 goaway
.description().size());
2597 DCHECK_EQ(expected_length
, builder
.length());
2598 return builder
.take();
2601 SpdySerializedFrame
* SpdyFramer::SerializeHeaders(
2602 const SpdyHeadersIR
& headers
) {
2604 if (headers
.fin()) {
2605 flags
|= CONTROL_FLAG_FIN
;
2607 if (protocol_version() > SPDY3
) {
2608 // This will get overwritten if we overflow into a CONTINUATION frame.
2609 flags
|= HEADERS_FLAG_END_HEADERS
;
2610 if (headers
.has_priority()) {
2611 flags
|= HEADERS_FLAG_PRIORITY
;
2615 // The size of this frame, including variable-length name-value block.
2616 size_t size
= GetHeadersMinimumSize();
2618 uint32 priority
= headers
.priority();
2619 if (headers
.has_priority()) {
2620 if (priority
> GetLowestPriority()) {
2621 DLOG(DFATAL
) << "Priority out-of-bounds.";
2622 priority
= GetLowestPriority();
2627 string hpack_encoding
;
2628 if (protocol_version() > SPDY3
) {
2629 if (enable_compression_
) {
2630 GetHpackEncoder()->EncodeHeaderSet(
2631 headers
.name_value_block(), &hpack_encoding
);
2633 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2634 headers
.name_value_block(), &hpack_encoding
);
2636 size
+= hpack_encoding
.size();
2637 if (size
> GetHeaderFragmentMaxSize()) {
2638 size
+= GetNumberRequiredContinuationFrames(size
) *
2639 GetContinuationMinimumSize();
2640 flags
&= ~HEADERS_FLAG_END_HEADERS
;
2643 size
+= GetSerializedLength(headers
.name_value_block());
2646 SpdyFrameBuilder
builder(size
, protocol_version());
2647 if (protocol_version() <= SPDY3
) {
2648 builder
.WriteControlFrameHeader(*this, HEADERS
, flags
);
2649 builder
.WriteUInt32(headers
.stream_id());
2651 builder
.BeginNewFrame(*this,
2654 headers
.stream_id());
2656 if (protocol_version() <= SPDY2
) {
2657 builder
.WriteUInt16(0); // Unused.
2659 DCHECK_EQ(GetHeadersMinimumSize(), builder
.length());
2661 if (protocol_version() > SPDY3
) {
2662 if (headers
.has_priority()) {
2663 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2664 builder
.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2665 builder
.WriteUInt8(MapPriorityToWeight(priority
));
2667 WritePayloadWithContinuation(&builder
,
2669 headers
.stream_id(),
2672 SerializeNameValueBlock(&builder
, headers
);
2675 if (debug_visitor_
) {
2676 // SPDY4 uses HPACK for header compression. However, continue to
2677 // use GetSerializedLength() for an apples-to-apples comparision of
2678 // compression performance between HPACK and SPDY w/ deflate.
2679 const size_t payload_len
=
2680 GetSerializedLength(protocol_version(),
2681 &(headers
.name_value_block()));
2682 debug_visitor_
->OnSendCompressedFrame(headers
.stream_id(),
2688 return builder
.take();
2691 SpdySerializedFrame
* SpdyFramer::SerializeWindowUpdate(
2692 const SpdyWindowUpdateIR
& window_update
) const {
2693 SpdyFrameBuilder
builder(GetWindowUpdateSize(), protocol_version());
2694 if (protocol_version() <= SPDY3
) {
2695 builder
.WriteControlFrameHeader(*this, WINDOW_UPDATE
, kNoFlags
);
2696 builder
.WriteUInt32(window_update
.stream_id());
2698 builder
.BeginNewFrame(*this,
2701 window_update
.stream_id());
2703 builder
.WriteUInt32(window_update
.delta());
2704 DCHECK_EQ(GetWindowUpdateSize(), builder
.length());
2705 return builder
.take();
2708 SpdyFrame
* SpdyFramer::SerializeBlocked(const SpdyBlockedIR
& blocked
) const {
2709 DCHECK_LT(SPDY3
, protocol_version());
2710 SpdyFrameBuilder
builder(GetBlockedSize(), protocol_version());
2711 builder
.BeginNewFrame(*this, BLOCKED
, kNoFlags
, blocked
.stream_id());
2712 return builder
.take();
2715 SpdyFrame
* SpdyFramer::SerializePushPromise(
2716 const SpdyPushPromiseIR
& push_promise
) {
2717 DCHECK_LT(SPDY3
, protocol_version());
2719 // This will get overwritten if we overflow into a CONTINUATION frame.
2720 flags
|= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2721 // The size of this frame, including variable-length name-value block.
2722 size_t size
= GetPushPromiseMinimumSize();
2724 string hpack_encoding
;
2725 if (enable_compression_
) {
2726 GetHpackEncoder()->EncodeHeaderSet(
2727 push_promise
.name_value_block(), &hpack_encoding
);
2729 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2730 push_promise
.name_value_block(), &hpack_encoding
);
2732 size
+= hpack_encoding
.size();
2733 if (size
> GetHeaderFragmentMaxSize()) {
2734 size
+= GetNumberRequiredContinuationFrames(size
) *
2735 GetContinuationMinimumSize();
2736 flags
&= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2739 SpdyFrameBuilder
builder(size
, protocol_version());
2740 builder
.BeginNewFrame(*this,
2743 push_promise
.stream_id());
2744 builder
.WriteUInt32(push_promise
.promised_stream_id());
2745 DCHECK_EQ(GetPushPromiseMinimumSize(), builder
.length());
2747 WritePayloadWithContinuation(&builder
,
2749 push_promise
.stream_id(),
2752 if (debug_visitor_
) {
2753 // SPDY4 uses HPACK for header compression. However, continue to
2754 // use GetSerializedLength() for an apples-to-apples comparision of
2755 // compression performance between HPACK and SPDY w/ deflate.
2756 const size_t payload_len
=
2757 GetSerializedLength(protocol_version(),
2758 &(push_promise
.name_value_block()));
2759 debug_visitor_
->OnSendCompressedFrame(push_promise
.stream_id(),
2765 return builder
.take();
2768 // TODO(jgraettinger): This implementation is incorrect. The continuation
2769 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2770 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2771 SpdyFrame
* SpdyFramer::SerializeContinuation(
2772 const SpdyContinuationIR
& continuation
) {
2773 CHECK_LT(SPDY3
, protocol_version());
2775 if (continuation
.end_headers()) {
2776 flags
|= HEADERS_FLAG_END_HEADERS
;
2779 // The size of this frame, including variable-length name-value block.
2780 size_t size
= GetContinuationMinimumSize();
2781 string hpack_encoding
;
2782 if (enable_compression_
) {
2783 GetHpackEncoder()->EncodeHeaderSet(
2784 continuation
.name_value_block(), &hpack_encoding
);
2786 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2787 continuation
.name_value_block(), &hpack_encoding
);
2789 size
+= hpack_encoding
.size();
2791 SpdyFrameBuilder
builder(size
, protocol_version());
2792 builder
.BeginNewFrame(*this, CONTINUATION
, flags
,
2793 continuation
.stream_id());
2794 DCHECK_EQ(GetContinuationMinimumSize(), builder
.length());
2796 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2797 return builder
.take();
2800 SpdyFrame
* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR
& altsvc
) {
2801 DCHECK_LT(SPDY3
, protocol_version());
2802 size_t size
= GetAltSvcMinimumSize();
2803 size
+= altsvc
.protocol_id().length();
2804 size
+= altsvc
.host().length();
2805 size
+= altsvc
.origin().length();
2807 SpdyFrameBuilder
builder(size
, protocol_version());
2808 builder
.BeginNewFrame(*this, ALTSVC
, kNoFlags
, altsvc
.stream_id());
2810 builder
.WriteUInt32(altsvc
.max_age());
2811 builder
.WriteUInt16(altsvc
.port());
2812 builder
.WriteUInt8(0); // Reserved.
2813 builder
.WriteUInt8(altsvc
.protocol_id().length());
2814 builder
.WriteBytes(altsvc
.protocol_id().data(),
2815 altsvc
.protocol_id().length());
2816 builder
.WriteUInt8(altsvc
.host().length());
2817 builder
.WriteBytes(altsvc
.host().data(), altsvc
.host().length());
2818 builder
.WriteBytes(altsvc
.origin().data(), altsvc
.origin().length());
2819 DCHECK_LT(GetAltSvcMinimumSize(), builder
.length());
2820 return builder
.take();
2823 SpdyFrame
* SpdyFramer::SerializePriority(const SpdyPriorityIR
& priority
) {
2824 DCHECK_LT(SPDY3
, protocol_version());
2825 size_t size
= GetPrioritySize();
2827 SpdyFrameBuilder
builder(size
, protocol_version());
2828 builder
.BeginNewFrame(*this, PRIORITY
, kNoFlags
, priority
.stream_id());
2830 // Make sure the highest-order bit in the parent stream id is zeroed out.
2831 uint32 parent_stream_id
= priority
.parent_stream_id() & 0x7fffffff;
2832 uint32 exclusive
= priority
.exclusive() ? 0x80000000 : 0;
2833 // Set the one-bit exclusivity flag.
2834 uint32 flag_and_parent_id
= parent_stream_id
| exclusive
;
2835 builder
.WriteUInt32(flag_and_parent_id
);
2836 builder
.WriteUInt8(priority
.weight());
2837 DCHECK_EQ(GetPrioritySize(), builder
.length());
2838 return builder
.take();
2843 class FrameSerializationVisitor
: public SpdyFrameVisitor
{
2845 explicit FrameSerializationVisitor(SpdyFramer
* framer
) : framer_(framer
) {}
2846 virtual ~FrameSerializationVisitor() {}
2848 SpdySerializedFrame
* ReleaseSerializedFrame() { return frame_
.release(); }
2850 virtual void VisitData(const SpdyDataIR
& data
) OVERRIDE
{
2851 frame_
.reset(framer_
->SerializeData(data
));
2853 virtual void VisitSynStream(const SpdySynStreamIR
& syn_stream
) OVERRIDE
{
2854 frame_
.reset(framer_
->SerializeSynStream(syn_stream
));
2856 virtual void VisitSynReply(const SpdySynReplyIR
& syn_reply
) OVERRIDE
{
2857 frame_
.reset(framer_
->SerializeSynReply(syn_reply
));
2859 virtual void VisitRstStream(const SpdyRstStreamIR
& rst_stream
) OVERRIDE
{
2860 frame_
.reset(framer_
->SerializeRstStream(rst_stream
));
2862 virtual void VisitSettings(const SpdySettingsIR
& settings
) OVERRIDE
{
2863 frame_
.reset(framer_
->SerializeSettings(settings
));
2865 virtual void VisitPing(const SpdyPingIR
& ping
) OVERRIDE
{
2866 frame_
.reset(framer_
->SerializePing(ping
));
2868 virtual void VisitGoAway(const SpdyGoAwayIR
& goaway
) OVERRIDE
{
2869 frame_
.reset(framer_
->SerializeGoAway(goaway
));
2871 virtual void VisitHeaders(const SpdyHeadersIR
& headers
) OVERRIDE
{
2872 frame_
.reset(framer_
->SerializeHeaders(headers
));
2874 virtual void VisitWindowUpdate(
2875 const SpdyWindowUpdateIR
& window_update
) OVERRIDE
{
2876 frame_
.reset(framer_
->SerializeWindowUpdate(window_update
));
2878 virtual void VisitBlocked(const SpdyBlockedIR
& blocked
) OVERRIDE
{
2879 frame_
.reset(framer_
->SerializeBlocked(blocked
));
2881 virtual void VisitPushPromise(
2882 const SpdyPushPromiseIR
& push_promise
) OVERRIDE
{
2883 frame_
.reset(framer_
->SerializePushPromise(push_promise
));
2885 virtual void VisitContinuation(
2886 const SpdyContinuationIR
& continuation
) OVERRIDE
{
2887 frame_
.reset(framer_
->SerializeContinuation(continuation
));
2889 virtual void VisitAltSvc(const SpdyAltSvcIR
& altsvc
) OVERRIDE
{
2890 frame_
.reset(framer_
->SerializeAltSvc(altsvc
));
2892 virtual void VisitPriority(const SpdyPriorityIR
& priority
) OVERRIDE
{
2893 frame_
.reset(framer_
->SerializePriority(priority
));
2897 SpdyFramer
* framer_
;
2898 scoped_ptr
<SpdySerializedFrame
> frame_
;
2903 SpdySerializedFrame
* SpdyFramer::SerializeFrame(const SpdyFrameIR
& frame
) {
2904 FrameSerializationVisitor
visitor(this);
2905 frame
.Visit(&visitor
);
2906 return visitor
.ReleaseSerializedFrame();
2909 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock
& headers
) {
2910 CHECK_GE(SPDY3
, protocol_version());
2911 const size_t uncompressed_length
=
2912 GetSerializedLength(protocol_version(), &headers
);
2913 if (!enable_compression_
) {
2914 return uncompressed_length
;
2916 z_stream
* compressor
= GetHeaderCompressor();
2917 // Since we'll be performing lots of flushes when compressing the data,
2918 // zlib's lower bounds may be insufficient.
2919 return 2 * deflateBound(compressor
, uncompressed_length
);
2922 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size
) {
2923 const size_t kMaxControlFrameSize
= GetHeaderFragmentMaxSize();
2924 DCHECK_GT(protocol_version(), SPDY3
);
2925 DCHECK_GT(size
, kMaxControlFrameSize
);
2926 size_t overflow
= size
- kMaxControlFrameSize
;
2927 return overflow
/ (kMaxControlFrameSize
- GetContinuationMinimumSize()) + 1;
2930 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder
* builder
,
2931 const string
& hpack_encoding
,
2932 SpdyStreamId stream_id
,
2933 SpdyFrameType type
) {
2934 const size_t kMaxControlFrameSize
= GetHeaderFragmentMaxSize();
2936 // In addition to the prefix, fixed_field_size includes the size of
2937 // any fields that come before the variable-length name/value block.
2938 size_t fixed_field_size
= 0;
2941 if (type
== HEADERS
) {
2942 fixed_field_size
= GetHeadersMinimumSize();
2943 end_flag
= HEADERS_FLAG_END_HEADERS
;
2944 } else if (type
== PUSH_PROMISE
) {
2945 fixed_field_size
= GetPushPromiseMinimumSize();
2946 end_flag
= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2948 DLOG(FATAL
) << "CONTINUATION frames cannot be used with frame type "
2949 << FrameTypeToString(type
);
2952 // Write as much of the payload as possible into the initial frame.
2953 size_t bytes_remaining
= hpack_encoding
.size() -
2954 std::min(hpack_encoding
.size(),
2955 kMaxControlFrameSize
- fixed_field_size
);
2956 builder
->WriteBytes(&hpack_encoding
[0],
2957 hpack_encoding
.size() - bytes_remaining
);
2959 if (bytes_remaining
> 0) {
2960 builder
->OverwriteLength(*this,
2961 kMaxControlFrameSize
- GetControlFrameHeaderSize());
2964 // Tack on CONTINUATION frames for the overflow.
2965 while (bytes_remaining
> 0) {
2966 size_t bytes_to_write
= std::min(bytes_remaining
,
2967 kMaxControlFrameSize
-
2968 GetContinuationMinimumSize());
2969 // Write CONTINUATION frame prefix.
2970 if (bytes_remaining
== bytes_to_write
) {
2973 builder
->BeginNewFrame(*this,
2977 // Write payload fragment.
2978 builder
->WriteBytes(&hpack_encoding
[hpack_encoding
.size() -
2981 bytes_remaining
-= bytes_to_write
;
2985 // The following compression setting are based on Brian Olson's analysis. See
2986 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2987 // for more details.
2988 #if defined(USE_SYSTEM_ZLIB)
2989 // System zlib is not expected to have workaround for http://crbug.com/139744,
2990 // so disable compression in that case.
2991 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2992 static const int kCompressorLevel
= 0;
2993 #else // !defined(USE_SYSTEM_ZLIB)
2994 static const int kCompressorLevel
= 9;
2995 #endif // !defined(USE_SYSTEM_ZLIB)
2996 static const int kCompressorWindowSizeInBits
= 11;
2997 static const int kCompressorMemLevel
= 1;
2999 z_stream
* SpdyFramer::GetHeaderCompressor() {
3000 if (header_compressor_
.get())
3001 return header_compressor_
.get(); // Already initialized.
3003 header_compressor_
.reset(new z_stream
);
3004 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
3006 int success
= deflateInit2(header_compressor_
.get(),
3009 kCompressorWindowSizeInBits
,
3010 kCompressorMemLevel
,
3011 Z_DEFAULT_STRATEGY
);
3012 if (success
== Z_OK
) {
3013 const char* dictionary
= (protocol_version() <= SPDY2
) ?
3014 kV2Dictionary
: kV3Dictionary
;
3015 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3016 kV2DictionarySize
: kV3DictionarySize
;
3017 success
= deflateSetDictionary(header_compressor_
.get(),
3018 reinterpret_cast<const Bytef
*>(dictionary
),
3021 if (success
!= Z_OK
) {
3022 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
3023 header_compressor_
.reset(NULL
);
3026 return header_compressor_
.get();
3029 z_stream
* SpdyFramer::GetHeaderDecompressor() {
3030 if (header_decompressor_
.get())
3031 return header_decompressor_
.get(); // Already initialized.
3033 header_decompressor_
.reset(new z_stream
);
3034 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
3036 int success
= inflateInit(header_decompressor_
.get());
3037 if (success
!= Z_OK
) {
3038 LOG(WARNING
) << "inflateInit failure: " << success
;
3039 header_decompressor_
.reset(NULL
);
3042 return header_decompressor_
.get();
3045 HpackEncoder
* SpdyFramer::GetHpackEncoder() {
3046 DCHECK_LT(SPDY3
, spdy_version_
);
3047 if (hpack_encoder_
.get() == NULL
) {
3048 hpack_encoder_
.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3050 return hpack_encoder_
.get();
3053 HpackDecoder
* SpdyFramer::GetHpackDecoder() {
3054 DCHECK_LT(SPDY3
, spdy_version_
);
3055 if (hpack_decoder_
.get() == NULL
) {
3056 hpack_decoder_
.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3058 return hpack_decoder_
.get();
3061 uint8
SpdyFramer::MapPriorityToWeight(SpdyPriority priority
) {
3062 const float kSteps
= 255.9f
/ 7.f
;
3063 return static_cast<uint8
>(kSteps
* (7.f
- priority
));
3066 SpdyPriority
SpdyFramer::MapWeightToPriority(uint8 weight
) {
3067 const float kSteps
= 255.9f
/ 7.f
;
3068 return static_cast<SpdyPriority
>(7.f
- weight
/ kSteps
);
3071 // Incrementally decompress the control frame's header block, feeding the
3072 // result to the visitor in chunks. Continue this until the visitor
3073 // indicates that it cannot process any more data, or (more commonly) we
3074 // run out of data to deliver.
3075 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3076 SpdyStreamId stream_id
,
3079 // Get a decompressor or set error.
3080 z_stream
* decomp
= GetHeaderDecompressor();
3081 if (decomp
== NULL
) {
3082 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
3083 set_error(SPDY_DECOMPRESS_FAILURE
);
3087 bool processed_successfully
= true;
3088 char buffer
[kHeaderDataChunkMaxSize
];
3090 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
3091 decomp
->avail_in
= len
;
3092 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3093 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3094 // reached this method successfully, stream_id should be nonzero.
3095 DCHECK_LT(0u, stream_id
);
3096 while (decomp
->avail_in
> 0 && processed_successfully
) {
3097 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
3098 decomp
->avail_out
= arraysize(buffer
);
3100 int rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3101 if (rv
== Z_NEED_DICT
) {
3102 const char* dictionary
= (protocol_version() <= SPDY2
) ? kV2Dictionary
3104 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3105 kV2DictionarySize
: kV3DictionarySize
;
3106 const DictionaryIds
& ids
= g_dictionary_ids
.Get();
3107 const uLong dictionary_id
= (protocol_version() <= SPDY2
) ?
3108 ids
.v2_dictionary_id
: ids
.v3_dictionary_id
;
3109 // Need to try again with the right dictionary.
3110 if (decomp
->adler
== dictionary_id
) {
3111 rv
= inflateSetDictionary(decomp
,
3112 reinterpret_cast<const Bytef
*>(dictionary
),
3115 rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3119 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3120 // without producing any output. The input is consumed and
3121 // buffered internally by zlib so we can detect this condition by
3122 // checking if avail_in is 0 after the call to inflate.
3123 bool input_exhausted
= ((rv
== Z_BUF_ERROR
) && (decomp
->avail_in
== 0));
3124 if ((rv
== Z_OK
) || input_exhausted
) {
3125 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
3126 if (decompressed_len
> 0) {
3127 processed_successfully
= visitor_
->OnControlFrameHeaderData(
3128 stream_id
, buffer
, decompressed_len
);
3130 if (!processed_successfully
) {
3131 // Assume that the problem was the header block was too large for the
3133 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3136 DLOG(WARNING
) << "inflate failure: " << rv
<< " " << len
;
3137 set_error(SPDY_DECOMPRESS_FAILURE
);
3138 processed_successfully
= false;
3141 return processed_successfully
;
3144 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3145 SpdyStreamId stream_id
, const char* data
, size_t len
) {
3146 bool read_successfully
= true;
3147 while (read_successfully
&& len
> 0) {
3148 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
3149 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
3151 data
+= bytes_to_deliver
;
3152 len
-= bytes_to_deliver
;
3153 if (!read_successfully
) {
3154 // Assume that the problem was the header block was too large for the
3156 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3159 return read_successfully
;
3162 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3163 SpdyFrameBuilder
* builder
,
3164 const SpdyNameValueBlock
& name_value_block
) const {
3165 // Serialize number of headers.
3166 if (protocol_version() <= SPDY2
) {
3167 builder
->WriteUInt16(name_value_block
.size());
3169 builder
->WriteUInt32(name_value_block
.size());
3172 // Serialize each header.
3173 for (SpdyHeaderBlock::const_iterator it
= name_value_block
.begin();
3174 it
!= name_value_block
.end();
3176 if (protocol_version() <= SPDY2
) {
3177 builder
->WriteString(it
->first
);
3178 builder
->WriteString(it
->second
);
3180 builder
->WriteStringPiece32(it
->first
);
3181 builder
->WriteStringPiece32(it
->second
);
3186 void SpdyFramer::SerializeNameValueBlock(
3187 SpdyFrameBuilder
* builder
,
3188 const SpdyFrameWithNameValueBlockIR
& frame
) {
3189 CHECK_GE(SPDY3
, protocol_version());
3190 if (!enable_compression_
) {
3191 return SerializeNameValueBlockWithoutCompression(builder
,
3192 frame
.name_value_block());
3195 // First build an uncompressed version to be fed into the compressor.
3196 const size_t uncompressed_len
= GetSerializedLength(
3197 protocol_version(), &(frame
.name_value_block()));
3198 SpdyFrameBuilder
uncompressed_builder(uncompressed_len
, protocol_version());
3199 SerializeNameValueBlockWithoutCompression(&uncompressed_builder
,
3200 frame
.name_value_block());
3201 scoped_ptr
<SpdyFrame
> uncompressed_payload(uncompressed_builder
.take());
3203 z_stream
* compressor
= GetHeaderCompressor();
3205 LOG(DFATAL
) << "Could not obtain compressor.";
3209 base::StatsCounter
compressed_frames("spdy.CompressedFrames");
3210 base::StatsCounter
pre_compress_bytes("spdy.PreCompressSize");
3211 base::StatsCounter
post_compress_bytes("spdy.PostCompressSize");
3213 // Create an output frame.
3214 // Since we'll be performing lots of flushes when compressing the data,
3215 // zlib's lower bounds may be insufficient.
3217 // TODO(akalin): Avoid the duplicate calculation with
3218 // GetSerializedLength(const SpdyHeaderBlock&).
3219 const int compressed_max_size
=
3220 2 * deflateBound(compressor
, uncompressed_len
);
3222 // TODO(phajdan.jr): Clean up after we no longer need
3223 // to workaround http://crbug.com/139744.
3224 #if defined(USE_SYSTEM_ZLIB)
3225 compressor
->next_in
= reinterpret_cast<Bytef
*>(uncompressed_payload
->data());
3226 compressor
->avail_in
= uncompressed_len
;
3227 #endif // defined(USE_SYSTEM_ZLIB)
3228 compressor
->next_out
= reinterpret_cast<Bytef
*>(
3229 builder
->GetWritableBuffer(compressed_max_size
));
3230 compressor
->avail_out
= compressed_max_size
;
3232 // TODO(phajdan.jr): Clean up after we no longer need
3233 // to workaround http://crbug.com/139744.
3234 #if defined(USE_SYSTEM_ZLIB)
3235 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
3236 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
3237 // This shouldn't happen, right?
3238 LOG(WARNING
) << "deflate failure: " << rv
;
3239 // TODO(akalin): Upstream this return.
3243 WriteHeaderBlockToZ(&frame
.name_value_block(), compressor
);
3244 #endif // defined(USE_SYSTEM_ZLIB)
3246 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
3247 builder
->Seek(compressed_size
);
3248 builder
->RewriteLength(*this);
3250 pre_compress_bytes
.Add(uncompressed_len
);
3251 post_compress_bytes
.Add(compressed_size
);
3253 compressed_frames
.Increment();