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/third_party/valgrind/memcheck.h"
10 #include "net/spdy/spdy_frame_builder.h"
11 #include "net/spdy/spdy_frame_reader.h"
12 #include "net/spdy/spdy_bitmasks.h"
13 #include "third_party/zlib/zlib.h"
15 using base::StringPiece
;
23 // Compute the id of our dictionary so that we know we're using the
24 // right one when asked for it.
25 uLong
CalculateDictionaryId(const char* dictionary
,
26 const size_t dictionary_size
) {
27 uLong initial_value
= adler32(0L, Z_NULL
, 0);
28 return adler32(initial_value
,
29 reinterpret_cast<const Bytef
*>(dictionary
),
33 // Check to see if the name and value of a cookie are both empty.
34 bool IsCookieEmpty(const base::StringPiece
& cookie
) {
35 if (cookie
.size() == 0) {
38 size_t pos
= cookie
.find('=');
39 if (pos
== base::StringPiece::npos
) {
42 // Ignore leading whitespaces of cookie value.
43 size_t value_start
= pos
+ 1;
44 for (; value_start
< cookie
.size(); value_start
++) {
45 if (!(cookie
[value_start
] == ' ' || cookie
[value_start
] == '\t')) {
49 return (pos
== 0) && ((cookie
.size() - value_start
) == 0);
52 struct DictionaryIds
{
54 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary
, kV2DictionarySize
)),
55 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary
, kV3DictionarySize
))
57 const uLong v2_dictionary_id
;
58 const uLong v3_dictionary_id
;
61 // Adler ID for the SPDY header compressor dictionaries. Note that they are
62 // initialized lazily to avoid static initializers.
63 base::LazyInstance
<DictionaryIds
>::Leaky g_dictionary_ids
;
65 // Used to indicate no flags in a SPDY flags field.
66 const uint8 kNoFlags
= 0;
68 // Wire sizes of priority payloads.
69 const size_t kPriorityDependencyPayloadSize
= 4;
70 const size_t kPriorityWeightPayloadSize
= 1;
72 // Wire size of pad length field.
73 const size_t kPadLengthFieldSize
= 1;
77 const SpdyStreamId
SpdyFramer::kInvalidStream
= static_cast<SpdyStreamId
>(-1);
78 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
79 // We fragment sent control frames at smaller payload boundaries.
80 const size_t SpdyFramer::kMaxControlFrameSize
= 1024;
81 // The size of the control frame buffer. Must be >= the minimum size of the
82 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
83 // calculation details.
84 const size_t SpdyFramer::kControlFrameBufferSize
= 19;
86 #ifdef DEBUG_SPDY_STATE_CHANGES
87 #define CHANGE_STATE(newstate) \
89 DVLOG(1) << "Changing state from: " \
90 << StateToString(state_) \
91 << " to " << StateToString(newstate) << "\n"; \
92 DCHECK(state_ != SPDY_ERROR); \
93 DCHECK_EQ(previous_state_, state_); \
94 previous_state_ = state_; \
98 #define CHANGE_STATE(newstate) \
100 DCHECK(state_ != SPDY_ERROR); \
101 DCHECK_EQ(previous_state_, state_); \
102 previous_state_ = state_; \
107 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(
108 SpdyMajorVersion version
, uint32 wire
) {
109 if (version
< SPDY3
) {
110 ConvertFlagsAndIdForSpdy2(&wire
);
112 return SettingsFlagsAndId(ntohl(wire
) >> 24, ntohl(wire
) & 0x00ffffff);
115 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags
, uint32 id
)
116 : flags_(flags
), id_(id
& 0x00ffffff) {
117 LOG_IF(DFATAL
, id
> (1u << 24)) << "SPDY setting ID too large: " << id
;
120 uint32
SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version
)
122 uint32 wire
= htonl(id_
& 0x00ffffff) | htonl(flags_
<< 24);
123 if (version
< SPDY3
) {
124 ConvertFlagsAndIdForSpdy2(&wire
);
129 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
130 // This method is used to preserve buggy behavior and works on both
131 // little-endian and big-endian hosts.
132 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
133 // as well as vice versa).
134 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32
* val
) {
135 uint8
* wire_array
= reinterpret_cast<uint8
*>(val
);
136 std::swap(wire_array
[0], wire_array
[3]);
137 std::swap(wire_array
[1], wire_array
[2]);
140 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
141 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
143 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data
,
148 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
149 const char* rst_stream_data
,
154 SpdyFramer::SpdyFramer(SpdyMajorVersion version
)
155 : current_frame_buffer_(new char[kControlFrameBufferSize
]),
156 expect_continuation_(0),
158 debug_visitor_(NULL
),
159 display_protocol_("SPDY"),
160 protocol_version_(version
),
161 enable_compression_(true),
162 syn_frame_processed_(false),
163 probable_http_response_(false),
164 end_stream_when_done_(false) {
165 DCHECK_GE(protocol_version_
, SPDY_MIN_VERSION
);
166 DCHECK_LE(protocol_version_
, SPDY_MAX_VERSION
);
167 DCHECK_LE(kMaxControlFrameSize
,
168 SpdyConstants::GetFrameMaximumSize(protocol_version_
) +
169 SpdyConstants::GetControlFrameHeaderSize(protocol_version_
));
173 SpdyFramer::~SpdyFramer() {
174 if (header_compressor_
.get()) {
175 deflateEnd(header_compressor_
.get());
177 if (header_decompressor_
.get()) {
178 inflateEnd(header_decompressor_
.get());
182 void SpdyFramer::Reset() {
184 previous_state_
= SPDY_RESET
;
185 error_code_
= SPDY_NO_ERROR
;
186 remaining_data_length_
= 0;
187 remaining_control_header_
= 0;
188 current_frame_buffer_length_
= 0;
189 current_frame_type_
= DATA
;
190 current_frame_flags_
= 0;
191 current_frame_length_
= 0;
192 current_frame_stream_id_
= kInvalidStream
;
193 settings_scratch_
.Reset();
194 altsvc_scratch_
.Reset();
195 remaining_padding_payload_length_
= 0;
198 size_t SpdyFramer::GetDataFrameMinimumSize() const {
199 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
202 // Size, in bytes, of the control frame header.
203 size_t SpdyFramer::GetControlFrameHeaderSize() const {
204 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
207 size_t SpdyFramer::GetSynStreamMinimumSize() const {
208 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
210 if (protocol_version() <= SPDY3
) {
212 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
213 // + 1 (unused, was credential slot)
214 return GetControlFrameHeaderSize() + 10;
216 return GetControlFrameHeaderSize() +
217 kPriorityDependencyPayloadSize
+
218 kPriorityWeightPayloadSize
;
222 size_t SpdyFramer::GetSynReplyMinimumSize() const {
223 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
225 size_t size
= GetControlFrameHeaderSize();
226 if (protocol_version() <= SPDY3
) {
228 // control frame header + 4 (stream IDs)
232 // In SPDY 2, there were 2 unused bytes before payload.
233 if (protocol_version() < SPDY3
) {
240 size_t SpdyFramer::GetRstStreamMinimumSize() const {
241 // Size, in bytes, of a RST_STREAM frame.
242 if (protocol_version() <= SPDY3
) {
244 // control frame header + 4 (stream id) + 4 (status code)
245 return GetControlFrameHeaderSize() + 8;
248 // frame prefix + 4 (status code)
249 return GetControlFrameHeaderSize() + 4;
253 size_t SpdyFramer::GetSettingsMinimumSize() const {
254 // Size, in bytes, of a SETTINGS frame not including the IDs and values
255 // from the variable-length value block. Calculated as:
256 // control frame header + 4 (number of ID/value pairs)
257 if (protocol_version() <= SPDY3
) {
258 return GetControlFrameHeaderSize() + 4;
260 return GetControlFrameHeaderSize();
264 size_t SpdyFramer::GetPingSize() const {
265 // Size, in bytes, of this PING frame.
266 if (protocol_version() <= SPDY3
) {
268 // control frame header + 4 (id)
269 return GetControlFrameHeaderSize() + 4;
272 // control frame header + 8 (id)
273 return GetControlFrameHeaderSize() + 8;
277 size_t SpdyFramer::GetGoAwayMinimumSize() const {
278 // Size, in bytes, of this GOAWAY frame. Calculated as:
279 // 1. Control frame header size
280 size_t size
= GetControlFrameHeaderSize();
282 // 2. Last good stream id (4 bytes)
285 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
286 if (protocol_version() >= SPDY3
) {
293 size_t SpdyFramer::GetHeadersMinimumSize() const {
294 // Size, in bytes, of a HEADERS frame not including the variable-length
296 size_t size
= GetControlFrameHeaderSize();
297 if (protocol_version() <= SPDY3
) {
299 // control frame header + 4 (stream IDs)
303 // In SPDY 2, there were 2 unused bytes before payload.
304 if (protocol_version() <= SPDY2
) {
311 size_t SpdyFramer::GetWindowUpdateSize() const {
312 // Size, in bytes, of a WINDOW_UPDATE frame.
313 if (protocol_version() <= SPDY3
) {
315 // control frame header + 4 (stream id) + 4 (delta)
316 return GetControlFrameHeaderSize() + 8;
319 // frame prefix + 4 (delta)
320 return GetControlFrameHeaderSize() + 4;
324 size_t SpdyFramer::GetBlockedSize() const {
325 DCHECK_LT(SPDY3
, protocol_version());
326 // Size, in bytes, of a BLOCKED frame.
327 // The BLOCKED frame has no payload beyond the control frame header.
328 return GetControlFrameHeaderSize();
331 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
332 DCHECK_LT(SPDY3
, protocol_version());
333 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
334 // Calculated as frame prefix + 4 (promised stream id).
335 return GetControlFrameHeaderSize() + 4;
338 size_t SpdyFramer::GetContinuationMinimumSize() const {
339 // Size, in bytes, of a CONTINUATION frame not including the variable-length
340 // headers fragments.
341 return GetControlFrameHeaderSize();
344 size_t SpdyFramer::GetAltSvcMinimumSize() const {
345 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
346 // (optional) Origin fields, all of which can vary in length.
347 // Note that this gives a lower bound on the frame size rather than a true
348 // minimum; the actual frame should always be larger than this.
349 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
350 // + 1 (pid_len) + 1 (host_len).
351 return GetControlFrameHeaderSize() + 9;
354 size_t SpdyFramer::GetPrioritySize() const {
355 // Size, in bytes, of a PRIORITY frame.
356 return GetControlFrameHeaderSize() +
357 kPriorityDependencyPayloadSize
+
358 kPriorityWeightPayloadSize
;
361 size_t SpdyFramer::GetFrameMinimumSize() const {
362 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
365 size_t SpdyFramer::GetFrameMaximumSize() const {
366 return SpdyConstants::GetFrameMaximumSize(protocol_version());
369 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
370 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
373 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type
) const {
374 return SpdyConstants::GetPrefixLength(type
, protocol_version());
377 const char* SpdyFramer::StateToString(int state
) {
381 case SPDY_AUTO_RESET
:
385 case SPDY_READING_COMMON_HEADER
:
386 return "READING_COMMON_HEADER";
387 case SPDY_CONTROL_FRAME_PAYLOAD
:
388 return "CONTROL_FRAME_PAYLOAD";
389 case SPDY_READ_DATA_FRAME_PADDING_LENGTH
:
390 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
391 case SPDY_CONSUME_PADDING
:
392 return "SPDY_CONSUME_PADDING";
393 case SPDY_IGNORE_REMAINING_PAYLOAD
:
394 return "IGNORE_REMAINING_PAYLOAD";
395 case SPDY_FORWARD_STREAM_FRAME
:
396 return "FORWARD_STREAM_FRAME";
397 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
398 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
399 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
400 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
401 case SPDY_GOAWAY_FRAME_PAYLOAD
:
402 return "SPDY_GOAWAY_FRAME_PAYLOAD";
403 case SPDY_RST_STREAM_FRAME_PAYLOAD
:
404 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
405 case SPDY_SETTINGS_FRAME_PAYLOAD
:
406 return "SPDY_SETTINGS_FRAME_PAYLOAD";
407 case SPDY_ALTSVC_FRAME_PAYLOAD
:
408 return "SPDY_ALTSVC_FRAME_PAYLOAD";
410 return "UNKNOWN_STATE";
413 void SpdyFramer::set_error(SpdyError error
) {
416 // These values will usually get reset once we come to the end
417 // of a header block, but if we run into an error that
418 // might not happen, so reset them here.
419 expect_continuation_
= 0;
420 end_stream_when_done_
= false;
422 CHANGE_STATE(SPDY_ERROR
);
423 visitor_
->OnError(this);
426 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
427 switch (error_code
) {
430 case SPDY_INVALID_CONTROL_FRAME
:
431 return "INVALID_CONTROL_FRAME";
432 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
433 return "CONTROL_PAYLOAD_TOO_LARGE";
434 case SPDY_ZLIB_INIT_FAILURE
:
435 return "ZLIB_INIT_FAILURE";
436 case SPDY_UNSUPPORTED_VERSION
:
437 return "UNSUPPORTED_VERSION";
438 case SPDY_DECOMPRESS_FAILURE
:
439 return "DECOMPRESS_FAILURE";
440 case SPDY_COMPRESS_FAILURE
:
441 return "COMPRESS_FAILURE";
442 case SPDY_INVALID_DATA_FRAME_FLAGS
:
443 return "SPDY_INVALID_DATA_FRAME_FLAGS";
444 case SPDY_INVALID_CONTROL_FRAME_FLAGS
:
445 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
446 case SPDY_UNEXPECTED_FRAME
:
447 return "UNEXPECTED_FRAME";
449 return "UNKNOWN_ERROR";
452 const char* SpdyFramer::StatusCodeToString(int status_code
) {
453 switch (status_code
) {
454 case RST_STREAM_INVALID
:
456 case RST_STREAM_PROTOCOL_ERROR
:
457 return "PROTOCOL_ERROR";
458 case RST_STREAM_INVALID_STREAM
:
459 return "INVALID_STREAM";
460 case RST_STREAM_REFUSED_STREAM
:
461 return "REFUSED_STREAM";
462 case RST_STREAM_UNSUPPORTED_VERSION
:
463 return "UNSUPPORTED_VERSION";
464 case RST_STREAM_CANCEL
:
466 case RST_STREAM_INTERNAL_ERROR
:
467 return "INTERNAL_ERROR";
468 case RST_STREAM_FLOW_CONTROL_ERROR
:
469 return "FLOW_CONTROL_ERROR";
470 case RST_STREAM_STREAM_IN_USE
:
471 return "STREAM_IN_USE";
472 case RST_STREAM_STREAM_ALREADY_CLOSED
:
473 return "STREAM_ALREADY_CLOSED";
474 case RST_STREAM_INVALID_CREDENTIALS
:
475 return "INVALID_CREDENTIALS";
476 case RST_STREAM_FRAME_TOO_LARGE
:
477 return "FRAME_TOO_LARGE";
478 case RST_STREAM_CONNECT_ERROR
:
479 return "CONNECT_ERROR";
480 case RST_STREAM_ENHANCE_YOUR_CALM
:
481 return "ENHANCE_YOUR_CALM";
482 case RST_STREAM_INADEQUATE_SECURITY
:
483 return "INADEQUATE_SECURITY";
484 case RST_STREAM_HTTP_1_1_REQUIRED
:
485 return "HTTP_1_1_REQUIRED";
487 return "UNKNOWN_STATUS";
490 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type
) {
509 return "WINDOW_UPDATE";
513 return "PUSH_PROMISE";
515 return "CONTINUATION";
523 return "UNKNOWN_CONTROL_TYPE";
526 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
530 size_t original_len
= len
;
532 previous_state_
= state_
;
537 case SPDY_AUTO_RESET
:
541 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
545 case SPDY_READING_COMMON_HEADER
: {
546 size_t bytes_read
= ProcessCommonHeader(data
, len
);
552 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
553 // Control frames that contain header blocks
554 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
555 // take a different path through the state machine - they
557 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
558 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
560 // SETTINGS frames take a slightly modified route:
561 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
562 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
564 // All other control frames will use the alternate route directly to
565 // SPDY_CONTROL_FRAME_PAYLOAD
566 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
572 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
573 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
579 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
580 int bytes_read
= ProcessControlFrameHeaderBlock(
581 data
, len
, protocol_version() > SPDY3
);
587 case SPDY_RST_STREAM_FRAME_PAYLOAD
: {
588 size_t bytes_read
= ProcessRstStreamFramePayload(data
, len
);
594 case SPDY_GOAWAY_FRAME_PAYLOAD
: {
595 size_t bytes_read
= ProcessGoAwayFramePayload(data
, len
);
601 case SPDY_ALTSVC_FRAME_PAYLOAD
: {
602 size_t bytes_read
= ProcessAltSvcFramePayload(data
, len
);
608 case SPDY_CONTROL_FRAME_PAYLOAD
: {
609 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
615 case SPDY_READ_DATA_FRAME_PADDING_LENGTH
: {
616 size_t bytes_read
= ProcessDataFramePaddingLength(data
, len
);
622 case SPDY_CONSUME_PADDING
: {
623 size_t bytes_read
= ProcessFramePadding(data
, len
);
629 case SPDY_IGNORE_REMAINING_PAYLOAD
: {
630 size_t bytes_read
= ProcessIgnoredControlFramePayload(/*data,*/ len
);
636 case SPDY_FORWARD_STREAM_FRAME
: {
637 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
644 LOG(DFATAL
) << "Invalid value for " << display_protocol_
645 << " framer state: " << state_
;
646 // This ensures that we don't infinite-loop if state_ gets an
647 // invalid value somehow, such as due to a SpdyFramer getting deleted
648 // from a callback it calls.
651 } while (state_
!= previous_state_
);
653 DCHECK(len
== 0 || state_
== SPDY_ERROR
);
654 if (current_frame_buffer_length_
== 0 &&
655 remaining_data_length_
== 0 &&
656 remaining_control_header_
== 0) {
657 DCHECK(state_
== SPDY_RESET
|| state_
== SPDY_ERROR
)
658 << "State: " << StateToString(state_
);
661 return original_len
- len
;
664 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
665 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
667 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
669 size_t original_len
= len
;
671 // Update current frame buffer as needed.
672 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
673 size_t bytes_desired
=
674 GetControlFrameHeaderSize() - current_frame_buffer_length_
;
675 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
678 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
679 // Not enough information to do anything meaningful.
680 return original_len
- len
;
683 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
684 // when processing DATA frames below.
685 scoped_ptr
<SpdyFrameReader
> reader(
686 new SpdyFrameReader(current_frame_buffer_
.get(),
687 current_frame_buffer_length_
));
689 bool is_control_frame
= false;
691 int control_frame_type_field
=
692 SpdyConstants::DataFrameType(protocol_version());
693 // ProcessControlFrameHeader() will set current_frame_type_ to the
694 // correct value if this is a valid control frame.
695 current_frame_type_
= DATA
;
696 if (protocol_version() <= SPDY3
) {
698 bool successful_read
= reader
->ReadUInt16(&version
);
699 DCHECK(successful_read
);
700 is_control_frame
= (version
& kControlFlagMask
) != 0;
701 version
&= ~kControlFlagMask
; // Only valid for control frames.
702 if (is_control_frame
) {
703 // We check version before we check validity: version can never be
704 // 'invalid', it can only be unsupported.
705 if (version
< SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION
) ||
706 version
> SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION
) ||
707 SpdyConstants::ParseMajorVersion(version
) != protocol_version()) {
708 // Version does not match the version the framer was initialized with.
709 DVLOG(1) << "Unsupported SPDY version "
711 << " (expected " << protocol_version() << ")";
712 set_error(SPDY_UNSUPPORTED_VERSION
);
715 // We check control_frame_type_field's validity in
716 // ProcessControlFrameHeader().
717 uint16 control_frame_type_field_uint16
;
718 successful_read
= reader
->ReadUInt16(&control_frame_type_field_uint16
);
719 control_frame_type_field
= control_frame_type_field_uint16
;
722 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
724 DCHECK(successful_read
);
726 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
727 DCHECK(successful_read
);
729 uint32 length_field
= 0;
730 successful_read
= reader
->ReadUInt24(&length_field
);
731 DCHECK(successful_read
);
732 remaining_data_length_
= length_field
;
733 current_frame_length_
= remaining_data_length_
+ reader
->GetBytesConsumed();
735 uint32 length_field
= 0;
736 bool successful_read
= reader
->ReadUInt24(&length_field
);
737 DCHECK(successful_read
);
739 uint8 control_frame_type_field_uint8
;
740 successful_read
= reader
->ReadUInt8(&control_frame_type_field_uint8
);
741 DCHECK(successful_read
);
742 // We check control_frame_type_field's validity in
743 // ProcessControlFrameHeader().
744 control_frame_type_field
= control_frame_type_field_uint8
;
745 is_control_frame
= control_frame_type_field
!=
746 SpdyConstants::SerializeFrameType(protocol_version(), DATA
);
748 if (is_control_frame
) {
749 current_frame_length_
= length_field
+ GetControlFrameHeaderSize();
751 current_frame_length_
= length_field
+ GetDataFrameMinimumSize();
754 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
755 DCHECK(successful_read
);
757 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
758 DCHECK(successful_read
);
760 remaining_data_length_
= current_frame_length_
- reader
->GetBytesConsumed();
762 // Before we accept a DATA frame, we need to make sure we're not in the
763 // middle of processing a header block.
764 const bool is_continuation_frame
= (control_frame_type_field
==
765 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION
));
766 if ((expect_continuation_
!= 0) != is_continuation_frame
) {
767 if (expect_continuation_
!= 0) {
768 DLOG(ERROR
) << "The framer was expecting to receive a CONTINUATION "
769 << "frame, but instead received frame type "
770 << control_frame_type_field
;
772 DLOG(ERROR
) << "The framer received an unexpected CONTINUATION frame.";
774 set_error(SPDY_UNEXPECTED_FRAME
);
775 return original_len
- len
;
778 DCHECK_EQ(is_control_frame
? GetControlFrameHeaderSize()
779 : GetDataFrameMinimumSize(),
780 reader
->GetBytesConsumed());
781 DCHECK_EQ(current_frame_length_
,
782 remaining_data_length_
+ reader
->GetBytesConsumed());
784 // This is just a sanity check for help debugging early frame errors.
785 if (remaining_data_length_
> 1000000u) {
786 // The strncmp for 5 is safe because we only hit this point if we
787 // have kMinCommonHeader (8) bytes
788 if (!syn_frame_processed_
&&
789 strncmp(current_frame_buffer_
.get(), "HTTP/", 5) == 0) {
790 LOG(WARNING
) << "Unexpected HTTP response to " << display_protocol_
792 probable_http_response_
= true;
794 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
795 << " session is likely corrupt.";
799 // if we're here, then we have the common header all received.
800 if (!is_control_frame
) {
801 if (protocol_version() > SPDY3
) {
802 // Catch bogus tests sending oversized DATA frames.
803 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_
)
804 << "DATA frame too large for SPDY >= 4.";
807 uint8 valid_data_flags
= 0;
808 if (protocol_version() > SPDY3
) {
810 DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
| DATA_FLAG_PADDED
;
812 valid_data_flags
= DATA_FLAG_FIN
;
815 if (current_frame_flags_
& ~valid_data_flags
) {
816 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
818 visitor_
->OnDataFrameHeader(current_frame_stream_id_
,
819 remaining_data_length_
,
820 current_frame_flags_
& DATA_FLAG_FIN
);
821 if (remaining_data_length_
> 0) {
822 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH
);
825 if (current_frame_flags_
& DATA_FLAG_FIN
) {
826 visitor_
->OnStreamFrameData(
827 current_frame_stream_id_
, NULL
, 0, true);
829 CHANGE_STATE(SPDY_AUTO_RESET
);
833 ProcessControlFrameHeader(control_frame_type_field
);
836 return original_len
- len
;
839 void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field
) {
840 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
841 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_
);
843 // TODO(mlavan): Either remove credential frames from the code entirely,
844 // or add them to parsing + serialization methods for SPDY3.
845 // Early detection of deprecated frames that we ignore.
846 if (protocol_version() <= SPDY3
) {
847 if (control_frame_type_field
== CREDENTIAL
) {
848 current_frame_type_
= CREDENTIAL
;
849 DCHECK_EQ(SPDY3
, protocol_version());
850 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
851 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
856 if (!SpdyConstants::IsValidFrameType(protocol_version(),
857 control_frame_type_field
)) {
858 if (protocol_version() <= SPDY3
) {
859 DLOG(WARNING
) << "Invalid control frame type " << control_frame_type_field
860 << " (protocol version: " << protocol_version() << ")";
861 set_error(SPDY_INVALID_CONTROL_FRAME
);
864 // In HTTP2 we ignore unknown frame types for extensibility, as long as
865 // the rest of the control frame header is valid.
866 // We rely on the visitor to check validity of current_frame_stream_id_.
867 bool valid_stream
= visitor_
->OnUnknownFrame(current_frame_stream_id_
,
868 control_frame_type_field
);
870 DVLOG(1) << "Ignoring unknown frame type.";
871 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
873 // Report an invalid frame error and close the stream if the
874 // stream_id is not valid.
875 DLOG(WARNING
) << "Unknown control frame type "
876 << control_frame_type_field
877 << " received on invalid stream "
878 << current_frame_stream_id_
;
879 set_error(SPDY_INVALID_CONTROL_FRAME
);
885 current_frame_type_
= SpdyConstants::ParseFrameType(protocol_version(),
886 control_frame_type_field
);
888 // Do some sanity checking on the control frame sizes and flags.
889 switch (current_frame_type_
) {
891 if (current_frame_length_
< GetSynStreamMinimumSize()) {
892 set_error(SPDY_INVALID_CONTROL_FRAME
);
893 } else if (current_frame_flags_
&
894 ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
895 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
899 if (current_frame_length_
< GetSynReplyMinimumSize()) {
900 set_error(SPDY_INVALID_CONTROL_FRAME
);
901 } else if (current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
902 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
906 // For SPDY versions < 4, the header has a fixed length.
907 // For SPDY version 4 and up, the RST_STREAM frame may include optional
908 // opaque data, so we only have a lower limit on the frame size.
909 if ((current_frame_length_
!= GetRstStreamMinimumSize() &&
910 protocol_version() <= SPDY3
) ||
911 (current_frame_length_
< GetRstStreamMinimumSize() &&
912 protocol_version() > SPDY3
)) {
913 set_error(SPDY_INVALID_CONTROL_FRAME
);
914 } else if (current_frame_flags_
!= 0) {
915 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
920 // Make sure that we have an integral number of 8-byte key/value pairs,
921 // plus a 4-byte length field in SPDY3 and below.
922 size_t values_prefix_size
= (protocol_version() <= SPDY3
? 4 : 0);
923 // Size of each key/value pair in bytes.
924 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
925 if (current_frame_length_
< GetSettingsMinimumSize() ||
926 (current_frame_length_
- GetControlFrameHeaderSize())
927 % setting_size
!= values_prefix_size
) {
928 DLOG(WARNING
) << "Invalid length for SETTINGS frame: "
929 << current_frame_length_
;
930 set_error(SPDY_INVALID_CONTROL_FRAME
);
931 } else if (protocol_version() <= SPDY3
&&
932 current_frame_flags_
&
933 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
934 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
935 } else if (protocol_version() > SPDY3
&&
936 current_frame_flags_
& ~SETTINGS_FLAG_ACK
) {
937 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
938 } else if (protocol_version() > SPDY3
&&
939 current_frame_flags_
& SETTINGS_FLAG_ACK
&&
940 current_frame_length_
> GetSettingsMinimumSize()) {
941 set_error(SPDY_INVALID_CONTROL_FRAME
);
946 if (current_frame_length_
!= GetPingSize()) {
947 set_error(SPDY_INVALID_CONTROL_FRAME
);
948 } else if ((protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) ||
949 (current_frame_flags_
& ~PING_FLAG_ACK
)) {
950 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
955 // For SPDY version < 4, there are only mandatory fields and the header
956 // has a fixed length. For SPDY version >= 4, optional opaque data may
957 // be appended to the GOAWAY frame, thus there is only a minimal length
959 if ((current_frame_length_
!= GetGoAwayMinimumSize() &&
960 protocol_version() <= SPDY3
) ||
961 (current_frame_length_
< GetGoAwayMinimumSize() &&
962 protocol_version() > SPDY3
)) {
963 set_error(SPDY_INVALID_CONTROL_FRAME
);
964 } else if (current_frame_flags_
!= 0) {
965 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
971 size_t min_size
= GetHeadersMinimumSize();
972 if (protocol_version() > SPDY3
&&
973 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
)) {
976 if (current_frame_length_
< min_size
) {
977 // TODO(mlavan): check here for HEADERS with no payload?
978 // (not allowed in SPDY4)
979 set_error(SPDY_INVALID_CONTROL_FRAME
);
980 } else if (protocol_version() <= SPDY3
&&
981 current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
982 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
983 } else if (protocol_version() > SPDY3
&&
984 current_frame_flags_
&
985 ~(CONTROL_FLAG_FIN
| HEADERS_FLAG_PRIORITY
|
986 HEADERS_FLAG_END_HEADERS
| HEADERS_FLAG_END_SEGMENT
|
987 HEADERS_FLAG_PADDED
)) {
988 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
993 if (current_frame_length_
!= GetWindowUpdateSize()) {
994 set_error(SPDY_INVALID_CONTROL_FRAME
);
995 } else if (current_frame_flags_
!= 0) {
996 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1000 if (current_frame_length_
!= GetBlockedSize() ||
1001 protocol_version() <= SPDY3
) {
1002 set_error(SPDY_INVALID_CONTROL_FRAME
);
1003 } else if (current_frame_flags_
!= 0) {
1004 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1008 if (current_frame_length_
< GetPushPromiseMinimumSize()) {
1009 set_error(SPDY_INVALID_CONTROL_FRAME
);
1010 } else if (protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) {
1011 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1012 } else if (protocol_version() > SPDY3
&&
1013 current_frame_flags_
&
1014 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
1015 HEADERS_FLAG_PADDED
)) {
1016 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1020 if (current_frame_length_
< GetContinuationMinimumSize() ||
1021 protocol_version() <= SPDY3
) {
1022 set_error(SPDY_INVALID_CONTROL_FRAME
);
1023 } else if (current_frame_flags_
& ~HEADERS_FLAG_END_HEADERS
) {
1024 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1028 if (current_frame_length_
<= GetAltSvcMinimumSize()) {
1029 set_error(SPDY_INVALID_CONTROL_FRAME
);
1030 } else if (current_frame_flags_
!= 0) {
1031 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1035 if (current_frame_length_
!= GetPrioritySize() ||
1036 protocol_version() <= SPDY3
) {
1037 set_error(SPDY_INVALID_CONTROL_FRAME
);
1038 } else if (current_frame_flags_
!= 0) {
1039 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1043 LOG(WARNING
) << "Valid " << display_protocol_
1044 << " control frame with unhandled type: "
1045 << current_frame_type_
;
1046 // This branch should be unreachable because of the frame type bounds
1047 // check above. However, we DLOG(FATAL) here in an effort to painfully
1048 // club the head of the developer who failed to keep this file in sync
1049 // with spdy_protocol.h.
1051 set_error(SPDY_INVALID_CONTROL_FRAME
);
1055 if (state_
== SPDY_ERROR
) {
1059 if (current_frame_length_
>
1060 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1061 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1062 DLOG(WARNING
) << "Received control frame of type " << current_frame_type_
1063 << " with way too big of a payload: "
1064 << current_frame_length_
;
1065 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1069 if (current_frame_type_
== GOAWAY
) {
1070 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD
);
1074 if (current_frame_type_
== RST_STREAM
) {
1075 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD
);
1079 if (current_frame_type_
== ALTSVC
) {
1080 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD
);
1083 // Determine the frame size without variable-length data.
1084 int32 frame_size_without_variable_data
;
1085 switch (current_frame_type_
) {
1087 syn_frame_processed_
= true;
1088 frame_size_without_variable_data
= GetSynStreamMinimumSize();
1091 syn_frame_processed_
= true;
1092 frame_size_without_variable_data
= GetSynReplyMinimumSize();
1095 frame_size_without_variable_data
= GetSettingsMinimumSize();
1098 frame_size_without_variable_data
= GetHeadersMinimumSize();
1099 if (protocol_version() > SPDY3
) {
1100 if (current_frame_flags_
& HEADERS_FLAG_PADDED
) {
1101 frame_size_without_variable_data
+= kPadLengthFieldSize
;
1103 if (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1104 frame_size_without_variable_data
+=
1105 kPriorityDependencyPayloadSize
+
1106 kPriorityWeightPayloadSize
;
1111 frame_size_without_variable_data
= GetPushPromiseMinimumSize();
1112 if (protocol_version() > SPDY3
&&
1113 current_frame_flags_
& PUSH_PROMISE_FLAG_PADDED
) {
1114 frame_size_without_variable_data
+= kPadLengthFieldSize
;
1118 frame_size_without_variable_data
= GetContinuationMinimumSize();
1121 frame_size_without_variable_data
= -1;
1125 if ((frame_size_without_variable_data
== -1) &&
1126 (current_frame_length_
> kControlFrameBufferSize
)) {
1127 // We should already be in an error state. Double-check.
1128 DCHECK_EQ(SPDY_ERROR
, state_
);
1129 if (state_
!= SPDY_ERROR
) {
1130 LOG(DFATAL
) << display_protocol_
1131 << " control frame buffer too small for fixed-length frame.";
1132 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1137 if (frame_size_without_variable_data
> 0) {
1138 // We have a control frame with a header block. We need to parse the
1139 // remainder of the control frame's header before we can parse the header
1140 // block. The start of the header block varies with the control type.
1141 DCHECK_GE(frame_size_without_variable_data
,
1142 static_cast<int32
>(current_frame_buffer_length_
));
1143 remaining_control_header_
= frame_size_without_variable_data
-
1144 current_frame_buffer_length_
;
1146 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
1150 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
1153 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
1155 size_t bytes_to_read
= std::min(*len
, max_bytes
);
1156 if (bytes_to_read
> 0) {
1157 DCHECK_GE(kControlFrameBufferSize
,
1158 current_frame_buffer_length_
+ bytes_to_read
);
1159 memcpy(current_frame_buffer_
.get() + current_frame_buffer_length_
,
1162 current_frame_buffer_length_
+= bytes_to_read
;
1163 *data
+= bytes_to_read
;
1164 *len
-= bytes_to_read
;
1166 return bytes_to_read
;
1169 size_t SpdyFramer::GetSerializedLength(
1170 const SpdyMajorVersion spdy_version
,
1171 const SpdyHeaderBlock
* headers
) {
1172 const size_t num_name_value_pairs_size
1173 = (spdy_version
< SPDY3
) ? sizeof(uint16
) : sizeof(uint32
);
1174 const size_t length_of_name_size
= num_name_value_pairs_size
;
1175 const size_t length_of_value_size
= num_name_value_pairs_size
;
1177 size_t total_length
= num_name_value_pairs_size
;
1178 for (SpdyHeaderBlock::const_iterator it
= headers
->begin();
1179 it
!= headers
->end();
1181 // We add space for the length of the name and the length of the value as
1182 // well as the length of the name and the length of the value.
1183 total_length
+= length_of_name_size
+ it
->first
.size() +
1184 length_of_value_size
+ it
->second
.size();
1186 return total_length
;
1189 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder
* frame
,
1190 const SpdyMajorVersion spdy_version
,
1191 const SpdyHeaderBlock
* headers
) {
1192 if (spdy_version
< SPDY3
) {
1193 frame
->WriteUInt16(static_cast<uint16
>(headers
->size()));
1195 frame
->WriteUInt32(headers
->size());
1197 SpdyHeaderBlock::const_iterator it
;
1198 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1199 if (spdy_version
< SPDY3
) {
1200 frame
->WriteString(it
->first
);
1201 frame
->WriteString(it
->second
);
1203 frame
->WriteStringPiece32(it
->first
);
1204 frame
->WriteStringPiece32(it
->second
);
1209 // TODO(phajdan.jr): Clean up after we no longer need
1210 // to workaround http://crbug.com/139744.
1211 #if !defined(USE_SYSTEM_ZLIB)
1213 // These constants are used by zlib to differentiate between normal data and
1214 // cookie data. Cookie data is handled specially by zlib when compressing.
1216 // kZStandardData is compressed normally, save that it will never match
1217 // against any other class of data in the window.
1218 kZStandardData
= Z_CLASS_STANDARD
,
1219 // kZCookieData is compressed in its own Huffman blocks and only matches in
1220 // its entirety and only against other kZCookieData blocks. Any matches must
1221 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1222 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1224 kZCookieData
= Z_CLASS_COOKIE
,
1225 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1226 // against the window.
1227 kZHuffmanOnlyData
= Z_CLASS_HUFFMAN_ONLY
,
1230 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1231 // needed when switching between classes of data.
1232 static void WriteZ(const base::StringPiece
& data
,
1237 // If we are switching from standard to non-standard data then we need to end
1238 // the current Huffman context to avoid it leaking between them.
1239 if (out
->clas
== kZStandardData
&&
1240 clas
!= kZStandardData
) {
1242 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1243 DCHECK_EQ(Z_OK
, rv
);
1244 DCHECK_EQ(0u, out
->avail_in
);
1245 DCHECK_LT(0u, out
->avail_out
);
1248 out
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
.data()));
1249 out
->avail_in
= data
.size();
1251 if (clas
== kZStandardData
) {
1252 rv
= deflate(out
, Z_NO_FLUSH
);
1254 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1256 if (!data
.empty()) {
1257 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1258 DCHECK_EQ(Z_OK
, rv
);
1260 DCHECK_EQ(0u, out
->avail_in
);
1261 DCHECK_LT(0u, out
->avail_out
);
1264 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1265 static void WriteLengthZ(size_t n
,
1270 DCHECK_LE(length
, sizeof(buf
));
1271 for (unsigned i
= 1; i
<= length
; i
++) {
1272 buf
[length
- i
] = static_cast<char>(n
);
1275 WriteZ(base::StringPiece(buf
, length
), clas
, out
);
1278 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1279 // manner that resists the length of the compressed data from compromising
1281 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
1282 z_stream
* z
) const {
1283 unsigned length_length
= 4;
1284 if (protocol_version() < 3)
1287 WriteLengthZ(headers
->size(), length_length
, kZStandardData
, z
);
1289 std::map
<std::string
, std::string
>::const_iterator it
;
1290 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1291 WriteLengthZ(it
->first
.size(), length_length
, kZStandardData
, z
);
1292 WriteZ(it
->first
, kZStandardData
, z
);
1294 if (it
->first
== "cookie") {
1295 // We require the cookie values (save for the last) to end with a
1296 // semicolon and (save for the first) to start with a space. This is
1297 // typically the format that we are given them in but we reserialize them
1300 std::vector
<base::StringPiece
> cookie_values
;
1301 size_t cookie_length
= 0;
1302 base::StringPiece
cookie_data(it
->second
);
1305 while (!cookie_data
.empty() &&
1306 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
1307 cookie_data
.remove_prefix(1);
1309 if (cookie_data
.empty())
1313 for (i
= 0; i
< cookie_data
.size(); i
++) {
1314 if (cookie_data
[i
] == ';')
1317 if (i
< cookie_data
.size()) {
1318 if (!IsCookieEmpty(cookie_data
.substr(0, i
))) {
1319 cookie_values
.push_back(cookie_data
.substr(0, i
));
1320 cookie_length
+= i
+ 2 /* semicolon and space */;
1322 cookie_data
.remove_prefix(i
+ 1);
1324 if (!IsCookieEmpty(cookie_data
)) {
1325 cookie_values
.push_back(cookie_data
);
1326 cookie_length
+= cookie_data
.size();
1327 } else if (cookie_length
> 2) {
1328 cookie_length
-= 2 /* compensate for previously added length */;
1330 cookie_data
.remove_prefix(i
);
1334 WriteLengthZ(cookie_length
, length_length
, kZStandardData
, z
);
1335 for (size_t i
= 0; i
< cookie_values
.size(); i
++) {
1337 // Since zlib will only back-reference complete cookies, a cookie that
1338 // is currently last (and so doesn't have a trailing semicolon) won't
1339 // match if it's later in a non-final position. The same is true of
1340 // the first cookie.
1341 if (i
== 0 && cookie_values
.size() == 1) {
1342 cookie
= cookie_values
[i
].as_string();
1343 } else if (i
== 0) {
1344 cookie
= cookie_values
[i
].as_string() + ";";
1345 } else if (i
< cookie_values
.size() - 1) {
1346 cookie
= " " + cookie_values
[i
].as_string() + ";";
1348 cookie
= " " + cookie_values
[i
].as_string();
1350 WriteZ(cookie
, kZCookieData
, z
);
1352 } else if (it
->first
== "accept" ||
1353 it
->first
== "accept-charset" ||
1354 it
->first
== "accept-encoding" ||
1355 it
->first
== "accept-language" ||
1356 it
->first
== "host" ||
1357 it
->first
== "version" ||
1358 it
->first
== "method" ||
1359 it
->first
== "scheme" ||
1360 it
->first
== ":host" ||
1361 it
->first
== ":version" ||
1362 it
->first
== ":method" ||
1363 it
->first
== ":scheme" ||
1364 it
->first
== "user-agent") {
1365 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1366 WriteZ(it
->second
, kZStandardData
, z
);
1368 // Non-whitelisted headers are Huffman compressed in their own block, but
1369 // don't match against the window.
1370 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1371 WriteZ(it
->second
, kZHuffmanOnlyData
, z
);
1376 int rv
= deflate(z
, Z_SYNC_FLUSH
);
1377 DCHECK_EQ(Z_OK
, rv
);
1378 z
->clas
= kZStandardData
;
1381 #endif // !defined(USE_SYSTEM_ZLIB)
1383 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
1385 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
1386 const size_t original_len
= len
;
1388 if (remaining_control_header_
> 0) {
1389 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1390 remaining_control_header_
);
1391 remaining_control_header_
-= bytes_read
;
1392 remaining_data_length_
-= bytes_read
;
1395 if (remaining_control_header_
== 0) {
1396 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1397 current_frame_buffer_length_
);
1398 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1400 switch (current_frame_type_
) {
1403 DCHECK_GE(SPDY3
, protocol_version());
1404 bool successful_read
= true;
1405 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1406 DCHECK(successful_read
);
1407 if (current_frame_stream_id_
== 0) {
1408 set_error(SPDY_INVALID_CONTROL_FRAME
);
1412 SpdyStreamId associated_to_stream_id
= kInvalidStream
;
1413 successful_read
= reader
.ReadUInt31(&associated_to_stream_id
);
1414 DCHECK(successful_read
);
1416 SpdyPriority priority
= 0;
1417 successful_read
= reader
.ReadUInt8(&priority
);
1418 DCHECK(successful_read
);
1419 if (protocol_version() <= SPDY2
) {
1420 priority
= priority
>> 6;
1422 priority
= priority
>> 5;
1425 // Seek past unused byte; used to be credential slot in SPDY 3.
1428 DCHECK(reader
.IsDoneReading());
1429 if (debug_visitor_
) {
1430 debug_visitor_
->OnReceiveCompressedFrame(
1431 current_frame_stream_id_
,
1432 current_frame_type_
,
1433 current_frame_length_
);
1435 visitor_
->OnSynStream(
1436 current_frame_stream_id_
,
1437 associated_to_stream_id
,
1439 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1440 (current_frame_flags_
& CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
1442 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1445 if (protocol_version() > SPDY3
&&
1446 current_frame_flags_
& SETTINGS_FLAG_ACK
) {
1447 visitor_
->OnSettingsAck();
1448 CHANGE_STATE(SPDY_AUTO_RESET
);
1450 visitor_
->OnSettings(current_frame_flags_
&
1451 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
);
1452 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
1457 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1459 if (protocol_version() > SPDY3
) {
1460 DCHECK_EQ(HEADERS
, current_frame_type_
);
1462 bool successful_read
= true;
1463 if (protocol_version() <= SPDY3
) {
1464 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1465 DCHECK(successful_read
);
1467 if (current_frame_stream_id_
== 0) {
1468 set_error(SPDY_INVALID_CONTROL_FRAME
);
1471 if (protocol_version() <= SPDY2
) {
1472 // SPDY 2 had two unused bytes here. Seek past them.
1475 if (protocol_version() > SPDY3
&&
1476 !(current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) &&
1477 current_frame_type_
== HEADERS
) {
1478 expect_continuation_
= current_frame_stream_id_
;
1479 end_stream_when_done_
= current_frame_flags_
& CONTROL_FLAG_FIN
;
1481 if (protocol_version() > SPDY3
&&
1482 current_frame_flags_
& HEADERS_FLAG_PADDED
) {
1483 uint8 pad_payload_len
= 0;
1484 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
1485 successful_read
= reader
.ReadUInt8(&pad_payload_len
);
1486 DCHECK(successful_read
);
1487 remaining_padding_payload_length_
= pad_payload_len
;
1489 const bool has_priority
=
1490 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0;
1491 SpdyPriority priority
= 0;
1492 if (protocol_version() > SPDY3
&& has_priority
) {
1493 // TODO(jgraettinger): Process dependency rather than ignoring it.
1494 reader
.Seek(kPriorityDependencyPayloadSize
);
1496 successful_read
= reader
.ReadUInt8(&weight
);
1497 if (successful_read
) {
1498 priority
= MapWeightToPriority(weight
);
1501 DCHECK(reader
.IsDoneReading());
1502 if (debug_visitor_
) {
1503 debug_visitor_
->OnReceiveCompressedFrame(
1504 current_frame_stream_id_
,
1505 current_frame_type_
,
1506 current_frame_length_
);
1508 if (current_frame_type_
== SYN_REPLY
) {
1509 visitor_
->OnSynReply(
1510 current_frame_stream_id_
,
1511 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0);
1513 visitor_
->OnHeaders(
1514 current_frame_stream_id_
,
1515 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0, priority
,
1516 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1517 expect_continuation_
== 0);
1520 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1524 DCHECK_LT(SPDY3
, protocol_version());
1525 if (current_frame_stream_id_
== 0) {
1526 set_error(SPDY_INVALID_CONTROL_FRAME
);
1529 bool successful_read
= true;
1530 if (protocol_version() > SPDY3
&&
1531 current_frame_flags_
& PUSH_PROMISE_FLAG_PADDED
) {
1532 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
1533 uint8 pad_payload_len
= 0;
1534 successful_read
= reader
.ReadUInt8(&pad_payload_len
);
1535 DCHECK(successful_read
);
1536 remaining_padding_payload_length_
= pad_payload_len
;
1540 SpdyStreamId promised_stream_id
= kInvalidStream
;
1541 bool successful_read
= reader
.ReadUInt31(&promised_stream_id
);
1542 DCHECK(successful_read
);
1543 DCHECK(reader
.IsDoneReading());
1544 if (promised_stream_id
== 0) {
1545 set_error(SPDY_INVALID_CONTROL_FRAME
);
1548 if (!(current_frame_flags_
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
1549 expect_continuation_
= current_frame_stream_id_
;
1551 if (debug_visitor_
) {
1552 debug_visitor_
->OnReceiveCompressedFrame(
1553 current_frame_stream_id_
,
1554 current_frame_type_
,
1555 current_frame_length_
);
1557 visitor_
->OnPushPromise(current_frame_stream_id_
,
1559 (current_frame_flags_
&
1560 PUSH_PROMISE_FLAG_END_PUSH_PROMISE
) != 0);
1562 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1566 // Check to make sure the stream id of the current frame is
1567 // the same as that of the preceding frame.
1568 // If we're at this point we should already know that
1569 // expect_continuation_ != 0, so this doubles as a check
1570 // that current_frame_stream_id != 0.
1571 if (current_frame_stream_id_
!= expect_continuation_
) {
1572 set_error(SPDY_INVALID_CONTROL_FRAME
);
1575 if (current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) {
1576 expect_continuation_
= 0;
1578 if (debug_visitor_
) {
1579 debug_visitor_
->OnReceiveCompressedFrame(
1580 current_frame_stream_id_
,
1581 current_frame_type_
,
1582 current_frame_length_
);
1584 visitor_
->OnContinuation(current_frame_stream_id_
,
1585 (current_frame_flags_
&
1586 HEADERS_FLAG_END_HEADERS
) != 0);
1588 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1594 return original_len
- len
;
1597 // Does not buffer the control payload. Instead, either passes directly to the
1598 // visitor or decompresses and then passes directly to the visitor, via
1599 // IncrementallyDeliverControlFrameHeaderData() or
1600 // IncrementallyDecompressControlFrameHeaderData() respectively.
1601 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
1603 bool is_hpack_header_block
) {
1604 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
1606 bool processed_successfully
= true;
1607 if (current_frame_type_
!= SYN_STREAM
&&
1608 current_frame_type_
!= SYN_REPLY
&&
1609 current_frame_type_
!= HEADERS
&&
1610 current_frame_type_
!= PUSH_PROMISE
&&
1611 current_frame_type_
!= CONTINUATION
) {
1612 LOG(DFATAL
) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1614 size_t process_bytes
= std::min(
1615 data_len
, remaining_data_length_
- remaining_padding_payload_length_
);
1616 if (is_hpack_header_block
) {
1617 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1618 current_frame_stream_id_
, data
, process_bytes
)) {
1619 // TODO(jgraettinger): Finer-grained HPACK error codes.
1620 set_error(SPDY_DECOMPRESS_FAILURE
);
1621 processed_successfully
= false;
1623 } else if (process_bytes
> 0) {
1624 if (enable_compression_
&& protocol_version() <= SPDY3
) {
1625 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
1626 current_frame_stream_id_
, data
, process_bytes
);
1628 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
1629 current_frame_stream_id_
, data
, process_bytes
);
1632 remaining_data_length_
-= process_bytes
;
1634 // Handle the case that there is no futher data in this frame.
1635 if (remaining_data_length_
== remaining_padding_payload_length_
&&
1636 processed_successfully
) {
1637 if (expect_continuation_
== 0) {
1638 if (is_hpack_header_block
) {
1639 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1640 current_frame_stream_id_
)) {
1641 set_error(SPDY_DECOMPRESS_FAILURE
);
1642 processed_successfully
= false;
1644 // TODO(jgraettinger): To be removed with migration to
1645 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1646 // block, delivered via reentrant call to
1647 // ProcessControlFrameHeaderBlock().
1648 DeliverHpackBlockAsSpdy3Block();
1649 return process_bytes
;
1652 // The complete header block has been delivered. We send a zero-length
1653 // OnControlFrameHeaderData() to indicate this.
1654 visitor_
->OnControlFrameHeaderData(current_frame_stream_id_
, NULL
, 0);
1657 if (processed_successfully
) {
1658 CHANGE_STATE(SPDY_CONSUME_PADDING
);
1663 if (!processed_successfully
) {
1667 // Return amount processed.
1668 return process_bytes
;
1671 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
1673 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD
, state_
);
1674 DCHECK_EQ(SETTINGS
, current_frame_type_
);
1675 size_t unprocessed_bytes
= std::min(data_len
, remaining_data_length_
);
1676 size_t processed_bytes
= 0;
1678 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
1680 // Loop over our incoming data.
1681 while (unprocessed_bytes
> 0) {
1682 // Process up to one setting at a time.
1683 size_t processing
= std::min(
1685 static_cast<size_t>(setting_size
- settings_scratch_
.setting_buf_len
));
1687 // Check if we have a complete setting in our input.
1688 if (processing
== setting_size
) {
1689 // Parse the setting directly out of the input without buffering.
1690 if (!ProcessSetting(data
+ processed_bytes
)) {
1691 set_error(SPDY_INVALID_CONTROL_FRAME
);
1692 return processed_bytes
;
1695 // Continue updating settings_scratch_.setting_buf.
1696 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
1697 data
+ processed_bytes
,
1699 settings_scratch_
.setting_buf_len
+= processing
;
1701 // Check if we have a complete setting buffered.
1702 if (settings_scratch_
.setting_buf_len
== setting_size
) {
1703 if (!ProcessSetting(settings_scratch_
.setting_buf
)) {
1704 set_error(SPDY_INVALID_CONTROL_FRAME
);
1705 return processed_bytes
;
1707 // Reset settings_scratch_.setting_buf for our next setting.
1708 settings_scratch_
.setting_buf_len
= 0;
1713 unprocessed_bytes
-= processing
;
1714 processed_bytes
+= processing
;
1717 // Check if we're done handling this SETTINGS frame.
1718 remaining_data_length_
-= processed_bytes
;
1719 if (remaining_data_length_
== 0) {
1720 visitor_
->OnSettingsEnd();
1721 CHANGE_STATE(SPDY_AUTO_RESET
);
1724 return processed_bytes
;
1727 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1728 DCHECK_LT(SPDY3
, protocol_version());
1729 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
1731 const SpdyNameValueBlock
& block
= GetHpackDecoder()->decoded_block();
1732 if (block
.empty()) {
1733 // Special-case this to make tests happy.
1734 ProcessControlFrameHeaderBlock(NULL
, 0, false);
1737 SpdyFrameBuilder
builder(
1738 GetSerializedLength(protocol_version(), &block
),
1741 SerializeNameValueBlockWithoutCompression(&builder
, block
);
1742 scoped_ptr
<SpdyFrame
> frame(builder
.take());
1744 // Preserve padding length, and reset it after the re-entrant call.
1745 size_t remaining_padding
= remaining_padding_payload_length_
;
1747 remaining_padding_payload_length_
= 0;
1748 remaining_data_length_
= frame
->size();
1750 ProcessControlFrameHeaderBlock(frame
->data(), frame
->size(), false);
1752 remaining_padding_payload_length_
= remaining_padding
;
1753 remaining_data_length_
= remaining_padding
;
1756 bool SpdyFramer::ProcessSetting(const char* data
) {
1763 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1764 if (protocol_version() <= SPDY3
) {
1765 const uint32 id_and_flags_wire
= *(reinterpret_cast<const uint32
*>(data
));
1766 SettingsFlagsAndId id_and_flags
=
1767 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire
);
1768 id_field
= id_and_flags
.id();
1769 flags
= id_and_flags
.flags();
1770 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 4)));
1772 id_field
= ntohs(*(reinterpret_cast<const uint16
*>(data
)));
1773 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 2)));
1777 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field
)) {
1778 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_field
;
1779 if (protocol_version() <= SPDY3
) {
1782 // In HTTP2 we ignore unknown settings for extensibility.
1786 id
= SpdyConstants::ParseSettingId(protocol_version(), id_field
);
1788 if (protocol_version() <= SPDY3
) {
1789 // Detect duplicates.
1790 if (id
<= settings_scratch_
.last_setting_id
) {
1791 DLOG(WARNING
) << "Duplicate entry or invalid ordering for id " << id
1792 << " in " << display_protocol_
<< " SETTINGS frame "
1793 << "(last setting id was "
1794 << settings_scratch_
.last_setting_id
<< ").";
1797 settings_scratch_
.last_setting_id
= id
;
1800 uint8 kFlagsMask
= SETTINGS_FLAG_PLEASE_PERSIST
| SETTINGS_FLAG_PERSISTED
;
1801 if ((flags
& ~(kFlagsMask
)) != 0) {
1802 DLOG(WARNING
) << "Unknown SETTINGS flags provided for id " << id
<< ": "
1808 // Validation succeeded. Pass on to visitor.
1809 visitor_
->OnSetting(id
, flags
, value
);
1813 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
1814 size_t original_len
= len
;
1815 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1816 remaining_data_length_
);
1817 remaining_data_length_
-= bytes_read
;
1818 if (remaining_data_length_
== 0) {
1819 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1820 current_frame_buffer_length_
);
1821 reader
.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1823 // Use frame-specific handlers.
1824 switch (current_frame_type_
) {
1827 bool is_ack
= protocol_version() > SPDY3
&&
1828 (current_frame_flags_
& PING_FLAG_ACK
);
1829 bool successful_read
= true;
1830 if (protocol_version() <= SPDY3
) {
1832 successful_read
= reader
.ReadUInt32(&id32
);
1835 successful_read
= reader
.ReadUInt64(&id
);
1837 DCHECK(successful_read
);
1838 DCHECK(reader
.IsDoneReading());
1839 visitor_
->OnPing(id
, is_ack
);
1842 case WINDOW_UPDATE
: {
1843 uint32 delta_window_size
= 0;
1844 bool successful_read
= true;
1845 if (protocol_version() <= SPDY3
) {
1846 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1847 DCHECK(successful_read
);
1849 successful_read
= reader
.ReadUInt32(&delta_window_size
);
1850 DCHECK(successful_read
);
1851 DCHECK(reader
.IsDoneReading());
1852 visitor_
->OnWindowUpdate(current_frame_stream_id_
,
1857 DCHECK_LT(SPDY3
, protocol_version());
1858 DCHECK(reader
.IsDoneReading());
1859 visitor_
->OnBlocked(current_frame_stream_id_
);
1863 DCHECK_LT(SPDY3
, protocol_version());
1864 uint32 parent_stream_id
;
1867 bool successful_read
= true;
1868 successful_read
= reader
.ReadUInt32(&parent_stream_id
);
1869 DCHECK(successful_read
);
1870 // Exclusivity is indicated by a single bit flag.
1871 exclusive
= (parent_stream_id
>> 31) != 0;
1872 // Zero out the highest-order bit to get the parent stream id.
1873 parent_stream_id
&= 0x7fffffff;
1874 successful_read
= reader
.ReadUInt8(&weight
);
1875 DCHECK(successful_read
);
1876 DCHECK(reader
.IsDoneReading());
1877 visitor_
->OnPriority(
1878 current_frame_stream_id_
, parent_stream_id
, weight
, exclusive
);
1883 LOG(FATAL
) << "Unhandled control frame " << current_frame_type_
;
1886 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
1888 return original_len
- len
;
1891 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data
, size_t len
) {
1895 // Clamp to the actual remaining payload.
1896 if (len
> remaining_data_length_
) {
1897 len
= remaining_data_length_
;
1899 size_t original_len
= len
;
1901 // Check if we had already read enough bytes to parse the GOAWAY header.
1902 const size_t header_size
= GetGoAwayMinimumSize();
1903 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1904 bool already_parsed_header
= (unread_header_bytes
== 0);
1905 if (!already_parsed_header
) {
1906 // Buffer the new GOAWAY header bytes we got.
1907 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1909 // Do we have enough to parse the constant size GOAWAY header?
1910 if (current_frame_buffer_length_
== header_size
) {
1911 // Parse out the last good stream id.
1912 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1913 current_frame_buffer_length_
);
1914 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1915 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1916 DCHECK(successful_read
);
1918 // In SPDYv3 and up, frames also specify a status code - parse it out.
1919 SpdyGoAwayStatus status
= GOAWAY_OK
;
1920 if (protocol_version() >= SPDY3
) {
1921 uint32 status_raw
= GOAWAY_OK
;
1922 successful_read
= reader
.ReadUInt32(&status_raw
);
1923 DCHECK(successful_read
);
1924 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1926 status
= SpdyConstants::ParseGoAwayStatus(protocol_version(),
1929 if (protocol_version() > SPDY3
) {
1930 // Treat unrecognized status codes as INTERNAL_ERROR as
1931 // recommended by the HTTP/2 spec.
1932 status
= GOAWAY_INTERNAL_ERROR
;
1936 // Finished parsing the GOAWAY header, call frame handler.
1937 visitor_
->OnGoAway(current_frame_stream_id_
, status
);
1941 // Handle remaining data as opaque.
1942 bool processed_successfully
= true;
1944 processed_successfully
= visitor_
->OnGoAwayFrameData(data
, len
);
1946 remaining_data_length_
-= original_len
;
1947 if (!processed_successfully
) {
1948 set_error(SPDY_GOAWAY_FRAME_CORRUPT
);
1949 } else if (remaining_data_length_
== 0) {
1950 // Signal that there is not more opaque data.
1951 visitor_
->OnGoAwayFrameData(NULL
, 0);
1952 CHANGE_STATE(SPDY_AUTO_RESET
);
1954 return original_len
;
1957 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data
, size_t len
) {
1961 // Clamp to the actual remaining payload.
1962 if (len
> remaining_data_length_
) {
1963 len
= remaining_data_length_
;
1965 size_t original_len
= len
;
1967 // Check if we had already read enough bytes to parse the fixed-length portion
1968 // of the RST_STREAM frame.
1969 const size_t header_size
= GetRstStreamMinimumSize();
1970 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1971 bool already_parsed_header
= (unread_header_bytes
== 0);
1972 if (!already_parsed_header
) {
1973 // Buffer the new RST_STREAM header bytes we got.
1974 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1976 // Do we have enough to parse the constant size RST_STREAM header?
1977 if (current_frame_buffer_length_
== header_size
) {
1978 // Parse out the last good stream id.
1979 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1980 current_frame_buffer_length_
);
1981 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1982 if (protocol_version() <= SPDY3
) {
1983 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1984 DCHECK(successful_read
);
1987 SpdyRstStreamStatus status
= RST_STREAM_INVALID
;
1988 uint32 status_raw
= status
;
1989 bool successful_read
= reader
.ReadUInt32(&status_raw
);
1990 DCHECK(successful_read
);
1991 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1994 SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw
);
1996 if (protocol_version() > SPDY3
) {
1997 // Treat unrecognized status codes as INTERNAL_ERROR as
1998 // recommended by the HTTP/2 spec.
1999 status
= RST_STREAM_INTERNAL_ERROR
;
2002 // Finished parsing the RST_STREAM header, call frame handler.
2003 visitor_
->OnRstStream(current_frame_stream_id_
, status
);
2007 // Handle remaining data as opaque.
2008 bool processed_successfully
= true;
2010 processed_successfully
= visitor_
->OnRstStreamFrameData(data
, len
);
2012 remaining_data_length_
-= original_len
;
2013 if (!processed_successfully
) {
2014 set_error(SPDY_RST_STREAM_FRAME_CORRUPT
);
2015 } else if (remaining_data_length_
== 0) {
2016 // Signal that there is not more opaque data.
2017 visitor_
->OnRstStreamFrameData(NULL
, 0);
2018 CHANGE_STATE(SPDY_AUTO_RESET
);
2020 return original_len
;
2023 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data
, size_t len
) {
2028 // Clamp to the actual remaining payload.
2029 len
= std::min(len
, remaining_data_length_
);
2031 size_t processed_bytes
= 0;
2032 size_t processing
= 0;
2033 size_t bytes_remaining
;
2038 if (altsvc_scratch_
.pid_len
== 0) {
2039 // The size of the frame up to the PID_LEN field.
2040 size_t fixed_len_portion
= GetAltSvcMinimumSize() - 1;
2041 bytes_remaining
= fixed_len_portion
- current_frame_buffer_length_
;
2042 processing
= std::min(len
, bytes_remaining
);
2043 // Buffer the new ALTSVC bytes we got.
2044 UpdateCurrentFrameBuffer(&data
, &len
, processing
);
2046 // Do we have enough to parse the length of the protocol id?
2047 if (current_frame_buffer_length_
== fixed_len_portion
) {
2048 // Parse out the max age, port, and pid_len.
2049 SpdyFrameReader
reader(current_frame_buffer_
.get(),
2050 current_frame_buffer_length_
);
2051 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2052 bool successful_read
= reader
.ReadUInt32(&altsvc_scratch_
.max_age
);
2053 reader
.ReadUInt16(&altsvc_scratch_
.port
);
2054 reader
.Seek(1); // Reserved byte.
2055 successful_read
= successful_read
&&
2056 reader
.ReadUInt8(&altsvc_scratch_
.pid_len
);
2057 DCHECK(successful_read
);
2058 // Sanity check length value.
2059 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
>=
2060 current_frame_length_
) {
2061 set_error(SPDY_INVALID_CONTROL_FRAME
);
2064 altsvc_scratch_
.protocol_id
.reset(
2065 new char[size_t(altsvc_scratch_
.pid_len
)]);
2067 processed_bytes
+= processing
;
2069 } else if (altsvc_scratch_
.pid_buf_len
< altsvc_scratch_
.pid_len
) {
2070 // Buffer protocol id field as in comes in.
2071 buffer
= altsvc_scratch_
.protocol_id
.get();
2072 buffer_len
= &altsvc_scratch_
.pid_buf_len
;
2073 bytes_remaining
= altsvc_scratch_
.pid_len
- altsvc_scratch_
.pid_buf_len
;
2074 } else if (altsvc_scratch_
.host_len
== 0) {
2075 // Parse out the host length.
2077 altsvc_scratch_
.host_len
= *reinterpret_cast<const uint8
*>(data
);
2078 // Sanity check length value.
2079 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
+
2080 altsvc_scratch_
.host_len
> current_frame_length_
) {
2081 set_error(SPDY_INVALID_CONTROL_FRAME
);
2084 altsvc_scratch_
.host
.reset(new char[altsvc_scratch_
.host_len
]);
2085 // Once we have host length, we can also determine the origin length
2086 // by process of elimination.
2087 altsvc_scratch_
.origin_len
= current_frame_length_
-
2088 GetAltSvcMinimumSize() -
2089 altsvc_scratch_
.pid_len
-
2090 altsvc_scratch_
.host_len
;
2091 if (altsvc_scratch_
.origin_len
> 0) {
2092 altsvc_scratch_
.origin
.reset(new char[altsvc_scratch_
.origin_len
]);
2095 processed_bytes
+= processing
;
2098 } else if (altsvc_scratch_
.host_buf_len
< altsvc_scratch_
.host_len
) {
2099 // Buffer host field as it comes in.
2100 // TODO(mlavan): check formatting for host and origin
2101 buffer
= altsvc_scratch_
.host
.get();
2102 buffer_len
= &altsvc_scratch_
.host_buf_len
;
2103 bytes_remaining
= altsvc_scratch_
.host_len
- altsvc_scratch_
.host_buf_len
;
2105 // Buffer (optional) origin field as it comes in.
2106 if (altsvc_scratch_
.origin_len
<= 0) {
2107 set_error(SPDY_INVALID_CONTROL_FRAME
);
2110 buffer
= altsvc_scratch_
.origin
.get();
2111 buffer_len
= &altsvc_scratch_
.origin_buf_len
;
2112 bytes_remaining
= remaining_data_length_
-
2114 altsvc_scratch_
.origin_buf_len
;
2115 if (len
> bytes_remaining
) {
2116 // This is our last field; there shouldn't be any more bytes.
2117 set_error(SPDY_INVALID_CONTROL_FRAME
);
2122 // Copy data bytes into the appropriate field.
2123 processing
= std::min(len
, bytes_remaining
);
2124 memcpy(buffer
+ *buffer_len
,
2127 *buffer_len
+= processing
;
2129 processed_bytes
+= processing
;
2133 remaining_data_length_
-= processed_bytes
;
2134 if (remaining_data_length_
== 0) {
2135 visitor_
->OnAltSvc(current_frame_stream_id_
,
2136 altsvc_scratch_
.max_age
,
2137 altsvc_scratch_
.port
,
2138 StringPiece(altsvc_scratch_
.protocol_id
.get(),
2139 altsvc_scratch_
.pid_len
),
2140 StringPiece(altsvc_scratch_
.host
.get(),
2141 altsvc_scratch_
.host_len
),
2142 StringPiece(altsvc_scratch_
.origin
.get(),
2143 altsvc_scratch_
.origin_len
));
2144 CHANGE_STATE(SPDY_AUTO_RESET
);
2147 return processed_bytes
;
2150 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data
, size_t len
) {
2151 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH
, state_
);
2152 DCHECK_EQ(0u, remaining_padding_payload_length_
);
2153 DCHECK_EQ(DATA
, current_frame_type_
);
2155 size_t original_len
= len
;
2156 if (current_frame_flags_
& DATA_FLAG_PADDED
) {
2158 if (remaining_data_length_
< kPadLengthFieldSize
) {
2159 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2163 remaining_padding_payload_length_
= *reinterpret_cast<const uint8
*>(data
);
2166 --remaining_data_length_
;
2168 // We don't have the data available for parsing the pad length field. Keep
2174 if (remaining_padding_payload_length_
> remaining_data_length_
) {
2175 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2178 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
2179 return original_len
- len
;
2182 size_t SpdyFramer::ProcessFramePadding(const char* data
, size_t len
) {
2183 DCHECK_EQ(SPDY_CONSUME_PADDING
, state_
);
2185 size_t original_len
= len
;
2186 if (remaining_padding_payload_length_
> 0) {
2187 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
2188 size_t amount_to_discard
= std::min(remaining_padding_payload_length_
, len
);
2189 if (current_frame_type_
== DATA
&& amount_to_discard
> 0) {
2190 // The visitor needs to know about padding so it can send window updates.
2191 // Communicate the padding to the visitor through a NULL data pointer,
2192 // with a nonzero size.
2193 visitor_
->OnStreamFrameData(
2194 current_frame_stream_id_
, NULL
, amount_to_discard
, false);
2196 data
+= amount_to_discard
;
2197 len
-= amount_to_discard
;
2198 remaining_padding_payload_length_
-= amount_to_discard
;
2199 remaining_data_length_
-= amount_to_discard
;
2202 if (remaining_data_length_
== 0) {
2203 // If the FIN flag is set, or this ends a header block which set FIN,
2204 // inform the visitor of EOF via a 0-length data frame.
2205 if (expect_continuation_
== 0 &&
2206 ((current_frame_flags_
& CONTROL_FLAG_FIN
) != 0 ||
2207 end_stream_when_done_
)) {
2208 end_stream_when_done_
= false;
2209 visitor_
->OnStreamFrameData(current_frame_stream_id_
, NULL
, 0, true);
2211 CHANGE_STATE(SPDY_AUTO_RESET
);
2213 return original_len
- len
;
2216 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
2217 size_t original_len
= len
;
2218 if (remaining_data_length_
- remaining_padding_payload_length_
> 0) {
2219 size_t amount_to_forward
= std::min(
2220 remaining_data_length_
- remaining_padding_payload_length_
, len
);
2221 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
2222 // Only inform the visitor if there is data.
2223 if (amount_to_forward
) {
2224 visitor_
->OnStreamFrameData(
2225 current_frame_stream_id_
, data
, amount_to_forward
, false);
2228 data
+= amount_to_forward
;
2229 len
-= amount_to_forward
;
2230 remaining_data_length_
-= amount_to_forward
;
2233 if (remaining_data_length_
== remaining_padding_payload_length_
) {
2234 CHANGE_STATE(SPDY_CONSUME_PADDING
);
2236 return original_len
- len
;
2239 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2241 size_t original_len
= len
;
2242 if (remaining_data_length_
> 0) {
2243 size_t amount_to_ignore
= std::min(remaining_data_length_
, len
);
2244 len
-= amount_to_ignore
;
2245 remaining_data_length_
-= amount_to_ignore
;
2248 if (remaining_data_length_
== 0) {
2249 CHANGE_STATE(SPDY_AUTO_RESET
);
2251 return original_len
- len
;
2254 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
2255 size_t header_length
,
2256 SpdyHeaderBlock
* block
) const {
2257 SpdyFrameReader
reader(header_data
, header_length
);
2259 // Read number of headers.
2261 if (protocol_version() <= SPDY2
) {
2263 if (!reader
.ReadUInt16(&temp
)) {
2264 DVLOG(1) << "Unable to read number of headers.";
2269 if (!reader
.ReadUInt32(&num_headers
)) {
2270 DVLOG(1) << "Unable to read number of headers.";
2275 // Read each header.
2276 for (uint32 index
= 0; index
< num_headers
; ++index
) {
2277 base::StringPiece temp
;
2279 // Read header name.
2280 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2281 : !reader
.ReadStringPiece32(&temp
)) {
2282 DVLOG(1) << "Unable to read header name (" << index
+ 1 << " of "
2283 << num_headers
<< ").";
2286 std::string name
= temp
.as_string();
2288 // Read header value.
2289 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2290 : !reader
.ReadStringPiece32(&temp
)) {
2291 DVLOG(1) << "Unable to read header value (" << index
+ 1 << " of "
2292 << num_headers
<< ").";
2295 std::string value
= temp
.as_string();
2297 // Ensure no duplicates.
2298 if (block
->find(name
) != block
->end()) {
2299 DVLOG(1) << "Duplicate header '" << name
<< "' (" << index
+ 1 << " of "
2300 << num_headers
<< ").";
2305 (*block
)[name
] = value
;
2307 return reader
.GetBytesConsumed();
2310 SpdySerializedFrame
* SpdyFramer::SerializeData(
2311 const SpdyDataIR
& data_ir
) const {
2312 uint8 flags
= DATA_FLAG_NONE
;
2313 if (data_ir
.fin()) {
2314 flags
= DATA_FLAG_FIN
;
2317 if (protocol_version() > SPDY3
) {
2318 int num_padding_fields
= 0;
2319 if (data_ir
.padded()) {
2320 flags
|= DATA_FLAG_PADDED
;
2321 ++num_padding_fields
;
2324 const size_t size_with_padding
= num_padding_fields
+
2325 data_ir
.data().length() + data_ir
.padding_payload_len() +
2326 GetDataFrameMinimumSize();
2327 SpdyFrameBuilder
builder(size_with_padding
, protocol_version());
2328 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2329 if (data_ir
.padded()) {
2330 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2332 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2333 if (data_ir
.padding_payload_len() > 0) {
2334 string
padding(data_ir
.padding_payload_len(), 0);
2335 builder
.WriteBytes(padding
.data(), padding
.length());
2337 DCHECK_EQ(size_with_padding
, builder
.length());
2338 return builder
.take();
2340 const size_t size
= GetDataFrameMinimumSize() + data_ir
.data().length();
2341 SpdyFrameBuilder
builder(size
, protocol_version());
2342 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2343 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2344 DCHECK_EQ(size
, builder
.length());
2345 return builder
.take();
2349 SpdySerializedFrame
* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2350 const SpdyDataIR
& data_ir
) const {
2351 uint8 flags
= DATA_FLAG_NONE
;
2352 if (data_ir
.fin()) {
2353 flags
= DATA_FLAG_FIN
;
2356 size_t frame_size
= GetDataFrameMinimumSize();
2357 size_t num_padding_fields
= 0;
2358 if (protocol_version() > SPDY3
) {
2359 if (data_ir
.padded()) {
2360 flags
|= DATA_FLAG_PADDED
;
2361 ++num_padding_fields
;
2363 frame_size
+= num_padding_fields
;
2366 SpdyFrameBuilder
builder(frame_size
, protocol_version());
2367 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2368 if (protocol_version() > SPDY3
) {
2369 if (data_ir
.padded()) {
2370 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2372 builder
.OverwriteLength(*this, num_padding_fields
+
2373 data_ir
.data().length() + data_ir
.padding_payload_len());
2375 builder
.OverwriteLength(*this, data_ir
.data().length());
2377 DCHECK_EQ(frame_size
, builder
.length());
2378 return builder
.take();
2381 SpdySerializedFrame
* SpdyFramer::SerializeSynStream(
2382 const SpdySynStreamIR
& syn_stream
) {
2383 DCHECK_GE(SPDY3
, protocol_version());
2385 if (syn_stream
.fin()) {
2386 flags
|= CONTROL_FLAG_FIN
;
2388 if (syn_stream
.unidirectional()) {
2389 // TODO(hkhalil): invalid for HTTP2.
2390 flags
|= CONTROL_FLAG_UNIDIRECTIONAL
;
2393 // Sanitize priority.
2394 uint8 priority
= syn_stream
.priority();
2395 if (priority
> GetLowestPriority()) {
2396 DLOG(DFATAL
) << "Priority out-of-bounds.";
2397 priority
= GetLowestPriority();
2400 // The size of this frame, including variable-length name-value block.
2401 size_t size
= GetSynStreamMinimumSize() +
2402 GetSerializedLength(syn_stream
.name_value_block());
2404 SpdyFrameBuilder
builder(size
, protocol_version());
2405 builder
.WriteControlFrameHeader(*this, SYN_STREAM
, flags
);
2406 builder
.WriteUInt32(syn_stream
.stream_id());
2407 builder
.WriteUInt32(syn_stream
.associated_to_stream_id());
2408 builder
.WriteUInt8(priority
<< ((protocol_version() <= SPDY2
) ? 6 : 5));
2409 builder
.WriteUInt8(0); // Unused byte where credential slot used to be.
2410 DCHECK_EQ(GetSynStreamMinimumSize(), builder
.length());
2411 SerializeNameValueBlock(&builder
, syn_stream
);
2413 if (debug_visitor_
) {
2414 const size_t payload_len
=
2415 GetSerializedLength(protocol_version(),
2416 &(syn_stream
.name_value_block()));
2417 debug_visitor_
->OnSendCompressedFrame(syn_stream
.stream_id(),
2423 return builder
.take();
2426 SpdySerializedFrame
* SpdyFramer::SerializeSynReply(
2427 const SpdySynReplyIR
& syn_reply
) {
2428 DCHECK_GE(SPDY3
, protocol_version());
2430 if (syn_reply
.fin()) {
2431 flags
|= CONTROL_FLAG_FIN
;
2434 // The size of this frame, including variable-length name-value block.
2435 const size_t size
= GetSynReplyMinimumSize() +
2436 GetSerializedLength(syn_reply
.name_value_block());
2438 SpdyFrameBuilder
builder(size
, protocol_version());
2439 if (protocol_version() <= SPDY3
) {
2440 builder
.WriteControlFrameHeader(*this, SYN_REPLY
, flags
);
2441 builder
.WriteUInt32(syn_reply
.stream_id());
2443 builder
.BeginNewFrame(*this,
2446 syn_reply
.stream_id());
2448 if (protocol_version() < SPDY3
) {
2449 builder
.WriteUInt16(0); // Unused.
2451 DCHECK_EQ(GetSynReplyMinimumSize(), builder
.length());
2452 SerializeNameValueBlock(&builder
, syn_reply
);
2454 if (debug_visitor_
) {
2455 const size_t payload_len
= GetSerializedLength(
2456 protocol_version(), &(syn_reply
.name_value_block()));
2457 debug_visitor_
->OnSendCompressedFrame(syn_reply
.stream_id(),
2463 return builder
.take();
2466 SpdySerializedFrame
* SpdyFramer::SerializeRstStream(
2467 const SpdyRstStreamIR
& rst_stream
) const {
2468 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2469 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2470 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2471 // commented but left in place to simplify future patching.
2472 // Compute the output buffer size, taking opaque data into account.
2473 size_t expected_length
= GetRstStreamMinimumSize();
2474 if (protocol_version() > SPDY3
) {
2475 expected_length
+= rst_stream
.description().size();
2477 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2479 // Serialize the RST_STREAM frame.
2480 if (protocol_version() <= SPDY3
) {
2481 builder
.WriteControlFrameHeader(*this, RST_STREAM
, 0);
2482 builder
.WriteUInt32(rst_stream
.stream_id());
2484 builder
.BeginNewFrame(*this, RST_STREAM
, 0, rst_stream
.stream_id());
2487 builder
.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
2488 protocol_version(), rst_stream
.status()));
2490 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2491 if (protocol_version() > SPDY3
&& rst_stream
.description().size() > 0) {
2492 builder
.WriteBytes(rst_stream
.description().data(),
2493 rst_stream
.description().size());
2496 DCHECK_EQ(expected_length
, builder
.length());
2497 return builder
.take();
2500 SpdySerializedFrame
* SpdyFramer::SerializeSettings(
2501 const SpdySettingsIR
& settings
) const {
2504 if (protocol_version() <= SPDY3
) {
2505 if (settings
.clear_settings()) {
2506 flags
|= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
2509 if (settings
.is_ack()) {
2510 flags
|= SETTINGS_FLAG_ACK
;
2513 const SpdySettingsIR::ValueMap
* values
= &(settings
.values());
2515 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
2516 // Size, in bytes, of this SETTINGS frame.
2517 const size_t size
= GetSettingsMinimumSize() +
2518 (values
->size() * setting_size
);
2519 SpdyFrameBuilder
builder(size
, protocol_version());
2520 if (protocol_version() <= SPDY3
) {
2521 builder
.WriteControlFrameHeader(*this, SETTINGS
, flags
);
2523 builder
.BeginNewFrame(*this, SETTINGS
, flags
, 0);
2526 // If this is an ACK, payload should be empty.
2527 if (protocol_version() > SPDY3
&& settings
.is_ack()) {
2528 return builder
.take();
2531 if (protocol_version() <= SPDY3
) {
2532 builder
.WriteUInt32(values
->size());
2534 DCHECK_EQ(GetSettingsMinimumSize(), builder
.length());
2535 for (SpdySettingsIR::ValueMap::const_iterator it
= values
->begin();
2536 it
!= values
->end();
2539 SpdyConstants::SerializeSettingId(protocol_version(), it
->first
);
2540 DCHECK_GE(setting_id
, 0);
2541 if (protocol_version() <= SPDY3
) {
2542 uint8 setting_flags
= 0;
2543 if (it
->second
.persist_value
) {
2544 setting_flags
|= SETTINGS_FLAG_PLEASE_PERSIST
;
2546 if (it
->second
.persisted
) {
2547 setting_flags
|= SETTINGS_FLAG_PERSISTED
;
2549 SettingsFlagsAndId
flags_and_id(setting_flags
, setting_id
);
2550 uint32 id_and_flags_wire
= flags_and_id
.GetWireFormat(protocol_version());
2551 builder
.WriteBytes(&id_and_flags_wire
, 4);
2553 builder
.WriteUInt16(static_cast<uint16
>(setting_id
));
2555 builder
.WriteUInt32(it
->second
.value
);
2557 DCHECK_EQ(size
, builder
.length());
2558 return builder
.take();
2561 SpdySerializedFrame
* SpdyFramer::SerializePing(const SpdyPingIR
& ping
) const {
2562 SpdyFrameBuilder
builder(GetPingSize(), protocol_version());
2563 if (protocol_version() <= SPDY3
) {
2564 builder
.WriteControlFrameHeader(*this, PING
, kNoFlags
);
2565 builder
.WriteUInt32(static_cast<uint32
>(ping
.id()));
2568 if (ping
.is_ack()) {
2569 flags
|= PING_FLAG_ACK
;
2571 builder
.BeginNewFrame(*this, PING
, flags
, 0);
2572 builder
.WriteUInt64(ping
.id());
2574 DCHECK_EQ(GetPingSize(), builder
.length());
2575 return builder
.take();
2578 SpdySerializedFrame
* SpdyFramer::SerializeGoAway(
2579 const SpdyGoAwayIR
& goaway
) const {
2581 // Compute the output buffer size, take opaque data into account.
2582 size_t expected_length
= GetGoAwayMinimumSize();
2583 if (protocol_version() > SPDY3
) {
2584 expected_length
+= goaway
.description().size();
2586 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2588 // Serialize the GOAWAY frame.
2589 if (protocol_version() <= SPDY3
) {
2590 builder
.WriteControlFrameHeader(*this, GOAWAY
, kNoFlags
);
2592 builder
.BeginNewFrame(*this, GOAWAY
, 0, 0);
2595 // GOAWAY frames specify the last good stream id for all SPDY versions.
2596 builder
.WriteUInt32(goaway
.last_good_stream_id());
2598 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2599 if (protocol_version() >= SPDY3
) {
2600 // TODO(jgraettinger): Merge back to server-side.
2601 builder
.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2605 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2606 if ((protocol_version() > SPDY3
) && (goaway
.description().size() > 0)) {
2607 builder
.WriteBytes(goaway
.description().data(),
2608 goaway
.description().size());
2611 DCHECK_EQ(expected_length
, builder
.length());
2612 return builder
.take();
2615 SpdySerializedFrame
* SpdyFramer::SerializeHeaders(
2616 const SpdyHeadersIR
& headers
) {
2618 if (headers
.fin()) {
2619 flags
|= CONTROL_FLAG_FIN
;
2621 if (protocol_version() > SPDY3
) {
2622 // This will get overwritten if we overflow into a CONTINUATION frame.
2623 flags
|= HEADERS_FLAG_END_HEADERS
;
2624 if (headers
.has_priority()) {
2625 flags
|= HEADERS_FLAG_PRIORITY
;
2627 if (headers
.padded()) {
2628 flags
|= HEADERS_FLAG_PADDED
;
2632 // The size of this frame, including padding (if there is any)
2633 // and variable-length name-value block.
2634 size_t size
= GetHeadersMinimumSize();
2636 if (protocol_version() > SPDY3
&& headers
.padded()) {
2637 size
+= kPadLengthFieldSize
;
2638 size
+= headers
.padding_payload_len();
2641 SpdyPriority priority
= static_cast<SpdyPriority
>(headers
.priority());
2642 if (headers
.has_priority()) {
2643 if (headers
.priority() > GetLowestPriority()) {
2644 DLOG(DFATAL
) << "Priority out-of-bounds.";
2645 priority
= GetLowestPriority();
2650 string hpack_encoding
;
2651 if (protocol_version() > SPDY3
) {
2652 if (enable_compression_
) {
2653 GetHpackEncoder()->EncodeHeaderSet(
2654 headers
.name_value_block(), &hpack_encoding
);
2656 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2657 headers
.name_value_block(), &hpack_encoding
);
2659 size
+= hpack_encoding
.size();
2660 if (size
> kMaxControlFrameSize
) {
2661 size
+= GetNumberRequiredContinuationFrames(size
) *
2662 GetContinuationMinimumSize();
2663 flags
&= ~HEADERS_FLAG_END_HEADERS
;
2666 size
+= GetSerializedLength(headers
.name_value_block());
2669 SpdyFrameBuilder
builder(size
, protocol_version());
2670 if (protocol_version() <= SPDY3
) {
2671 builder
.WriteControlFrameHeader(*this, HEADERS
, flags
);
2672 builder
.WriteUInt32(headers
.stream_id());
2674 builder
.BeginNewFrame(*this,
2677 headers
.stream_id());
2679 if (protocol_version() <= SPDY2
) {
2680 builder
.WriteUInt16(0); // Unused.
2682 DCHECK_EQ(GetHeadersMinimumSize(), builder
.length());
2684 if (protocol_version() > SPDY3
) {
2685 int padding_payload_len
= 0;
2686 if (headers
.padded()) {
2687 builder
.WriteUInt8(headers
.padding_payload_len());
2688 padding_payload_len
= headers
.padding_payload_len();
2690 if (headers
.has_priority()) {
2691 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2692 builder
.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2693 builder
.WriteUInt8(MapPriorityToWeight(priority
));
2695 WritePayloadWithContinuation(&builder
,
2697 headers
.stream_id(),
2699 padding_payload_len
);
2701 SerializeNameValueBlock(&builder
, headers
);
2704 if (debug_visitor_
) {
2705 // SPDY4 uses HPACK for header compression. However, continue to
2706 // use GetSerializedLength() for an apples-to-apples comparision of
2707 // compression performance between HPACK and SPDY w/ deflate.
2708 const size_t payload_len
=
2709 GetSerializedLength(protocol_version(),
2710 &(headers
.name_value_block()));
2711 debug_visitor_
->OnSendCompressedFrame(headers
.stream_id(),
2717 return builder
.take();
2720 SpdySerializedFrame
* SpdyFramer::SerializeWindowUpdate(
2721 const SpdyWindowUpdateIR
& window_update
) const {
2722 SpdyFrameBuilder
builder(GetWindowUpdateSize(), protocol_version());
2723 if (protocol_version() <= SPDY3
) {
2724 builder
.WriteControlFrameHeader(*this, WINDOW_UPDATE
, kNoFlags
);
2725 builder
.WriteUInt32(window_update
.stream_id());
2727 builder
.BeginNewFrame(*this,
2730 window_update
.stream_id());
2732 builder
.WriteUInt32(window_update
.delta());
2733 DCHECK_EQ(GetWindowUpdateSize(), builder
.length());
2734 return builder
.take();
2737 SpdyFrame
* SpdyFramer::SerializeBlocked(const SpdyBlockedIR
& blocked
) const {
2738 DCHECK_LT(SPDY3
, protocol_version());
2739 SpdyFrameBuilder
builder(GetBlockedSize(), protocol_version());
2740 builder
.BeginNewFrame(*this, BLOCKED
, kNoFlags
, blocked
.stream_id());
2741 return builder
.take();
2744 SpdyFrame
* SpdyFramer::SerializePushPromise(
2745 const SpdyPushPromiseIR
& push_promise
) {
2746 DCHECK_LT(SPDY3
, protocol_version());
2748 // This will get overwritten if we overflow into a CONTINUATION frame.
2749 flags
|= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2750 // The size of this frame, including variable-length name-value block.
2751 size_t size
= GetPushPromiseMinimumSize();
2753 if (push_promise
.padded()) {
2754 flags
|= PUSH_PROMISE_FLAG_PADDED
;
2755 size
+= kPadLengthFieldSize
;
2756 size
+= push_promise
.padding_payload_len();
2759 string hpack_encoding
;
2760 if (enable_compression_
) {
2761 GetHpackEncoder()->EncodeHeaderSet(
2762 push_promise
.name_value_block(), &hpack_encoding
);
2764 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2765 push_promise
.name_value_block(), &hpack_encoding
);
2767 size
+= hpack_encoding
.size();
2768 if (size
> kMaxControlFrameSize
) {
2769 size
+= GetNumberRequiredContinuationFrames(size
) *
2770 GetContinuationMinimumSize();
2771 flags
&= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2774 SpdyFrameBuilder
builder(size
, protocol_version());
2775 builder
.BeginNewFrame(*this,
2778 push_promise
.stream_id());
2779 int padding_payload_len
= 0;
2780 if (push_promise
.padded()) {
2781 builder
.WriteUInt8(push_promise
.padding_payload_len());
2782 builder
.WriteUInt32(push_promise
.promised_stream_id());
2783 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize
,
2786 padding_payload_len
= push_promise
.padding_payload_len();
2788 builder
.WriteUInt32(push_promise
.promised_stream_id());
2789 DCHECK_EQ(GetPushPromiseMinimumSize(), builder
.length());
2792 WritePayloadWithContinuation(&builder
,
2794 push_promise
.stream_id(),
2796 padding_payload_len
);
2798 if (debug_visitor_
) {
2799 // SPDY4 uses HPACK for header compression. However, continue to
2800 // use GetSerializedLength() for an apples-to-apples comparision of
2801 // compression performance between HPACK and SPDY w/ deflate.
2802 const size_t payload_len
=
2803 GetSerializedLength(protocol_version(),
2804 &(push_promise
.name_value_block()));
2805 debug_visitor_
->OnSendCompressedFrame(push_promise
.stream_id(),
2811 return builder
.take();
2814 // TODO(jgraettinger): This implementation is incorrect. The continuation
2815 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2816 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2817 SpdyFrame
* SpdyFramer::SerializeContinuation(
2818 const SpdyContinuationIR
& continuation
) {
2819 CHECK_LT(SPDY3
, protocol_version());
2821 if (continuation
.end_headers()) {
2822 flags
|= HEADERS_FLAG_END_HEADERS
;
2825 // The size of this frame, including variable-length name-value block.
2826 size_t size
= GetContinuationMinimumSize();
2827 string hpack_encoding
;
2828 if (enable_compression_
) {
2829 GetHpackEncoder()->EncodeHeaderSet(
2830 continuation
.name_value_block(), &hpack_encoding
);
2832 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2833 continuation
.name_value_block(), &hpack_encoding
);
2835 size
+= hpack_encoding
.size();
2837 SpdyFrameBuilder
builder(size
, protocol_version());
2838 builder
.BeginNewFrame(*this, CONTINUATION
, flags
,
2839 continuation
.stream_id());
2840 DCHECK_EQ(GetContinuationMinimumSize(), builder
.length());
2842 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2843 return builder
.take();
2846 SpdyFrame
* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR
& altsvc
) {
2847 DCHECK_LT(SPDY3
, protocol_version());
2848 size_t size
= GetAltSvcMinimumSize();
2849 size
+= altsvc
.protocol_id().length();
2850 size
+= altsvc
.host().length();
2851 size
+= altsvc
.origin().length();
2853 SpdyFrameBuilder
builder(size
, protocol_version());
2854 builder
.BeginNewFrame(*this, ALTSVC
, kNoFlags
, altsvc
.stream_id());
2856 // TODO(bnc): http://crbug.com/438263
2857 // Update the binary format here to the new text-based payload format.
2858 builder
.WriteUInt32(altsvc
.max_age());
2859 builder
.WriteUInt16(altsvc
.port());
2860 builder
.WriteUInt8(0); // Reserved.
2861 builder
.WriteUInt8(static_cast<uint8
>(altsvc
.protocol_id().length()));
2862 builder
.WriteBytes(altsvc
.protocol_id().data(),
2863 altsvc
.protocol_id().length());
2864 builder
.WriteUInt8(static_cast<uint8
>(altsvc
.host().length()));
2865 builder
.WriteBytes(altsvc
.host().data(), altsvc
.host().length());
2866 builder
.WriteBytes(altsvc
.origin().data(), altsvc
.origin().length());
2867 DCHECK_LT(GetAltSvcMinimumSize(), builder
.length());
2868 return builder
.take();
2871 SpdyFrame
* SpdyFramer::SerializePriority(const SpdyPriorityIR
& priority
) const {
2872 DCHECK_LT(SPDY3
, protocol_version());
2873 size_t size
= GetPrioritySize();
2875 SpdyFrameBuilder
builder(size
, protocol_version());
2876 builder
.BeginNewFrame(*this, PRIORITY
, kNoFlags
, priority
.stream_id());
2878 // Make sure the highest-order bit in the parent stream id is zeroed out.
2879 uint32 parent_stream_id
= priority
.parent_stream_id() & 0x7fffffff;
2880 uint32 exclusive
= priority
.exclusive() ? 0x80000000 : 0;
2881 // Set the one-bit exclusivity flag.
2882 uint32 flag_and_parent_id
= parent_stream_id
| exclusive
;
2883 builder
.WriteUInt32(flag_and_parent_id
);
2884 builder
.WriteUInt8(priority
.weight());
2885 DCHECK_EQ(GetPrioritySize(), builder
.length());
2886 return builder
.take();
2891 class FrameSerializationVisitor
: public SpdyFrameVisitor
{
2893 explicit FrameSerializationVisitor(SpdyFramer
* framer
) : framer_(framer
) {}
2894 ~FrameSerializationVisitor() override
{}
2896 SpdySerializedFrame
* ReleaseSerializedFrame() { return frame_
.release(); }
2898 void VisitData(const SpdyDataIR
& data
) override
{
2899 frame_
.reset(framer_
->SerializeData(data
));
2901 void VisitSynStream(const SpdySynStreamIR
& syn_stream
) override
{
2902 frame_
.reset(framer_
->SerializeSynStream(syn_stream
));
2904 void VisitSynReply(const SpdySynReplyIR
& syn_reply
) override
{
2905 frame_
.reset(framer_
->SerializeSynReply(syn_reply
));
2907 void VisitRstStream(const SpdyRstStreamIR
& rst_stream
) override
{
2908 frame_
.reset(framer_
->SerializeRstStream(rst_stream
));
2910 void VisitSettings(const SpdySettingsIR
& settings
) override
{
2911 frame_
.reset(framer_
->SerializeSettings(settings
));
2913 void VisitPing(const SpdyPingIR
& ping
) override
{
2914 frame_
.reset(framer_
->SerializePing(ping
));
2916 void VisitGoAway(const SpdyGoAwayIR
& goaway
) override
{
2917 frame_
.reset(framer_
->SerializeGoAway(goaway
));
2919 void VisitHeaders(const SpdyHeadersIR
& headers
) override
{
2920 frame_
.reset(framer_
->SerializeHeaders(headers
));
2922 void VisitWindowUpdate(const SpdyWindowUpdateIR
& window_update
) override
{
2923 frame_
.reset(framer_
->SerializeWindowUpdate(window_update
));
2925 void VisitBlocked(const SpdyBlockedIR
& blocked
) override
{
2926 frame_
.reset(framer_
->SerializeBlocked(blocked
));
2928 void VisitPushPromise(const SpdyPushPromiseIR
& push_promise
) override
{
2929 frame_
.reset(framer_
->SerializePushPromise(push_promise
));
2931 void VisitContinuation(const SpdyContinuationIR
& continuation
) override
{
2932 frame_
.reset(framer_
->SerializeContinuation(continuation
));
2934 void VisitAltSvc(const SpdyAltSvcIR
& altsvc
) override
{
2935 frame_
.reset(framer_
->SerializeAltSvc(altsvc
));
2937 void VisitPriority(const SpdyPriorityIR
& priority
) override
{
2938 frame_
.reset(framer_
->SerializePriority(priority
));
2942 SpdyFramer
* framer_
;
2943 scoped_ptr
<SpdySerializedFrame
> frame_
;
2948 SpdySerializedFrame
* SpdyFramer::SerializeFrame(const SpdyFrameIR
& frame
) {
2949 FrameSerializationVisitor
visitor(this);
2950 frame
.Visit(&visitor
);
2951 return visitor
.ReleaseSerializedFrame();
2954 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock
& headers
) {
2955 CHECK_GE(SPDY3
, protocol_version());
2956 const size_t uncompressed_length
=
2957 GetSerializedLength(protocol_version(), &headers
);
2958 if (!enable_compression_
) {
2959 return uncompressed_length
;
2961 z_stream
* compressor
= GetHeaderCompressor();
2962 // Since we'll be performing lots of flushes when compressing the data,
2963 // zlib's lower bounds may be insufficient.
2964 return 2 * deflateBound(compressor
, uncompressed_length
);
2967 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size
) {
2968 DCHECK_GT(protocol_version(), SPDY3
);
2969 DCHECK_GT(size
, kMaxControlFrameSize
);
2970 size_t overflow
= size
- kMaxControlFrameSize
;
2971 return overflow
/ (kMaxControlFrameSize
- GetContinuationMinimumSize()) + 1;
2974 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder
* builder
,
2975 const string
& hpack_encoding
,
2976 SpdyStreamId stream_id
,
2978 int padding_payload_len
) {
2981 if (type
== HEADERS
) {
2982 end_flag
= HEADERS_FLAG_END_HEADERS
;
2983 } else if (type
== PUSH_PROMISE
) {
2984 end_flag
= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2986 DLOG(FATAL
) << "CONTINUATION frames cannot be used with frame type "
2987 << FrameTypeToString(type
);
2990 // Write all the padding payload and as much of the data payload as possible
2991 // into the initial frame.
2992 size_t bytes_remaining
= 0;
2994 hpack_encoding
.size() -
2995 std::min(hpack_encoding
.size(),
2996 kMaxControlFrameSize
- builder
->length() - padding_payload_len
);
2997 builder
->WriteBytes(&hpack_encoding
[0],
2998 hpack_encoding
.size() - bytes_remaining
);
2999 if (padding_payload_len
> 0) {
3000 string padding
= string(padding_payload_len
, 0);
3001 builder
->WriteBytes(padding
.data(), padding
.length());
3003 if (bytes_remaining
> 0) {
3004 builder
->OverwriteLength(
3005 *this, kMaxControlFrameSize
- GetControlFrameHeaderSize());
3008 // Tack on CONTINUATION frames for the overflow.
3009 while (bytes_remaining
> 0) {
3010 size_t bytes_to_write
= std::min(
3011 bytes_remaining
, kMaxControlFrameSize
- GetContinuationMinimumSize());
3012 // Write CONTINUATION frame prefix.
3013 if (bytes_remaining
== bytes_to_write
) {
3016 builder
->BeginNewFrame(*this, CONTINUATION
, flags
, stream_id
);
3017 // Write payload fragment.
3018 builder
->WriteBytes(
3019 &hpack_encoding
[hpack_encoding
.size() - bytes_remaining
],
3021 bytes_remaining
-= bytes_to_write
;
3025 // The following compression setting are based on Brian Olson's analysis. See
3026 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
3027 // for more details.
3028 #if defined(USE_SYSTEM_ZLIB)
3029 // System zlib is not expected to have workaround for http://crbug.com/139744,
3030 // so disable compression in that case.
3031 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
3032 static const int kCompressorLevel
= 0;
3033 #else // !defined(USE_SYSTEM_ZLIB)
3034 static const int kCompressorLevel
= 9;
3035 #endif // !defined(USE_SYSTEM_ZLIB)
3036 static const int kCompressorWindowSizeInBits
= 11;
3037 static const int kCompressorMemLevel
= 1;
3039 z_stream
* SpdyFramer::GetHeaderCompressor() {
3040 if (header_compressor_
.get())
3041 return header_compressor_
.get(); // Already initialized.
3043 header_compressor_
.reset(new z_stream
);
3044 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
3046 int success
= deflateInit2(header_compressor_
.get(),
3049 kCompressorWindowSizeInBits
,
3050 kCompressorMemLevel
,
3051 Z_DEFAULT_STRATEGY
);
3052 if (success
== Z_OK
) {
3053 const char* dictionary
= (protocol_version() <= SPDY2
) ?
3054 kV2Dictionary
: kV3Dictionary
;
3055 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3056 kV2DictionarySize
: kV3DictionarySize
;
3057 success
= deflateSetDictionary(header_compressor_
.get(),
3058 reinterpret_cast<const Bytef
*>(dictionary
),
3061 if (success
!= Z_OK
) {
3062 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
3063 header_compressor_
.reset(NULL
);
3066 return header_compressor_
.get();
3069 z_stream
* SpdyFramer::GetHeaderDecompressor() {
3070 if (header_decompressor_
.get())
3071 return header_decompressor_
.get(); // Already initialized.
3073 header_decompressor_
.reset(new z_stream
);
3074 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
3076 int success
= inflateInit(header_decompressor_
.get());
3077 if (success
!= Z_OK
) {
3078 LOG(WARNING
) << "inflateInit failure: " << success
;
3079 header_decompressor_
.reset(NULL
);
3082 return header_decompressor_
.get();
3085 HpackEncoder
* SpdyFramer::GetHpackEncoder() {
3086 DCHECK_LT(SPDY3
, protocol_version());
3087 if (hpack_encoder_
.get() == nullptr) {
3088 hpack_encoder_
.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3090 return hpack_encoder_
.get();
3093 HpackDecoder
* SpdyFramer::GetHpackDecoder() {
3094 DCHECK_LT(SPDY3
, protocol_version());
3095 if (hpack_decoder_
.get() == nullptr) {
3096 hpack_decoder_
.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3098 return hpack_decoder_
.get();
3101 uint8
SpdyFramer::MapPriorityToWeight(SpdyPriority priority
) {
3102 const float kSteps
= 255.9f
/ 7.f
;
3103 return static_cast<uint8
>(kSteps
* (7.f
- priority
));
3106 SpdyPriority
SpdyFramer::MapWeightToPriority(uint8 weight
) {
3107 const float kSteps
= 255.9f
/ 7.f
;
3108 return static_cast<SpdyPriority
>(7.f
- weight
/ kSteps
);
3111 // Incrementally decompress the control frame's header block, feeding the
3112 // result to the visitor in chunks. Continue this until the visitor
3113 // indicates that it cannot process any more data, or (more commonly) we
3114 // run out of data to deliver.
3115 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3116 SpdyStreamId stream_id
,
3119 // Get a decompressor or set error.
3120 z_stream
* decomp
= GetHeaderDecompressor();
3121 if (decomp
== NULL
) {
3122 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
3123 set_error(SPDY_DECOMPRESS_FAILURE
);
3127 bool processed_successfully
= true;
3128 char buffer
[kHeaderDataChunkMaxSize
];
3130 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
3131 decomp
->avail_in
= len
;
3132 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3133 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3134 // reached this method successfully, stream_id should be nonzero.
3135 DCHECK_LT(0u, stream_id
);
3136 while (decomp
->avail_in
> 0 && processed_successfully
) {
3137 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
3138 decomp
->avail_out
= arraysize(buffer
);
3140 int rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3141 if (rv
== Z_NEED_DICT
) {
3142 const char* dictionary
= (protocol_version() <= SPDY2
) ? kV2Dictionary
3144 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3145 kV2DictionarySize
: kV3DictionarySize
;
3146 const DictionaryIds
& ids
= g_dictionary_ids
.Get();
3147 const uLong dictionary_id
= (protocol_version() <= SPDY2
) ?
3148 ids
.v2_dictionary_id
: ids
.v3_dictionary_id
;
3149 // Need to try again with the right dictionary.
3150 if (decomp
->adler
== dictionary_id
) {
3151 rv
= inflateSetDictionary(decomp
,
3152 reinterpret_cast<const Bytef
*>(dictionary
),
3155 rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3159 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3160 // without producing any output. The input is consumed and
3161 // buffered internally by zlib so we can detect this condition by
3162 // checking if avail_in is 0 after the call to inflate.
3163 bool input_exhausted
= ((rv
== Z_BUF_ERROR
) && (decomp
->avail_in
== 0));
3164 if ((rv
== Z_OK
) || input_exhausted
) {
3165 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
3166 if (decompressed_len
> 0) {
3167 processed_successfully
= visitor_
->OnControlFrameHeaderData(
3168 stream_id
, buffer
, decompressed_len
);
3170 if (!processed_successfully
) {
3171 // Assume that the problem was the header block was too large for the
3173 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3176 DLOG(WARNING
) << "inflate failure: " << rv
<< " " << len
;
3177 set_error(SPDY_DECOMPRESS_FAILURE
);
3178 processed_successfully
= false;
3181 return processed_successfully
;
3184 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3185 SpdyStreamId stream_id
, const char* data
, size_t len
) {
3186 bool read_successfully
= true;
3187 while (read_successfully
&& len
> 0) {
3188 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
3189 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
3191 data
+= bytes_to_deliver
;
3192 len
-= bytes_to_deliver
;
3193 if (!read_successfully
) {
3194 // Assume that the problem was the header block was too large for the
3196 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3199 return read_successfully
;
3202 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3203 SpdyFrameBuilder
* builder
,
3204 const SpdyNameValueBlock
& name_value_block
) const {
3205 // Serialize number of headers.
3206 if (protocol_version() <= SPDY2
) {
3207 builder
->WriteUInt16(static_cast<uint16
>(name_value_block
.size()));
3209 builder
->WriteUInt32(name_value_block
.size());
3212 // Serialize each header.
3213 for (SpdyHeaderBlock::const_iterator it
= name_value_block
.begin();
3214 it
!= name_value_block
.end();
3216 if (protocol_version() <= SPDY2
) {
3217 builder
->WriteString(it
->first
);
3218 builder
->WriteString(it
->second
);
3220 builder
->WriteStringPiece32(it
->first
);
3221 builder
->WriteStringPiece32(it
->second
);
3226 void SpdyFramer::SerializeNameValueBlock(
3227 SpdyFrameBuilder
* builder
,
3228 const SpdyFrameWithNameValueBlockIR
& frame
) {
3229 CHECK_GE(SPDY3
, protocol_version());
3230 if (!enable_compression_
) {
3231 return SerializeNameValueBlockWithoutCompression(builder
,
3232 frame
.name_value_block());
3235 // First build an uncompressed version to be fed into the compressor.
3236 const size_t uncompressed_len
= GetSerializedLength(
3237 protocol_version(), &(frame
.name_value_block()));
3238 SpdyFrameBuilder
uncompressed_builder(uncompressed_len
, protocol_version());
3239 SerializeNameValueBlockWithoutCompression(&uncompressed_builder
,
3240 frame
.name_value_block());
3241 scoped_ptr
<SpdyFrame
> uncompressed_payload(uncompressed_builder
.take());
3243 z_stream
* compressor
= GetHeaderCompressor();
3245 LOG(DFATAL
) << "Could not obtain compressor.";
3248 // Create an output frame.
3249 // Since we'll be performing lots of flushes when compressing the data,
3250 // zlib's lower bounds may be insufficient.
3252 // TODO(akalin): Avoid the duplicate calculation with
3253 // GetSerializedLength(const SpdyHeaderBlock&).
3254 const int compressed_max_size
=
3255 2 * deflateBound(compressor
, uncompressed_len
);
3257 // TODO(phajdan.jr): Clean up after we no longer need
3258 // to workaround http://crbug.com/139744.
3259 #if defined(USE_SYSTEM_ZLIB)
3260 compressor
->next_in
= reinterpret_cast<Bytef
*>(uncompressed_payload
->data());
3261 compressor
->avail_in
= uncompressed_len
;
3262 #endif // defined(USE_SYSTEM_ZLIB)
3263 compressor
->next_out
= reinterpret_cast<Bytef
*>(
3264 builder
->GetWritableBuffer(compressed_max_size
));
3265 compressor
->avail_out
= compressed_max_size
;
3267 // TODO(phajdan.jr): Clean up after we no longer need
3268 // to workaround http://crbug.com/139744.
3269 #if defined(USE_SYSTEM_ZLIB)
3270 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
3271 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
3272 // This shouldn't happen, right?
3273 LOG(WARNING
) << "deflate failure: " << rv
;
3274 // TODO(akalin): Upstream this return.
3278 WriteHeaderBlockToZ(&frame
.name_value_block(), compressor
);
3279 #endif // defined(USE_SYSTEM_ZLIB)
3281 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
3282 builder
->Seek(compressed_size
);
3283 builder
->RewriteLength(*this);