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"
14 #include "base/lazy_instance.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram_macros.h"
17 #include "base/third_party/valgrind/memcheck.h"
18 #include "net/spdy/hpack/hpack_constants.h"
19 #include "net/spdy/spdy_frame_builder.h"
20 #include "net/spdy/spdy_frame_reader.h"
21 #include "net/spdy/spdy_bitmasks.h"
22 #include "third_party/zlib/zlib.h"
24 using base::StringPiece
;
32 // Compute the id of our dictionary so that we know we're using the
33 // right one when asked for it.
34 uLong
CalculateDictionaryId(const char* dictionary
,
35 const size_t dictionary_size
) {
36 uLong initial_value
= adler32(0L, Z_NULL
, 0);
37 return adler32(initial_value
,
38 reinterpret_cast<const Bytef
*>(dictionary
),
42 // Check to see if the name and value of a cookie are both empty.
43 bool IsCookieEmpty(const base::StringPiece
& cookie
) {
44 if (cookie
.size() == 0) {
47 size_t pos
= cookie
.find('=');
48 if (pos
== base::StringPiece::npos
) {
51 // Ignore leading whitespaces of cookie value.
52 size_t value_start
= pos
+ 1;
53 for (; value_start
< cookie
.size(); value_start
++) {
54 if (!(cookie
[value_start
] == ' ' || cookie
[value_start
] == '\t')) {
58 return (pos
== 0) && ((cookie
.size() - value_start
) == 0);
61 // Pack parent stream ID and exclusive flag into the format used by HTTP/2
62 // headers and priority frames.
63 uint32
PackStreamDependencyValues(bool exclusive
,
64 SpdyStreamId parent_stream_id
) {
65 // Make sure the highest-order bit in the parent stream id is zeroed out.
66 uint32 parent
= parent_stream_id
& 0x7fffffff;
67 // Set the one-bit exclusivity flag.
68 uint32 e_bit
= exclusive
? 0x80000000 : 0;
69 return parent
| e_bit
;
72 // Unpack parent stream ID and exclusive flag from the format used by HTTP/2
73 // headers and priority frames.
74 void UnpackStreamDependencyValues(uint32 packed
,
76 SpdyStreamId
* parent_stream_id
) {
77 *exclusive
= (packed
>> 31) != 0;
78 // Zero out the highest-order bit to get the parent stream id.
79 *parent_stream_id
= packed
& 0x7fffffff;
82 struct DictionaryIds
{
84 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary
, kV2DictionarySize
)),
85 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary
, kV3DictionarySize
))
87 const uLong v2_dictionary_id
;
88 const uLong v3_dictionary_id
;
91 // Adler ID for the SPDY header compressor dictionaries. Note that they are
92 // initialized lazily to avoid static initializers.
93 base::LazyInstance
<DictionaryIds
>::Leaky g_dictionary_ids
;
95 // Used to indicate no flags in a SPDY flags field.
96 const uint8 kNoFlags
= 0;
98 // Wire sizes of priority payloads.
99 const size_t kPriorityDependencyPayloadSize
= 4;
100 const size_t kPriorityWeightPayloadSize
= 1;
102 // Wire size of pad length field.
103 const size_t kPadLengthFieldSize
= 1;
107 const SpdyStreamId
SpdyFramer::kInvalidStream
= static_cast<SpdyStreamId
>(-1);
108 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
109 // We fragment sent control frames at smaller payload boundaries.
110 const size_t SpdyFramer::kMaxControlFrameSize
= 1024;
111 // The size of the control frame buffer. Must be >= the minimum size of the
112 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
113 // calculation details.
114 const size_t SpdyFramer::kControlFrameBufferSize
= 19;
116 #ifdef DEBUG_SPDY_STATE_CHANGES
117 #define CHANGE_STATE(newstate) \
119 DVLOG(1) << "Changing state from: " \
120 << StateToString(state_) \
121 << " to " << StateToString(newstate) << "\n"; \
122 DCHECK(state_ != SPDY_ERROR); \
123 DCHECK_EQ(previous_state_, state_); \
124 previous_state_ = state_; \
128 #define CHANGE_STATE(newstate) \
130 DCHECK(state_ != SPDY_ERROR); \
131 DCHECK_EQ(previous_state_, state_); \
132 previous_state_ = state_; \
137 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(
138 SpdyMajorVersion version
, uint32 wire
) {
139 if (version
< SPDY3
) {
140 ConvertFlagsAndIdForSpdy2(&wire
);
142 return SettingsFlagsAndId(ntohl(wire
) >> 24, ntohl(wire
) & 0x00ffffff);
145 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags
, uint32 id
)
146 : flags_(flags
), id_(id
& 0x00ffffff) {
147 LOG_IF(DFATAL
, id
> (1u << 24)) << "SPDY setting ID too large: " << id
;
150 uint32
SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version
)
152 uint32 wire
= htonl(id_
& 0x00ffffff) | htonl(flags_
<< 24);
153 if (version
< SPDY3
) {
154 ConvertFlagsAndIdForSpdy2(&wire
);
159 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
160 // This method is used to preserve buggy behavior and works on both
161 // little-endian and big-endian hosts.
162 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
163 // as well as vice versa).
164 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32
* val
) {
165 uint8
* wire_array
= reinterpret_cast<uint8
*>(val
);
166 std::swap(wire_array
[0], wire_array
[3]);
167 std::swap(wire_array
[1], wire_array
[2]);
170 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
171 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
173 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data
,
178 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
179 const char* rst_stream_data
,
184 SpdyFramer::SpdyFramer(SpdyMajorVersion version
)
185 : current_frame_buffer_(new char[kControlFrameBufferSize
]),
186 expect_continuation_(0),
188 debug_visitor_(NULL
),
189 display_protocol_("SPDY"),
190 protocol_version_(version
),
191 enable_compression_(true),
192 syn_frame_processed_(false),
193 probable_http_response_(false),
194 end_stream_when_done_(false),
195 header_table_size_bound_(4096) {
196 DCHECK_GE(protocol_version_
, SPDY_MIN_VERSION
);
197 DCHECK_LE(protocol_version_
, SPDY_MAX_VERSION
);
198 DCHECK_LE(kMaxControlFrameSize
,
199 SpdyConstants::GetFrameMaximumSize(protocol_version_
) +
200 SpdyConstants::GetControlFrameHeaderSize(protocol_version_
));
204 SpdyFramer::~SpdyFramer() {
205 if (header_compressor_
.get()) {
206 deflateEnd(header_compressor_
.get());
208 if (header_decompressor_
.get()) {
209 inflateEnd(header_decompressor_
.get());
213 void SpdyFramer::Reset() {
214 state_
= SPDY_READY_FOR_FRAME
;
215 previous_state_
= SPDY_READY_FOR_FRAME
;
216 error_code_
= SPDY_NO_ERROR
;
217 remaining_data_length_
= 0;
218 remaining_control_header_
= 0;
219 current_frame_buffer_length_
= 0;
220 current_frame_type_
= DATA
;
221 current_frame_flags_
= 0;
222 current_frame_length_
= 0;
223 current_frame_stream_id_
= kInvalidStream
;
224 settings_scratch_
.Reset();
225 altsvc_scratch_
.Reset();
226 remaining_padding_payload_length_
= 0;
229 size_t SpdyFramer::GetDataFrameMinimumSize() const {
230 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
233 // Size, in bytes, of the control frame header.
234 size_t SpdyFramer::GetControlFrameHeaderSize() const {
235 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
238 size_t SpdyFramer::GetSynStreamMinimumSize() const {
239 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
241 if (protocol_version() <= SPDY3
) {
243 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
244 // + 1 (unused, was credential slot)
245 return GetControlFrameHeaderSize() + 10;
247 return GetControlFrameHeaderSize() +
248 kPriorityDependencyPayloadSize
+
249 kPriorityWeightPayloadSize
;
253 size_t SpdyFramer::GetSynReplyMinimumSize() const {
254 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
256 size_t size
= GetControlFrameHeaderSize();
257 if (protocol_version() <= SPDY3
) {
259 // control frame header + 4 (stream IDs)
263 // In SPDY 2, there were 2 unused bytes before payload.
264 if (protocol_version() < SPDY3
) {
271 size_t SpdyFramer::GetRstStreamMinimumSize() const {
272 // Size, in bytes, of a RST_STREAM frame.
273 if (protocol_version() <= SPDY3
) {
275 // control frame header + 4 (stream id) + 4 (status code)
276 return GetControlFrameHeaderSize() + 8;
279 // frame prefix + 4 (status code)
280 return GetControlFrameHeaderSize() + 4;
284 size_t SpdyFramer::GetSettingsMinimumSize() const {
285 // Size, in bytes, of a SETTINGS frame not including the IDs and values
286 // from the variable-length value block. Calculated as:
287 // control frame header + 4 (number of ID/value pairs)
288 if (protocol_version() <= SPDY3
) {
289 return GetControlFrameHeaderSize() + 4;
291 return GetControlFrameHeaderSize();
295 size_t SpdyFramer::GetPingSize() const {
296 // Size, in bytes, of this PING frame.
297 if (protocol_version() <= SPDY3
) {
299 // control frame header + 4 (id)
300 return GetControlFrameHeaderSize() + 4;
303 // control frame header + 8 (id)
304 return GetControlFrameHeaderSize() + 8;
308 size_t SpdyFramer::GetGoAwayMinimumSize() const {
309 // Size, in bytes, of this GOAWAY frame. Calculated as:
310 // 1. Control frame header size
311 size_t size
= GetControlFrameHeaderSize();
313 // 2. Last good stream id (4 bytes)
316 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
317 if (protocol_version() >= SPDY3
) {
324 size_t SpdyFramer::GetHeadersMinimumSize() const {
325 // Size, in bytes, of a HEADERS frame not including the variable-length
327 size_t size
= GetControlFrameHeaderSize();
328 if (protocol_version() <= SPDY3
) {
330 // control frame header + 4 (stream IDs)
334 // In SPDY 2, there were 2 unused bytes before payload.
335 if (protocol_version() <= SPDY2
) {
342 size_t SpdyFramer::GetWindowUpdateSize() const {
343 // Size, in bytes, of a WINDOW_UPDATE frame.
344 if (protocol_version() <= SPDY3
) {
346 // control frame header + 4 (stream id) + 4 (delta)
347 return GetControlFrameHeaderSize() + 8;
350 // frame prefix + 4 (delta)
351 return GetControlFrameHeaderSize() + 4;
355 size_t SpdyFramer::GetBlockedSize() const {
356 DCHECK_LT(SPDY3
, protocol_version());
357 // Size, in bytes, of a BLOCKED frame.
358 // The BLOCKED frame has no payload beyond the control frame header.
359 return GetControlFrameHeaderSize();
362 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
363 DCHECK_LT(SPDY3
, protocol_version());
364 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
365 // Calculated as frame prefix + 4 (promised stream id).
366 return GetControlFrameHeaderSize() + 4;
369 size_t SpdyFramer::GetContinuationMinimumSize() const {
370 // Size, in bytes, of a CONTINUATION frame not including the variable-length
371 // headers fragments.
372 return GetControlFrameHeaderSize();
375 size_t SpdyFramer::GetAltSvcMinimumSize() const {
376 // Size, in bytes, of an ALTSVC frame not including the Field-Value and
377 // (optional) Origin fields, both of which can vary in length. Note that this
378 // gives a lower bound on the frame size rather than a true minimum; the
379 // actual frame should always be larger than this.
380 // Calculated as frame prefix + 2 (origin_len).
381 return GetControlFrameHeaderSize() + 2;
384 size_t SpdyFramer::GetPrioritySize() const {
385 // Size, in bytes, of a PRIORITY frame.
386 return GetControlFrameHeaderSize() +
387 kPriorityDependencyPayloadSize
+
388 kPriorityWeightPayloadSize
;
391 size_t SpdyFramer::GetFrameMinimumSize() const {
392 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
395 size_t SpdyFramer::GetFrameMaximumSize() const {
396 return SpdyConstants::GetFrameMaximumSize(protocol_version());
399 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
400 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
403 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type
) const {
404 return SpdyConstants::GetPrefixLength(type
, protocol_version());
407 const char* SpdyFramer::StateToString(int state
) {
411 case SPDY_FRAME_COMPLETE
:
412 return "FRAME_COMPLETE";
413 case SPDY_READY_FOR_FRAME
:
414 return "READY_FOR_FRAME";
415 case SPDY_READING_COMMON_HEADER
:
416 return "READING_COMMON_HEADER";
417 case SPDY_CONTROL_FRAME_PAYLOAD
:
418 return "CONTROL_FRAME_PAYLOAD";
419 case SPDY_READ_DATA_FRAME_PADDING_LENGTH
:
420 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
421 case SPDY_CONSUME_PADDING
:
422 return "SPDY_CONSUME_PADDING";
423 case SPDY_IGNORE_REMAINING_PAYLOAD
:
424 return "IGNORE_REMAINING_PAYLOAD";
425 case SPDY_FORWARD_STREAM_FRAME
:
426 return "FORWARD_STREAM_FRAME";
427 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
428 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
429 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
430 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
431 case SPDY_GOAWAY_FRAME_PAYLOAD
:
432 return "SPDY_GOAWAY_FRAME_PAYLOAD";
433 case SPDY_RST_STREAM_FRAME_PAYLOAD
:
434 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
435 case SPDY_SETTINGS_FRAME_PAYLOAD
:
436 return "SPDY_SETTINGS_FRAME_PAYLOAD";
437 case SPDY_ALTSVC_FRAME_PAYLOAD
:
438 return "SPDY_ALTSVC_FRAME_PAYLOAD";
440 return "UNKNOWN_STATE";
443 void SpdyFramer::set_error(SpdyError error
) {
446 // These values will usually get reset once we come to the end
447 // of a header block, but if we run into an error that
448 // might not happen, so reset them here.
449 expect_continuation_
= 0;
450 end_stream_when_done_
= false;
452 CHANGE_STATE(SPDY_ERROR
);
453 visitor_
->OnError(this);
456 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
457 switch (error_code
) {
460 case SPDY_INVALID_CONTROL_FRAME
:
461 return "INVALID_CONTROL_FRAME";
462 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
463 return "CONTROL_PAYLOAD_TOO_LARGE";
464 case SPDY_ZLIB_INIT_FAILURE
:
465 return "ZLIB_INIT_FAILURE";
466 case SPDY_UNSUPPORTED_VERSION
:
467 return "UNSUPPORTED_VERSION";
468 case SPDY_DECOMPRESS_FAILURE
:
469 return "DECOMPRESS_FAILURE";
470 case SPDY_COMPRESS_FAILURE
:
471 return "COMPRESS_FAILURE";
472 case SPDY_INVALID_DATA_FRAME_FLAGS
:
473 return "SPDY_INVALID_DATA_FRAME_FLAGS";
474 case SPDY_INVALID_CONTROL_FRAME_FLAGS
:
475 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
476 case SPDY_UNEXPECTED_FRAME
:
477 return "UNEXPECTED_FRAME";
479 return "UNKNOWN_ERROR";
482 const char* SpdyFramer::StatusCodeToString(int status_code
) {
483 switch (status_code
) {
484 case RST_STREAM_INVALID
:
486 case RST_STREAM_PROTOCOL_ERROR
:
487 return "PROTOCOL_ERROR";
488 case RST_STREAM_INVALID_STREAM
:
489 return "INVALID_STREAM";
490 case RST_STREAM_REFUSED_STREAM
:
491 return "REFUSED_STREAM";
492 case RST_STREAM_UNSUPPORTED_VERSION
:
493 return "UNSUPPORTED_VERSION";
494 case RST_STREAM_CANCEL
:
496 case RST_STREAM_INTERNAL_ERROR
:
497 return "INTERNAL_ERROR";
498 case RST_STREAM_FLOW_CONTROL_ERROR
:
499 return "FLOW_CONTROL_ERROR";
500 case RST_STREAM_STREAM_IN_USE
:
501 return "STREAM_IN_USE";
502 case RST_STREAM_STREAM_ALREADY_CLOSED
:
503 return "STREAM_ALREADY_CLOSED";
504 case RST_STREAM_INVALID_CREDENTIALS
:
505 return "INVALID_CREDENTIALS";
506 case RST_STREAM_FRAME_TOO_LARGE
:
507 return "FRAME_TOO_LARGE";
508 case RST_STREAM_CONNECT_ERROR
:
509 return "CONNECT_ERROR";
510 case RST_STREAM_ENHANCE_YOUR_CALM
:
511 return "ENHANCE_YOUR_CALM";
512 case RST_STREAM_INADEQUATE_SECURITY
:
513 return "INADEQUATE_SECURITY";
514 case RST_STREAM_HTTP_1_1_REQUIRED
:
515 return "HTTP_1_1_REQUIRED";
517 return "UNKNOWN_STATUS";
520 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type
) {
539 return "WINDOW_UPDATE";
543 return "PUSH_PROMISE";
545 return "CONTINUATION";
553 return "UNKNOWN_CONTROL_TYPE";
556 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
560 const size_t original_len
= len
;
562 previous_state_
= state_
;
567 case SPDY_FRAME_COMPLETE
:
568 // Should not enter in this state.
569 DCHECK_LT(len
, original_len
);
571 if (len
> 0 && !process_single_input_frame_
) {
572 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
576 case SPDY_READY_FOR_FRAME
:
578 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
582 case SPDY_READING_COMMON_HEADER
: {
583 size_t bytes_read
= ProcessCommonHeader(data
, len
);
589 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
590 // Control frames that contain header blocks
591 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
592 // take a different path through the state machine - they
594 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
595 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
597 // SETTINGS frames take a slightly modified route:
598 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
599 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
601 // All other control frames will use the alternate route directly to
602 // SPDY_CONTROL_FRAME_PAYLOAD
603 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
609 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
610 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
616 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
617 int bytes_read
= ProcessControlFrameHeaderBlock(
618 data
, len
, protocol_version() > SPDY3
);
624 case SPDY_RST_STREAM_FRAME_PAYLOAD
: {
625 size_t bytes_read
= ProcessRstStreamFramePayload(data
, len
);
631 case SPDY_GOAWAY_FRAME_PAYLOAD
: {
632 size_t bytes_read
= ProcessGoAwayFramePayload(data
, len
);
638 case SPDY_ALTSVC_FRAME_PAYLOAD
: {
639 size_t bytes_read
= ProcessAltSvcFramePayload(data
, len
);
645 case SPDY_CONTROL_FRAME_PAYLOAD
: {
646 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
652 case SPDY_READ_DATA_FRAME_PADDING_LENGTH
: {
653 size_t bytes_read
= ProcessDataFramePaddingLength(data
, len
);
659 case SPDY_CONSUME_PADDING
: {
660 size_t bytes_read
= ProcessFramePadding(data
, len
);
666 case SPDY_IGNORE_REMAINING_PAYLOAD
: {
667 size_t bytes_read
= ProcessIgnoredControlFramePayload(/*data,*/ len
);
673 case SPDY_FORWARD_STREAM_FRAME
: {
674 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
681 LOG(DFATAL
) << "Invalid value for " << display_protocol_
682 << " framer state: " << state_
;
683 // This ensures that we don't infinite-loop if state_ gets an
684 // invalid value somehow, such as due to a SpdyFramer getting deleted
685 // from a callback it calls.
688 } while (state_
!= previous_state_
);
690 DCHECK(len
== 0 || state_
== SPDY_ERROR
|| process_single_input_frame_
);
691 if (current_frame_buffer_length_
== 0 && remaining_data_length_
== 0 &&
692 remaining_control_header_
== 0) {
693 DCHECK(state_
== SPDY_READY_FOR_FRAME
|| state_
== SPDY_ERROR
)
694 << "State: " << StateToString(state_
);
697 return original_len
- len
;
700 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
701 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
703 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
705 size_t original_len
= len
;
707 // Update current frame buffer as needed.
708 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
709 size_t bytes_desired
=
710 GetControlFrameHeaderSize() - current_frame_buffer_length_
;
711 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
714 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
715 // Not enough information to do anything meaningful.
716 return original_len
- len
;
719 SpdyFrameReader
reader(current_frame_buffer_
.get(),
720 current_frame_buffer_length_
);
721 bool is_control_frame
= false;
723 int control_frame_type_field
=
724 SpdyConstants::DataFrameType(protocol_version());
725 // ProcessControlFrameHeader() will set current_frame_type_ to the
726 // correct value if this is a valid control frame.
727 current_frame_type_
= DATA
;
728 if (protocol_version() <= SPDY3
) {
730 bool successful_read
= reader
.ReadUInt16(&version
);
731 DCHECK(successful_read
);
732 is_control_frame
= (version
& kControlFlagMask
) != 0;
733 version
&= ~kControlFlagMask
; // Only valid for control frames.
734 if (is_control_frame
) {
735 // We check version before we check validity: version can never be
736 // 'invalid', it can only be unsupported.
737 if (version
< SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION
) ||
738 version
> SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION
) ||
739 SpdyConstants::ParseMajorVersion(version
) != protocol_version()) {
740 // Version does not match the version the framer was initialized with.
741 DVLOG(1) << "Unsupported SPDY version "
743 << " (expected " << protocol_version() << ")";
744 set_error(SPDY_UNSUPPORTED_VERSION
);
747 // We check control_frame_type_field's validity in
748 // ProcessControlFrameHeader().
749 uint16 control_frame_type_field_uint16
;
750 successful_read
= reader
.ReadUInt16(&control_frame_type_field_uint16
);
751 control_frame_type_field
= control_frame_type_field_uint16
;
754 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
756 DCHECK(successful_read
);
758 successful_read
= reader
.ReadUInt8(¤t_frame_flags_
);
759 DCHECK(successful_read
);
761 uint32 length_field
= 0;
762 successful_read
= reader
.ReadUInt24(&length_field
);
763 DCHECK(successful_read
);
764 remaining_data_length_
= length_field
;
765 current_frame_length_
= remaining_data_length_
+ reader
.GetBytesConsumed();
767 uint32 length_field
= 0;
768 bool successful_read
= reader
.ReadUInt24(&length_field
);
769 DCHECK(successful_read
);
771 uint8 control_frame_type_field_uint8
;
772 successful_read
= reader
.ReadUInt8(&control_frame_type_field_uint8
);
773 DCHECK(successful_read
);
774 // We check control_frame_type_field's validity in
775 // ProcessControlFrameHeader().
776 control_frame_type_field
= control_frame_type_field_uint8
;
777 is_control_frame
= control_frame_type_field
!=
778 SpdyConstants::SerializeFrameType(protocol_version(), DATA
);
780 if (is_control_frame
) {
781 current_frame_length_
= length_field
+ GetControlFrameHeaderSize();
783 current_frame_length_
= length_field
+ GetDataFrameMinimumSize();
786 successful_read
= reader
.ReadUInt8(¤t_frame_flags_
);
787 DCHECK(successful_read
);
789 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
790 DCHECK(successful_read
);
792 remaining_data_length_
= current_frame_length_
- reader
.GetBytesConsumed();
794 // Before we accept a DATA frame, we need to make sure we're not in the
795 // middle of processing a header block.
796 const bool is_continuation_frame
= (control_frame_type_field
==
797 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION
));
798 if ((expect_continuation_
!= 0) != is_continuation_frame
) {
799 if (expect_continuation_
!= 0) {
800 DLOG(ERROR
) << "The framer was expecting to receive a CONTINUATION "
801 << "frame, but instead received frame type "
802 << control_frame_type_field
;
804 DLOG(ERROR
) << "The framer received an unexpected CONTINUATION frame.";
806 set_error(SPDY_UNEXPECTED_FRAME
);
807 return original_len
- len
;
810 DCHECK_EQ(is_control_frame
? GetControlFrameHeaderSize()
811 : GetDataFrameMinimumSize(),
812 reader
.GetBytesConsumed());
813 DCHECK_EQ(current_frame_length_
,
814 remaining_data_length_
+ reader
.GetBytesConsumed());
816 // This is just a sanity check for help debugging early frame errors.
817 if (remaining_data_length_
> 1000000u) {
818 // The strncmp for 5 is safe because we only hit this point if we
819 // have kMinCommonHeader (8) bytes
820 if (!syn_frame_processed_
&&
821 strncmp(current_frame_buffer_
.get(), "HTTP/", 5) == 0) {
822 LOG(WARNING
) << "Unexpected HTTP response to " << display_protocol_
824 probable_http_response_
= true;
826 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
827 << " session is likely corrupt.";
831 // if we're here, then we have the common header all received.
832 if (!is_control_frame
) {
833 if (protocol_version() > SPDY3
) {
834 // Catch bogus tests sending oversized DATA frames.
835 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_
)
836 << "DATA frame too large for SPDY >= 4.";
839 uint8 valid_data_flags
= 0;
840 if (protocol_version() > SPDY3
) {
842 DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
| DATA_FLAG_PADDED
;
844 valid_data_flags
= DATA_FLAG_FIN
;
847 if (current_frame_flags_
& ~valid_data_flags
) {
848 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
850 visitor_
->OnDataFrameHeader(current_frame_stream_id_
,
851 remaining_data_length_
,
852 current_frame_flags_
& DATA_FLAG_FIN
);
853 if (remaining_data_length_
> 0) {
854 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH
);
857 if (current_frame_flags_
& DATA_FLAG_FIN
) {
858 visitor_
->OnStreamFrameData(
859 current_frame_stream_id_
, NULL
, 0, true);
861 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
865 ProcessControlFrameHeader(control_frame_type_field
);
868 return original_len
- len
;
871 void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field
) {
872 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
873 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_
);
875 // TODO(mlavan): Either remove credential frames from the code entirely,
876 // or add them to parsing + serialization methods for SPDY3.
877 // Early detection of deprecated frames that we ignore.
878 if (protocol_version() <= SPDY3
) {
879 if (control_frame_type_field
== CREDENTIAL
) {
880 current_frame_type_
= CREDENTIAL
;
881 DCHECK_EQ(SPDY3
, protocol_version());
882 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
883 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
888 if (!SpdyConstants::IsValidFrameType(protocol_version(),
889 control_frame_type_field
)) {
890 if (protocol_version() <= SPDY3
) {
891 DLOG(WARNING
) << "Invalid control frame type " << control_frame_type_field
892 << " (protocol version: " << protocol_version() << ")";
893 set_error(SPDY_INVALID_CONTROL_FRAME
);
896 // In HTTP2 we ignore unknown frame types for extensibility, as long as
897 // the rest of the control frame header is valid.
898 // We rely on the visitor to check validity of current_frame_stream_id_.
899 bool valid_stream
= visitor_
->OnUnknownFrame(current_frame_stream_id_
,
900 control_frame_type_field
);
902 DVLOG(1) << "Ignoring unknown frame type.";
903 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
905 // Report an invalid frame error and close the stream if the
906 // stream_id is not valid.
907 DLOG(WARNING
) << "Unknown control frame type "
908 << control_frame_type_field
909 << " received on invalid stream "
910 << current_frame_stream_id_
;
911 set_error(SPDY_INVALID_CONTROL_FRAME
);
917 current_frame_type_
= SpdyConstants::ParseFrameType(protocol_version(),
918 control_frame_type_field
);
920 // Do some sanity checking on the control frame sizes and flags.
921 switch (current_frame_type_
) {
923 if (current_frame_length_
< GetSynStreamMinimumSize()) {
924 set_error(SPDY_INVALID_CONTROL_FRAME
);
925 } else if (current_frame_flags_
&
926 ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
927 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
931 if (current_frame_length_
< GetSynReplyMinimumSize()) {
932 set_error(SPDY_INVALID_CONTROL_FRAME
);
933 } else if (current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
934 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
938 // For SPDY versions < 4, the header has a fixed length.
939 // For SPDY version 4 and up, the RST_STREAM frame may include optional
940 // opaque data, so we only have a lower limit on the frame size.
941 if ((current_frame_length_
!= GetRstStreamMinimumSize() &&
942 protocol_version() <= SPDY3
) ||
943 (current_frame_length_
< GetRstStreamMinimumSize() &&
944 protocol_version() > SPDY3
)) {
945 set_error(SPDY_INVALID_CONTROL_FRAME
);
946 } else if (current_frame_flags_
!= 0) {
947 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
952 // Make sure that we have an integral number of 8-byte key/value pairs,
953 // plus a 4-byte length field in SPDY3 and below.
954 size_t values_prefix_size
= (protocol_version() <= SPDY3
? 4 : 0);
955 // Size of each key/value pair in bytes.
956 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
957 if (current_frame_length_
< GetSettingsMinimumSize() ||
958 (current_frame_length_
- GetControlFrameHeaderSize())
959 % setting_size
!= values_prefix_size
) {
960 DLOG(WARNING
) << "Invalid length for SETTINGS frame: "
961 << current_frame_length_
;
962 set_error(SPDY_INVALID_CONTROL_FRAME
);
963 } else if (protocol_version() <= SPDY3
&&
964 current_frame_flags_
&
965 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
966 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
967 } else if (protocol_version() > SPDY3
&&
968 current_frame_flags_
& ~SETTINGS_FLAG_ACK
) {
969 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
970 } else if (protocol_version() > SPDY3
&&
971 current_frame_flags_
& SETTINGS_FLAG_ACK
&&
972 current_frame_length_
> GetSettingsMinimumSize()) {
973 set_error(SPDY_INVALID_CONTROL_FRAME
);
978 if (current_frame_length_
!= GetPingSize()) {
979 set_error(SPDY_INVALID_CONTROL_FRAME
);
980 } else if ((protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) ||
981 (current_frame_flags_
& ~PING_FLAG_ACK
)) {
982 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
987 // For SPDY version < 4, there are only mandatory fields and the header
988 // has a fixed length. For SPDY version >= 4, optional opaque data may
989 // be appended to the GOAWAY frame, thus there is only a minimal length
991 if ((current_frame_length_
!= GetGoAwayMinimumSize() &&
992 protocol_version() <= SPDY3
) ||
993 (current_frame_length_
< GetGoAwayMinimumSize() &&
994 protocol_version() > SPDY3
)) {
995 set_error(SPDY_INVALID_CONTROL_FRAME
);
996 } else if (current_frame_flags_
!= 0) {
997 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1003 size_t min_size
= GetHeadersMinimumSize();
1004 if (protocol_version() > SPDY3
&&
1005 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
)) {
1008 if (current_frame_length_
< min_size
) {
1009 // TODO(mlavan): check here for HEADERS with no payload?
1010 // (not allowed in HTTP2)
1011 set_error(SPDY_INVALID_CONTROL_FRAME
);
1012 } else if (protocol_version() <= SPDY3
&&
1013 current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
1014 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1015 } else if (protocol_version() > SPDY3
&&
1016 current_frame_flags_
&
1017 ~(CONTROL_FLAG_FIN
| HEADERS_FLAG_PRIORITY
|
1018 HEADERS_FLAG_END_HEADERS
| HEADERS_FLAG_END_SEGMENT
|
1019 HEADERS_FLAG_PADDED
)) {
1020 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1025 if (current_frame_length_
!= GetWindowUpdateSize()) {
1026 set_error(SPDY_INVALID_CONTROL_FRAME
);
1027 } else if (current_frame_flags_
!= 0) {
1028 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1032 if (current_frame_length_
!= GetBlockedSize() ||
1033 protocol_version() <= SPDY3
) {
1034 set_error(SPDY_INVALID_CONTROL_FRAME
);
1035 } else if (current_frame_flags_
!= 0) {
1036 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1040 if (current_frame_length_
< GetPushPromiseMinimumSize()) {
1041 set_error(SPDY_INVALID_CONTROL_FRAME
);
1042 } else if (protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) {
1043 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1044 } else if (protocol_version() > SPDY3
&&
1045 current_frame_flags_
&
1046 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
1047 HEADERS_FLAG_PADDED
)) {
1048 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1052 if (current_frame_length_
< GetContinuationMinimumSize() ||
1053 protocol_version() <= SPDY3
) {
1054 set_error(SPDY_INVALID_CONTROL_FRAME
);
1055 } else if (current_frame_flags_
& ~HEADERS_FLAG_END_HEADERS
) {
1056 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1060 if (current_frame_length_
<= GetAltSvcMinimumSize()) {
1061 set_error(SPDY_INVALID_CONTROL_FRAME
);
1062 } else if (current_frame_flags_
!= 0) {
1063 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1067 if (current_frame_length_
!= GetPrioritySize() ||
1068 protocol_version() <= SPDY3
) {
1069 set_error(SPDY_INVALID_CONTROL_FRAME
);
1070 } else if (current_frame_flags_
!= 0) {
1071 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1075 LOG(WARNING
) << "Valid " << display_protocol_
1076 << " control frame with unhandled type: "
1077 << current_frame_type_
;
1078 // This branch should be unreachable because of the frame type bounds
1079 // check above. However, we DLOG(FATAL) here in an effort to painfully
1080 // club the head of the developer who failed to keep this file in sync
1081 // with spdy_protocol.h.
1082 set_error(SPDY_INVALID_CONTROL_FRAME
);
1087 if (state_
== SPDY_ERROR
) {
1091 if (current_frame_length_
>
1092 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1093 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1094 DLOG(WARNING
) << "Received control frame of type " << current_frame_type_
1095 << " with way too big of a payload: "
1096 << current_frame_length_
;
1097 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1101 if (current_frame_type_
== GOAWAY
) {
1102 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD
);
1106 if (current_frame_type_
== RST_STREAM
) {
1107 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD
);
1111 if (current_frame_type_
== ALTSVC
) {
1112 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD
);
1115 // Determine the frame size without variable-length data.
1116 int32 frame_size_without_variable_data
;
1117 switch (current_frame_type_
) {
1119 syn_frame_processed_
= true;
1120 frame_size_without_variable_data
= GetSynStreamMinimumSize();
1123 syn_frame_processed_
= true;
1124 frame_size_without_variable_data
= GetSynReplyMinimumSize();
1127 frame_size_without_variable_data
= GetSettingsMinimumSize();
1130 frame_size_without_variable_data
= GetHeadersMinimumSize();
1131 if (protocol_version() > SPDY3
) {
1132 if (current_frame_flags_
& HEADERS_FLAG_PADDED
) {
1133 frame_size_without_variable_data
+= kPadLengthFieldSize
;
1135 if (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1136 frame_size_without_variable_data
+=
1137 kPriorityDependencyPayloadSize
+
1138 kPriorityWeightPayloadSize
;
1143 frame_size_without_variable_data
= GetPushPromiseMinimumSize();
1144 if (protocol_version() > SPDY3
&&
1145 current_frame_flags_
& PUSH_PROMISE_FLAG_PADDED
) {
1146 frame_size_without_variable_data
+= kPadLengthFieldSize
;
1150 frame_size_without_variable_data
= GetContinuationMinimumSize();
1153 frame_size_without_variable_data
= -1;
1157 if ((frame_size_without_variable_data
== -1) &&
1158 (current_frame_length_
> kControlFrameBufferSize
)) {
1159 // We should already be in an error state. Double-check.
1160 DCHECK_EQ(SPDY_ERROR
, state_
);
1161 if (state_
!= SPDY_ERROR
) {
1162 LOG(DFATAL
) << display_protocol_
1163 << " control frame buffer too small for fixed-length frame.";
1164 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1169 if (frame_size_without_variable_data
> 0) {
1170 // We have a control frame with a header block. We need to parse the
1171 // remainder of the control frame's header before we can parse the header
1172 // block. The start of the header block varies with the control type.
1173 DCHECK_GE(frame_size_without_variable_data
,
1174 static_cast<int32
>(current_frame_buffer_length_
));
1175 remaining_control_header_
= frame_size_without_variable_data
-
1176 current_frame_buffer_length_
;
1178 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
1182 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
1185 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
1187 size_t bytes_to_read
= std::min(*len
, max_bytes
);
1188 if (bytes_to_read
> 0) {
1189 DCHECK_GE(kControlFrameBufferSize
,
1190 current_frame_buffer_length_
+ bytes_to_read
);
1191 memcpy(current_frame_buffer_
.get() + current_frame_buffer_length_
,
1194 current_frame_buffer_length_
+= bytes_to_read
;
1195 *data
+= bytes_to_read
;
1196 *len
-= bytes_to_read
;
1198 return bytes_to_read
;
1201 size_t SpdyFramer::GetSerializedLength(
1202 const SpdyMajorVersion spdy_version
,
1203 const SpdyHeaderBlock
* headers
) {
1204 const size_t num_name_value_pairs_size
1205 = (spdy_version
< SPDY3
) ? sizeof(uint16
) : sizeof(uint32
);
1206 const size_t length_of_name_size
= num_name_value_pairs_size
;
1207 const size_t length_of_value_size
= num_name_value_pairs_size
;
1209 size_t total_length
= num_name_value_pairs_size
;
1210 for (const auto& header
: *headers
) {
1211 // We add space for the length of the name and the length of the value as
1212 // well as the length of the name and the length of the value.
1213 total_length
+= length_of_name_size
+ header
.first
.size() +
1214 length_of_value_size
+ header
.second
.size();
1216 return total_length
;
1219 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder
* frame
,
1220 const SpdyMajorVersion spdy_version
,
1221 const SpdyHeaderBlock
* headers
) {
1222 if (spdy_version
< SPDY3
) {
1223 frame
->WriteUInt16(static_cast<uint16
>(headers
->size()));
1225 frame
->WriteUInt32(headers
->size());
1227 SpdyHeaderBlock::const_iterator it
;
1228 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1229 if (spdy_version
< SPDY3
) {
1230 frame
->WriteStringPiece16(it
->first
);
1231 frame
->WriteStringPiece16(it
->second
);
1233 frame
->WriteStringPiece32(it
->first
);
1234 frame
->WriteStringPiece32(it
->second
);
1239 // TODO(phajdan.jr): Clean up after we no longer need
1240 // to workaround http://crbug.com/139744.
1241 #if !defined(USE_SYSTEM_ZLIB)
1243 // These constants are used by zlib to differentiate between normal data and
1244 // cookie data. Cookie data is handled specially by zlib when compressing.
1246 // kZStandardData is compressed normally, save that it will never match
1247 // against any other class of data in the window.
1248 kZStandardData
= Z_CLASS_STANDARD
,
1249 // kZCookieData is compressed in its own Huffman blocks and only matches in
1250 // its entirety and only against other kZCookieData blocks. Any matches must
1251 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1252 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1254 kZCookieData
= Z_CLASS_COOKIE
,
1255 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1256 // against the window.
1257 kZHuffmanOnlyData
= Z_CLASS_HUFFMAN_ONLY
,
1260 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1261 // needed when switching between classes of data.
1262 static void WriteZ(const base::StringPiece
& data
,
1267 // If we are switching from standard to non-standard data then we need to end
1268 // the current Huffman context to avoid it leaking between them.
1269 if (out
->clas
== kZStandardData
&&
1270 clas
!= kZStandardData
) {
1272 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1273 DCHECK_EQ(Z_OK
, rv
);
1274 DCHECK_EQ(0u, out
->avail_in
);
1275 DCHECK_LT(0u, out
->avail_out
);
1278 out
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
.data()));
1279 out
->avail_in
= data
.size();
1281 if (clas
== kZStandardData
) {
1282 rv
= deflate(out
, Z_NO_FLUSH
);
1284 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1286 if (!data
.empty()) {
1287 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1288 DCHECK_EQ(Z_OK
, rv
);
1290 DCHECK_EQ(0u, out
->avail_in
);
1291 DCHECK_LT(0u, out
->avail_out
);
1294 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1295 static void WriteLengthZ(size_t n
,
1300 DCHECK_LE(length
, sizeof(buf
));
1301 for (unsigned i
= 1; i
<= length
; i
++) {
1302 buf
[length
- i
] = static_cast<char>(n
);
1305 WriteZ(base::StringPiece(buf
, length
), clas
, out
);
1308 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1309 // manner that resists the length of the compressed data from compromising
1311 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
1312 z_stream
* z
) const {
1313 unsigned length_length
= 4;
1314 if (protocol_version() < 3)
1317 WriteLengthZ(headers
->size(), length_length
, kZStandardData
, z
);
1319 std::map
<std::string
, std::string
>::const_iterator it
;
1320 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1321 WriteLengthZ(it
->first
.size(), length_length
, kZStandardData
, z
);
1322 WriteZ(it
->first
, kZStandardData
, z
);
1324 if (it
->first
== "cookie") {
1325 // We require the cookie values (save for the last) to end with a
1326 // semicolon and (save for the first) to start with a space. This is
1327 // typically the format that we are given them in but we reserialize them
1330 std::vector
<base::StringPiece
> cookie_values
;
1331 size_t cookie_length
= 0;
1332 base::StringPiece
cookie_data(it
->second
);
1335 while (!cookie_data
.empty() &&
1336 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
1337 cookie_data
.remove_prefix(1);
1339 if (cookie_data
.empty())
1343 for (i
= 0; i
< cookie_data
.size(); i
++) {
1344 if (cookie_data
[i
] == ';')
1347 if (i
< cookie_data
.size()) {
1348 if (!IsCookieEmpty(cookie_data
.substr(0, i
))) {
1349 cookie_values
.push_back(cookie_data
.substr(0, i
));
1350 cookie_length
+= i
+ 2 /* semicolon and space */;
1352 cookie_data
.remove_prefix(i
+ 1);
1354 if (!IsCookieEmpty(cookie_data
)) {
1355 cookie_values
.push_back(cookie_data
);
1356 cookie_length
+= cookie_data
.size();
1357 } else if (cookie_length
> 2) {
1358 cookie_length
-= 2 /* compensate for previously added length */;
1360 cookie_data
.remove_prefix(i
);
1364 WriteLengthZ(cookie_length
, length_length
, kZStandardData
, z
);
1365 for (size_t i
= 0; i
< cookie_values
.size(); i
++) {
1367 // Since zlib will only back-reference complete cookies, a cookie that
1368 // is currently last (and so doesn't have a trailing semicolon) won't
1369 // match if it's later in a non-final position. The same is true of
1370 // the first cookie.
1371 if (i
== 0 && cookie_values
.size() == 1) {
1372 cookie
= cookie_values
[i
].as_string();
1373 } else if (i
== 0) {
1374 cookie
= cookie_values
[i
].as_string() + ";";
1375 } else if (i
< cookie_values
.size() - 1) {
1376 cookie
= " " + cookie_values
[i
].as_string() + ";";
1378 cookie
= " " + cookie_values
[i
].as_string();
1380 WriteZ(cookie
, kZCookieData
, z
);
1382 } else if (it
->first
== "accept" ||
1383 it
->first
== "accept-charset" ||
1384 it
->first
== "accept-encoding" ||
1385 it
->first
== "accept-language" ||
1386 it
->first
== "host" ||
1387 it
->first
== "version" ||
1388 it
->first
== "method" ||
1389 it
->first
== "scheme" ||
1390 it
->first
== ":host" ||
1391 it
->first
== ":version" ||
1392 it
->first
== ":method" ||
1393 it
->first
== ":scheme" ||
1394 it
->first
== "user-agent") {
1395 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1396 WriteZ(it
->second
, kZStandardData
, z
);
1398 // Non-whitelisted headers are Huffman compressed in their own block, but
1399 // don't match against the window.
1400 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1401 WriteZ(it
->second
, kZHuffmanOnlyData
, z
);
1406 int rv
= deflate(z
, Z_SYNC_FLUSH
);
1407 DCHECK_EQ(Z_OK
, rv
);
1408 z
->clas
= kZStandardData
;
1411 #endif // !defined(USE_SYSTEM_ZLIB)
1413 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
1415 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
1416 const size_t original_len
= len
;
1418 if (remaining_control_header_
> 0) {
1419 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1420 remaining_control_header_
);
1421 remaining_control_header_
-= bytes_read
;
1422 remaining_data_length_
-= bytes_read
;
1425 if (remaining_control_header_
== 0) {
1426 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1427 current_frame_buffer_length_
);
1428 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1430 switch (current_frame_type_
) {
1433 DCHECK_GE(SPDY3
, protocol_version());
1434 bool successful_read
= true;
1435 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1436 DCHECK(successful_read
);
1437 if (current_frame_stream_id_
== 0) {
1438 set_error(SPDY_INVALID_CONTROL_FRAME
);
1442 SpdyStreamId associated_to_stream_id
= kInvalidStream
;
1443 successful_read
= reader
.ReadUInt31(&associated_to_stream_id
);
1444 DCHECK(successful_read
);
1446 SpdyPriority priority
= 0;
1447 successful_read
= reader
.ReadUInt8(&priority
);
1448 DCHECK(successful_read
);
1449 if (protocol_version() <= SPDY2
) {
1450 priority
= priority
>> 6;
1452 priority
= priority
>> 5;
1455 // Seek past unused byte; used to be credential slot in SPDY 3.
1458 DCHECK(reader
.IsDoneReading());
1459 if (debug_visitor_
) {
1460 debug_visitor_
->OnReceiveCompressedFrame(
1461 current_frame_stream_id_
,
1462 current_frame_type_
,
1463 current_frame_length_
);
1465 visitor_
->OnSynStream(
1466 current_frame_stream_id_
,
1467 associated_to_stream_id
,
1469 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1470 (current_frame_flags_
& CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
1472 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1475 if (protocol_version() > SPDY3
&&
1476 current_frame_flags_
& SETTINGS_FLAG_ACK
) {
1477 visitor_
->OnSettingsAck();
1478 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
1480 visitor_
->OnSettings(current_frame_flags_
&
1481 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
);
1482 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
1487 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1489 if (protocol_version() > SPDY3
) {
1490 DCHECK_EQ(HEADERS
, current_frame_type_
);
1492 bool successful_read
= true;
1493 if (protocol_version() <= SPDY3
) {
1494 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1495 DCHECK(successful_read
);
1497 if (current_frame_stream_id_
== 0) {
1498 set_error(SPDY_INVALID_CONTROL_FRAME
);
1501 if (protocol_version() <= SPDY2
) {
1502 // SPDY 2 had two unused bytes here. Seek past them.
1505 if (protocol_version() > SPDY3
&&
1506 !(current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) &&
1507 current_frame_type_
== HEADERS
) {
1508 expect_continuation_
= current_frame_stream_id_
;
1509 end_stream_when_done_
= current_frame_flags_
& CONTROL_FLAG_FIN
;
1511 if (protocol_version() > SPDY3
&&
1512 current_frame_flags_
& HEADERS_FLAG_PADDED
) {
1513 uint8 pad_payload_len
= 0;
1514 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
1515 successful_read
= reader
.ReadUInt8(&pad_payload_len
);
1516 DCHECK(successful_read
);
1517 remaining_padding_payload_length_
= pad_payload_len
;
1519 const bool has_priority
=
1520 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0;
1521 SpdyPriority priority
= 0;
1522 uint32 parent_stream_id
= 0;
1523 bool exclusive
= false;
1524 if (protocol_version() > SPDY3
&& has_priority
) {
1525 uint32 stream_dependency
;
1526 successful_read
= reader
.ReadUInt32(&stream_dependency
);
1527 DCHECK(successful_read
);
1528 UnpackStreamDependencyValues(stream_dependency
, &exclusive
,
1532 successful_read
= reader
.ReadUInt8(&weight
);
1533 if (successful_read
) {
1534 priority
= MapWeightToPriority(weight
);
1537 DCHECK(reader
.IsDoneReading());
1538 if (debug_visitor_
) {
1539 debug_visitor_
->OnReceiveCompressedFrame(
1540 current_frame_stream_id_
,
1541 current_frame_type_
,
1542 current_frame_length_
);
1544 if (current_frame_type_
== SYN_REPLY
) {
1545 visitor_
->OnSynReply(
1546 current_frame_stream_id_
,
1547 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0);
1549 visitor_
->OnHeaders(
1550 current_frame_stream_id_
,
1551 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0, priority
,
1552 parent_stream_id
, exclusive
,
1553 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1554 expect_continuation_
== 0);
1557 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1561 DCHECK_LT(SPDY3
, protocol_version());
1562 if (current_frame_stream_id_
== 0) {
1563 set_error(SPDY_INVALID_CONTROL_FRAME
);
1566 bool successful_read
= true;
1567 if (protocol_version() > SPDY3
&&
1568 current_frame_flags_
& PUSH_PROMISE_FLAG_PADDED
) {
1569 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
1570 uint8 pad_payload_len
= 0;
1571 successful_read
= reader
.ReadUInt8(&pad_payload_len
);
1572 DCHECK(successful_read
);
1573 remaining_padding_payload_length_
= pad_payload_len
;
1577 SpdyStreamId promised_stream_id
= kInvalidStream
;
1578 bool successful_read
= reader
.ReadUInt31(&promised_stream_id
);
1579 DCHECK(successful_read
);
1580 DCHECK(reader
.IsDoneReading());
1581 if (promised_stream_id
== 0) {
1582 set_error(SPDY_INVALID_CONTROL_FRAME
);
1585 if (!(current_frame_flags_
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
1586 expect_continuation_
= current_frame_stream_id_
;
1588 if (debug_visitor_
) {
1589 debug_visitor_
->OnReceiveCompressedFrame(
1590 current_frame_stream_id_
,
1591 current_frame_type_
,
1592 current_frame_length_
);
1594 visitor_
->OnPushPromise(current_frame_stream_id_
,
1596 (current_frame_flags_
&
1597 PUSH_PROMISE_FLAG_END_PUSH_PROMISE
) != 0);
1599 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1603 // Check to make sure the stream id of the current frame is
1604 // the same as that of the preceding frame.
1605 // If we're at this point we should already know that
1606 // expect_continuation_ != 0, so this doubles as a check
1607 // that current_frame_stream_id != 0.
1608 if (current_frame_stream_id_
!= expect_continuation_
) {
1609 set_error(SPDY_INVALID_CONTROL_FRAME
);
1612 if (current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) {
1613 expect_continuation_
= 0;
1615 if (debug_visitor_
) {
1616 debug_visitor_
->OnReceiveCompressedFrame(
1617 current_frame_stream_id_
,
1618 current_frame_type_
,
1619 current_frame_length_
);
1621 visitor_
->OnContinuation(current_frame_stream_id_
,
1622 (current_frame_flags_
&
1623 HEADERS_FLAG_END_HEADERS
) != 0);
1625 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1631 return original_len
- len
;
1634 // Does not buffer the control payload. Instead, either passes directly to the
1635 // visitor or decompresses and then passes directly to the visitor, via
1636 // IncrementallyDeliverControlFrameHeaderData() or
1637 // IncrementallyDecompressControlFrameHeaderData() respectively.
1638 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
1640 bool is_hpack_header_block
) {
1641 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
1643 bool processed_successfully
= true;
1644 if (current_frame_type_
!= SYN_STREAM
&&
1645 current_frame_type_
!= SYN_REPLY
&&
1646 current_frame_type_
!= HEADERS
&&
1647 current_frame_type_
!= PUSH_PROMISE
&&
1648 current_frame_type_
!= CONTINUATION
) {
1649 LOG(DFATAL
) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1651 size_t process_bytes
= std::min(
1652 data_len
, remaining_data_length_
- remaining_padding_payload_length_
);
1653 if (is_hpack_header_block
) {
1654 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1655 current_frame_stream_id_
, data
, process_bytes
)) {
1656 // TODO(jgraettinger): Finer-grained HPACK error codes.
1657 set_error(SPDY_DECOMPRESS_FAILURE
);
1658 processed_successfully
= false;
1660 } else if (process_bytes
> 0) {
1661 if (enable_compression_
&& protocol_version() <= SPDY3
) {
1662 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
1663 current_frame_stream_id_
, data
, process_bytes
);
1665 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
1666 current_frame_stream_id_
, data
, process_bytes
);
1669 remaining_data_length_
-= process_bytes
;
1671 // Handle the case that there is no futher data in this frame.
1672 if (remaining_data_length_
== remaining_padding_payload_length_
&&
1673 processed_successfully
) {
1674 if (expect_continuation_
== 0) {
1675 if (is_hpack_header_block
) {
1676 size_t compressed_len
= 0;
1677 if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
1678 current_frame_stream_id_
, &compressed_len
)) {
1679 // TODO(jgraettinger): To be removed with migration to
1680 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1681 // block, delivered via reentrant call to
1682 // ProcessControlFrameHeaderBlock().
1683 DeliverHpackBlockAsSpdy3Block(compressed_len
);
1684 return process_bytes
;
1686 set_error(SPDY_DECOMPRESS_FAILURE
);
1687 processed_successfully
= false;
1689 // The complete header block has been delivered. We send a zero-length
1690 // OnControlFrameHeaderData() to indicate this.
1691 visitor_
->OnControlFrameHeaderData(current_frame_stream_id_
, NULL
, 0);
1694 if (processed_successfully
) {
1695 CHANGE_STATE(SPDY_CONSUME_PADDING
);
1700 if (!processed_successfully
) {
1704 // Return amount processed.
1705 return process_bytes
;
1708 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
1710 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD
, state_
);
1711 DCHECK_EQ(SETTINGS
, current_frame_type_
);
1712 size_t unprocessed_bytes
= std::min(data_len
, remaining_data_length_
);
1713 size_t processed_bytes
= 0;
1715 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
1717 // Loop over our incoming data.
1718 while (unprocessed_bytes
> 0) {
1719 // Process up to one setting at a time.
1720 size_t processing
= std::min(
1722 static_cast<size_t>(setting_size
- settings_scratch_
.setting_buf_len
));
1724 // Check if we have a complete setting in our input.
1725 if (processing
== setting_size
) {
1726 // Parse the setting directly out of the input without buffering.
1727 if (!ProcessSetting(data
+ processed_bytes
)) {
1728 set_error(SPDY_INVALID_CONTROL_FRAME
);
1729 return processed_bytes
;
1732 // Continue updating settings_scratch_.setting_buf.
1733 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
1734 data
+ processed_bytes
,
1736 settings_scratch_
.setting_buf_len
+= processing
;
1738 // Check if we have a complete setting buffered.
1739 if (settings_scratch_
.setting_buf_len
== setting_size
) {
1740 if (!ProcessSetting(settings_scratch_
.setting_buf
)) {
1741 set_error(SPDY_INVALID_CONTROL_FRAME
);
1742 return processed_bytes
;
1744 // Reset settings_scratch_.setting_buf for our next setting.
1745 settings_scratch_
.setting_buf_len
= 0;
1750 unprocessed_bytes
-= processing
;
1751 processed_bytes
+= processing
;
1754 // Check if we're done handling this SETTINGS frame.
1755 remaining_data_length_
-= processed_bytes
;
1756 if (remaining_data_length_
== 0) {
1757 visitor_
->OnSettingsEnd();
1758 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
1761 return processed_bytes
;
1764 void SpdyFramer::DeliverHpackBlockAsSpdy3Block(size_t compressed_len
) {
1765 DCHECK_LT(SPDY3
, protocol_version());
1766 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
1768 const SpdyHeaderBlock
& block
= GetHpackDecoder()->decoded_block();
1769 if (block
.empty()) {
1770 // Special-case this to make tests happy.
1771 ProcessControlFrameHeaderBlock(NULL
, 0, false);
1774 size_t payload_len
= GetSerializedLength(protocol_version(), &block
);
1775 SpdyFrameBuilder
builder(payload_len
, SPDY3
);
1777 SerializeHeaderBlockWithoutCompression(&builder
, block
);
1778 scoped_ptr
<SpdyFrame
> frame(builder
.take());
1780 // Preserve padding length, and reset it after the re-entrant call.
1781 size_t remaining_padding
= remaining_padding_payload_length_
;
1783 remaining_padding_payload_length_
= 0;
1784 remaining_data_length_
= frame
->size();
1786 if (payload_len
!= 0) {
1787 int compression_pct
= 100 - (100 * compressed_len
) / payload_len
;
1788 DVLOG(1) << "Net.SpdyHpackDecompressionPercentage: " << compression_pct
;
1789 UMA_HISTOGRAM_PERCENTAGE("Net.SpdyHpackDecompressionPercentage",
1793 ProcessControlFrameHeaderBlock(frame
->data(), frame
->size(), false);
1795 remaining_padding_payload_length_
= remaining_padding
;
1796 remaining_data_length_
= remaining_padding
;
1799 bool SpdyFramer::ProcessSetting(const char* data
) {
1806 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1807 if (protocol_version() <= SPDY3
) {
1808 const uint32 id_and_flags_wire
= *(reinterpret_cast<const uint32
*>(data
));
1809 SettingsFlagsAndId id_and_flags
=
1810 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire
);
1811 id_field
= id_and_flags
.id();
1812 flags
= id_and_flags
.flags();
1813 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 4)));
1815 id_field
= ntohs(*(reinterpret_cast<const uint16
*>(data
)));
1816 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 2)));
1820 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field
)) {
1821 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_field
;
1822 if (protocol_version() <= SPDY3
) {
1825 // In HTTP2 we ignore unknown settings for extensibility.
1829 id
= SpdyConstants::ParseSettingId(protocol_version(), id_field
);
1831 if (protocol_version() <= SPDY3
) {
1832 // Detect duplicates.
1833 if (id
<= settings_scratch_
.last_setting_id
) {
1834 DLOG(WARNING
) << "Duplicate entry or invalid ordering for id " << id
1835 << " in " << display_protocol_
<< " SETTINGS frame "
1836 << "(last setting id was "
1837 << settings_scratch_
.last_setting_id
<< ").";
1840 settings_scratch_
.last_setting_id
= id
;
1843 uint8 kFlagsMask
= SETTINGS_FLAG_PLEASE_PERSIST
| SETTINGS_FLAG_PERSISTED
;
1844 if ((flags
& ~(kFlagsMask
)) != 0) {
1845 DLOG(WARNING
) << "Unknown SETTINGS flags provided for id " << id
<< ": "
1851 // Validation succeeded. Pass on to visitor.
1852 visitor_
->OnSetting(id
, flags
, value
);
1856 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
1857 size_t original_len
= len
;
1858 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1859 remaining_data_length_
);
1860 remaining_data_length_
-= bytes_read
;
1861 if (remaining_data_length_
== 0) {
1862 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1863 current_frame_buffer_length_
);
1864 reader
.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1866 // Use frame-specific handlers.
1867 switch (current_frame_type_
) {
1870 bool is_ack
= protocol_version() > SPDY3
&&
1871 (current_frame_flags_
& PING_FLAG_ACK
);
1872 bool successful_read
= true;
1873 if (protocol_version() <= SPDY3
) {
1875 successful_read
= reader
.ReadUInt32(&id32
);
1878 successful_read
= reader
.ReadUInt64(&id
);
1880 DCHECK(successful_read
);
1881 DCHECK(reader
.IsDoneReading());
1882 visitor_
->OnPing(id
, is_ack
);
1885 case WINDOW_UPDATE
: {
1886 uint32 delta_window_size
= 0;
1887 bool successful_read
= true;
1888 if (protocol_version() <= SPDY3
) {
1889 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1890 DCHECK(successful_read
);
1892 successful_read
= reader
.ReadUInt32(&delta_window_size
);
1893 DCHECK(successful_read
);
1894 DCHECK(reader
.IsDoneReading());
1895 visitor_
->OnWindowUpdate(current_frame_stream_id_
,
1900 DCHECK_LT(SPDY3
, protocol_version());
1901 DCHECK(reader
.IsDoneReading());
1902 visitor_
->OnBlocked(current_frame_stream_id_
);
1906 DCHECK_LT(SPDY3
, protocol_version());
1907 uint32 stream_dependency
;
1908 uint32 parent_stream_id
;
1911 bool successful_read
= reader
.ReadUInt32(&stream_dependency
);
1912 DCHECK(successful_read
);
1913 UnpackStreamDependencyValues(stream_dependency
, &exclusive
,
1916 successful_read
= reader
.ReadUInt8(&weight
);
1917 DCHECK(successful_read
);
1918 DCHECK(reader
.IsDoneReading());
1919 visitor_
->OnPriority(
1920 current_frame_stream_id_
, parent_stream_id
, weight
, exclusive
);
1925 LOG(FATAL
) << "Unhandled control frame " << current_frame_type_
;
1928 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
1930 return original_len
- len
;
1933 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data
, size_t len
) {
1937 // Clamp to the actual remaining payload.
1938 if (len
> remaining_data_length_
) {
1939 len
= remaining_data_length_
;
1941 size_t original_len
= len
;
1943 // Check if we had already read enough bytes to parse the GOAWAY header.
1944 const size_t header_size
= GetGoAwayMinimumSize();
1945 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1946 bool already_parsed_header
= (unread_header_bytes
== 0);
1947 if (!already_parsed_header
) {
1948 // Buffer the new GOAWAY header bytes we got.
1949 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1951 // Do we have enough to parse the constant size GOAWAY header?
1952 if (current_frame_buffer_length_
== header_size
) {
1953 // Parse out the last good stream id.
1954 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1955 current_frame_buffer_length_
);
1956 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1957 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1958 DCHECK(successful_read
);
1960 // In SPDYv3 and up, frames also specify a status code - parse it out.
1961 SpdyGoAwayStatus status
= GOAWAY_OK
;
1962 if (protocol_version() >= SPDY3
) {
1963 uint32 status_raw
= GOAWAY_OK
;
1964 successful_read
= reader
.ReadUInt32(&status_raw
);
1965 DCHECK(successful_read
);
1966 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1968 status
= SpdyConstants::ParseGoAwayStatus(protocol_version(),
1971 if (protocol_version() > SPDY3
) {
1972 // Treat unrecognized status codes as INTERNAL_ERROR as
1973 // recommended by the HTTP/2 spec.
1974 status
= GOAWAY_INTERNAL_ERROR
;
1978 // Finished parsing the GOAWAY header, call frame handler.
1979 visitor_
->OnGoAway(current_frame_stream_id_
, status
);
1983 // Handle remaining data as opaque.
1984 bool processed_successfully
= true;
1986 processed_successfully
= visitor_
->OnGoAwayFrameData(data
, len
);
1988 remaining_data_length_
-= original_len
;
1989 if (!processed_successfully
) {
1990 set_error(SPDY_GOAWAY_FRAME_CORRUPT
);
1991 } else if (remaining_data_length_
== 0) {
1992 // Signal that there is not more opaque data.
1993 visitor_
->OnGoAwayFrameData(NULL
, 0);
1994 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
1996 return original_len
;
1999 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data
, size_t len
) {
2003 // Clamp to the actual remaining payload.
2004 if (len
> remaining_data_length_
) {
2005 len
= remaining_data_length_
;
2007 size_t original_len
= len
;
2009 // Check if we had already read enough bytes to parse the fixed-length portion
2010 // of the RST_STREAM frame.
2011 const size_t header_size
= GetRstStreamMinimumSize();
2012 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
2013 bool already_parsed_header
= (unread_header_bytes
== 0);
2014 if (!already_parsed_header
) {
2015 // Buffer the new RST_STREAM header bytes we got.
2016 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
2018 // Do we have enough to parse the constant size RST_STREAM header?
2019 if (current_frame_buffer_length_
== header_size
) {
2020 // Parse out the last good stream id.
2021 SpdyFrameReader
reader(current_frame_buffer_
.get(),
2022 current_frame_buffer_length_
);
2023 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2024 if (protocol_version() <= SPDY3
) {
2025 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
2026 DCHECK(successful_read
);
2029 SpdyRstStreamStatus status
= RST_STREAM_INVALID
;
2030 uint32 status_raw
= status
;
2031 bool successful_read
= reader
.ReadUInt32(&status_raw
);
2032 DCHECK(successful_read
);
2033 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
2036 SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw
);
2038 if (protocol_version() > SPDY3
) {
2039 // Treat unrecognized status codes as INTERNAL_ERROR as
2040 // recommended by the HTTP/2 spec.
2041 status
= RST_STREAM_INTERNAL_ERROR
;
2044 // Finished parsing the RST_STREAM header, call frame handler.
2045 visitor_
->OnRstStream(current_frame_stream_id_
, status
);
2049 // Handle remaining data as opaque.
2050 bool processed_successfully
= true;
2052 processed_successfully
= visitor_
->OnRstStreamFrameData(data
, len
);
2054 remaining_data_length_
-= original_len
;
2055 if (!processed_successfully
) {
2056 set_error(SPDY_RST_STREAM_FRAME_CORRUPT
);
2057 } else if (remaining_data_length_
== 0) {
2058 // Signal that there is not more opaque data.
2059 visitor_
->OnRstStreamFrameData(NULL
, 0);
2060 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
2062 return original_len
;
2065 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data
, size_t len
) {
2070 // Clamp to the actual remaining payload.
2071 len
= std::min(len
, remaining_data_length_
);
2073 if (altsvc_scratch_
.buffer
.get() == nullptr) {
2074 altsvc_scratch_
.buffer
.reset(
2075 new char[current_frame_length_
- GetControlFrameHeaderSize()]);
2076 altsvc_scratch_
.buffer_length
= 0;
2078 memcpy(altsvc_scratch_
.buffer
.get() + altsvc_scratch_
.buffer_length
, data
,
2080 altsvc_scratch_
.buffer_length
+= len
;
2081 remaining_data_length_
-= len
;
2082 if (remaining_data_length_
> 0) {
2086 SpdyFrameReader
reader(altsvc_scratch_
.buffer
.get(),
2087 altsvc_scratch_
.buffer_length
);
2089 bool successful_read
= reader
.ReadStringPiece16(&origin
);
2090 if (!successful_read
) {
2091 set_error(SPDY_INVALID_CONTROL_FRAME
);
2094 StringPiece
value(altsvc_scratch_
.buffer
.get() + reader
.GetBytesConsumed(),
2095 altsvc_scratch_
.buffer_length
- reader
.GetBytesConsumed());
2097 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector
;
2099 SpdyAltSvcWireFormat::ParseHeaderFieldValue(value
, &altsvc_vector
);
2101 set_error(SPDY_INVALID_CONTROL_FRAME
);
2105 visitor_
->OnAltSvc(current_frame_stream_id_
, origin
, altsvc_vector
);
2106 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
2110 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data
, size_t len
) {
2111 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH
, state_
);
2112 DCHECK_EQ(0u, remaining_padding_payload_length_
);
2113 DCHECK_EQ(DATA
, current_frame_type_
);
2115 size_t original_len
= len
;
2116 if (current_frame_flags_
& DATA_FLAG_PADDED
) {
2118 if (remaining_data_length_
< kPadLengthFieldSize
) {
2119 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2123 static_assert(kPadLengthFieldSize
== 1,
2124 "Unexpected pad length field size.");
2125 remaining_padding_payload_length_
= *reinterpret_cast<const uint8
*>(data
);
2128 --remaining_data_length_
;
2129 visitor_
->OnStreamPadding(current_frame_stream_id_
, kPadLengthFieldSize
);
2131 // We don't have the data available for parsing the pad length field. Keep
2137 if (remaining_padding_payload_length_
> remaining_data_length_
) {
2138 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2141 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
2142 return original_len
- len
;
2145 size_t SpdyFramer::ProcessFramePadding(const char* data
, size_t len
) {
2146 DCHECK_EQ(SPDY_CONSUME_PADDING
, state_
);
2148 size_t original_len
= len
;
2149 if (remaining_padding_payload_length_
> 0) {
2150 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
2151 size_t amount_to_discard
= std::min(remaining_padding_payload_length_
, len
);
2152 if (current_frame_type_
== DATA
&& amount_to_discard
> 0) {
2153 DCHECK_LE(HTTP2
, protocol_version());
2154 visitor_
->OnStreamPadding(current_frame_stream_id_
, amount_to_discard
);
2156 data
+= amount_to_discard
;
2157 len
-= amount_to_discard
;
2158 remaining_padding_payload_length_
-= amount_to_discard
;
2159 remaining_data_length_
-= amount_to_discard
;
2162 if (remaining_data_length_
== 0) {
2163 // If the FIN flag is set, or this ends a header block which set FIN,
2164 // inform the visitor of EOF via a 0-length data frame.
2165 if (expect_continuation_
== 0 &&
2166 ((current_frame_flags_
& CONTROL_FLAG_FIN
) != 0 ||
2167 end_stream_when_done_
)) {
2168 end_stream_when_done_
= false;
2169 visitor_
->OnStreamFrameData(current_frame_stream_id_
, NULL
, 0, true);
2171 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
2173 return original_len
- len
;
2176 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
2177 size_t original_len
= len
;
2178 if (remaining_data_length_
- remaining_padding_payload_length_
> 0) {
2179 size_t amount_to_forward
= std::min(
2180 remaining_data_length_
- remaining_padding_payload_length_
, len
);
2181 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
2182 // Only inform the visitor if there is data.
2183 if (amount_to_forward
) {
2184 visitor_
->OnStreamFrameData(
2185 current_frame_stream_id_
, data
, amount_to_forward
, false);
2188 data
+= amount_to_forward
;
2189 len
-= amount_to_forward
;
2190 remaining_data_length_
-= amount_to_forward
;
2193 if (remaining_data_length_
== remaining_padding_payload_length_
) {
2194 CHANGE_STATE(SPDY_CONSUME_PADDING
);
2196 return original_len
- len
;
2199 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2201 size_t original_len
= len
;
2202 if (remaining_data_length_
> 0) {
2203 size_t amount_to_ignore
= std::min(remaining_data_length_
, len
);
2204 len
-= amount_to_ignore
;
2205 remaining_data_length_
-= amount_to_ignore
;
2208 if (remaining_data_length_
== 0) {
2209 CHANGE_STATE(SPDY_FRAME_COMPLETE
);
2211 return original_len
- len
;
2214 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
2215 size_t header_length
,
2216 SpdyHeaderBlock
* block
) const {
2217 SpdyFrameReader
reader(header_data
, header_length
);
2219 // Read number of headers.
2221 if (protocol_version() <= SPDY2
) {
2223 if (!reader
.ReadUInt16(&temp
)) {
2224 DVLOG(1) << "Unable to read number of headers.";
2229 if (!reader
.ReadUInt32(&num_headers
)) {
2230 DVLOG(1) << "Unable to read number of headers.";
2235 // Read each header.
2236 for (uint32 index
= 0; index
< num_headers
; ++index
) {
2237 base::StringPiece temp
;
2239 // Read header name.
2240 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2241 : !reader
.ReadStringPiece32(&temp
)) {
2242 DVLOG(1) << "Unable to read header name (" << index
+ 1 << " of "
2243 << num_headers
<< ").";
2246 std::string name
= temp
.as_string();
2248 // Read header value.
2249 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2250 : !reader
.ReadStringPiece32(&temp
)) {
2251 DVLOG(1) << "Unable to read header value (" << index
+ 1 << " of "
2252 << num_headers
<< ").";
2255 std::string value
= temp
.as_string();
2257 // Ensure no duplicates.
2258 if (block
->find(name
) != block
->end()) {
2259 DVLOG(1) << "Duplicate header '" << name
<< "' (" << index
+ 1 << " of "
2260 << num_headers
<< ").";
2265 (*block
)[name
] = value
;
2267 return reader
.GetBytesConsumed();
2270 SpdySerializedFrame
* SpdyFramer::SerializeData(
2271 const SpdyDataIR
& data_ir
) const {
2272 uint8 flags
= DATA_FLAG_NONE
;
2273 if (data_ir
.fin()) {
2274 flags
= DATA_FLAG_FIN
;
2277 if (protocol_version() > SPDY3
) {
2278 int num_padding_fields
= 0;
2279 if (data_ir
.padded()) {
2280 flags
|= DATA_FLAG_PADDED
;
2281 ++num_padding_fields
;
2284 const size_t size_with_padding
= num_padding_fields
+
2285 data_ir
.data().length() + data_ir
.padding_payload_len() +
2286 GetDataFrameMinimumSize();
2287 SpdyFrameBuilder
builder(size_with_padding
, protocol_version());
2288 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2289 if (data_ir
.padded()) {
2290 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2292 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2293 if (data_ir
.padding_payload_len() > 0) {
2294 string
padding(data_ir
.padding_payload_len(), 0);
2295 builder
.WriteBytes(padding
.data(), padding
.length());
2297 DCHECK_EQ(size_with_padding
, builder
.length());
2298 return builder
.take();
2300 const size_t size
= GetDataFrameMinimumSize() + data_ir
.data().length();
2301 SpdyFrameBuilder
builder(size
, protocol_version());
2302 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2303 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2304 DCHECK_EQ(size
, builder
.length());
2305 return builder
.take();
2309 SpdySerializedFrame
* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2310 const SpdyDataIR
& data_ir
) const {
2311 uint8 flags
= DATA_FLAG_NONE
;
2312 if (data_ir
.fin()) {
2313 flags
= DATA_FLAG_FIN
;
2316 size_t frame_size
= GetDataFrameMinimumSize();
2317 size_t num_padding_fields
= 0;
2318 if (protocol_version() > SPDY3
) {
2319 if (data_ir
.padded()) {
2320 flags
|= DATA_FLAG_PADDED
;
2321 ++num_padding_fields
;
2323 frame_size
+= num_padding_fields
;
2326 SpdyFrameBuilder
builder(frame_size
, protocol_version());
2327 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2328 if (protocol_version() > SPDY3
) {
2329 if (data_ir
.padded()) {
2330 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2332 builder
.OverwriteLength(*this, num_padding_fields
+
2333 data_ir
.data().length() + data_ir
.padding_payload_len());
2335 builder
.OverwriteLength(*this, data_ir
.data().length());
2337 DCHECK_EQ(frame_size
, builder
.length());
2338 return builder
.take();
2341 SpdySerializedFrame
* SpdyFramer::SerializeSynStream(
2342 const SpdySynStreamIR
& syn_stream
) {
2343 DCHECK_GE(SPDY3
, protocol_version());
2345 if (syn_stream
.fin()) {
2346 flags
|= CONTROL_FLAG_FIN
;
2348 if (syn_stream
.unidirectional()) {
2349 // TODO(hkhalil): invalid for HTTP2.
2350 flags
|= CONTROL_FLAG_UNIDIRECTIONAL
;
2353 // Sanitize priority.
2354 uint8 priority
= syn_stream
.priority();
2355 if (priority
> GetLowestPriority()) {
2356 DLOG(DFATAL
) << "Priority out-of-bounds.";
2357 priority
= GetLowestPriority();
2360 // The size of this frame, including variable-length header block.
2361 size_t size
= GetSynStreamMinimumSize() +
2362 GetSerializedLength(syn_stream
.header_block());
2364 SpdyFrameBuilder
builder(size
, protocol_version());
2365 builder
.WriteControlFrameHeader(*this, SYN_STREAM
, flags
);
2366 builder
.WriteUInt32(syn_stream
.stream_id());
2367 builder
.WriteUInt32(syn_stream
.associated_to_stream_id());
2368 builder
.WriteUInt8(priority
<< ((protocol_version() <= SPDY2
) ? 6 : 5));
2369 builder
.WriteUInt8(0); // Unused byte where credential slot used to be.
2370 DCHECK_EQ(GetSynStreamMinimumSize(), builder
.length());
2371 SerializeHeaderBlock(&builder
, syn_stream
);
2373 if (debug_visitor_
) {
2374 const size_t payload_len
=
2375 GetSerializedLength(protocol_version(), &(syn_stream
.header_block()));
2376 debug_visitor_
->OnSendCompressedFrame(syn_stream
.stream_id(),
2382 return builder
.take();
2385 SpdySerializedFrame
* SpdyFramer::SerializeSynReply(
2386 const SpdySynReplyIR
& syn_reply
) {
2387 DCHECK_GE(SPDY3
, protocol_version());
2389 if (syn_reply
.fin()) {
2390 flags
|= CONTROL_FLAG_FIN
;
2393 // The size of this frame, including variable-length header block.
2395 GetSynReplyMinimumSize() + GetSerializedLength(syn_reply
.header_block());
2397 SpdyFrameBuilder
builder(size
, protocol_version());
2398 if (protocol_version() <= SPDY3
) {
2399 builder
.WriteControlFrameHeader(*this, SYN_REPLY
, flags
);
2400 builder
.WriteUInt32(syn_reply
.stream_id());
2402 builder
.BeginNewFrame(*this,
2405 syn_reply
.stream_id());
2407 if (protocol_version() < SPDY3
) {
2408 builder
.WriteUInt16(0); // Unused.
2410 DCHECK_EQ(GetSynReplyMinimumSize(), builder
.length());
2411 SerializeHeaderBlock(&builder
, syn_reply
);
2413 if (debug_visitor_
) {
2414 const size_t payload_len
=
2415 GetSerializedLength(protocol_version(), &(syn_reply
.header_block()));
2416 debug_visitor_
->OnSendCompressedFrame(syn_reply
.stream_id(),
2422 return builder
.take();
2425 SpdySerializedFrame
* SpdyFramer::SerializeRstStream(
2426 const SpdyRstStreamIR
& rst_stream
) const {
2427 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2428 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2429 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2430 // commented but left in place to simplify future patching.
2431 // Compute the output buffer size, taking opaque data into account.
2432 size_t expected_length
= GetRstStreamMinimumSize();
2433 if (protocol_version() > SPDY3
) {
2434 expected_length
+= rst_stream
.description().size();
2436 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2438 // Serialize the RST_STREAM frame.
2439 if (protocol_version() <= SPDY3
) {
2440 builder
.WriteControlFrameHeader(*this, RST_STREAM
, 0);
2441 builder
.WriteUInt32(rst_stream
.stream_id());
2443 builder
.BeginNewFrame(*this, RST_STREAM
, 0, rst_stream
.stream_id());
2446 builder
.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
2447 protocol_version(), rst_stream
.status()));
2449 // In HTTP2 and up, RST_STREAM frames may also specify opaque data.
2450 if (protocol_version() > SPDY3
&& rst_stream
.description().size() > 0) {
2451 builder
.WriteBytes(rst_stream
.description().data(),
2452 rst_stream
.description().size());
2455 DCHECK_EQ(expected_length
, builder
.length());
2456 return builder
.take();
2459 SpdySerializedFrame
* SpdyFramer::SerializeSettings(
2460 const SpdySettingsIR
& settings
) const {
2463 if (protocol_version() <= SPDY3
) {
2464 if (settings
.clear_settings()) {
2465 flags
|= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
2468 if (settings
.is_ack()) {
2469 flags
|= SETTINGS_FLAG_ACK
;
2472 const SpdySettingsIR::ValueMap
* values
= &(settings
.values());
2474 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
2475 // Size, in bytes, of this SETTINGS frame.
2476 const size_t size
= GetSettingsMinimumSize() +
2477 (values
->size() * setting_size
);
2478 SpdyFrameBuilder
builder(size
, protocol_version());
2479 if (protocol_version() <= SPDY3
) {
2480 builder
.WriteControlFrameHeader(*this, SETTINGS
, flags
);
2482 builder
.BeginNewFrame(*this, SETTINGS
, flags
, 0);
2485 // If this is an ACK, payload should be empty.
2486 if (protocol_version() > SPDY3
&& settings
.is_ack()) {
2487 return builder
.take();
2490 if (protocol_version() <= SPDY3
) {
2491 builder
.WriteUInt32(values
->size());
2493 DCHECK_EQ(GetSettingsMinimumSize(), builder
.length());
2494 for (SpdySettingsIR::ValueMap::const_iterator it
= values
->begin();
2495 it
!= values
->end();
2498 SpdyConstants::SerializeSettingId(protocol_version(), it
->first
);
2499 DCHECK_GE(setting_id
, 0);
2500 if (protocol_version() <= SPDY3
) {
2501 uint8 setting_flags
= 0;
2502 if (it
->second
.persist_value
) {
2503 setting_flags
|= SETTINGS_FLAG_PLEASE_PERSIST
;
2505 if (it
->second
.persisted
) {
2506 setting_flags
|= SETTINGS_FLAG_PERSISTED
;
2508 SettingsFlagsAndId
flags_and_id(setting_flags
, setting_id
);
2509 uint32 id_and_flags_wire
= flags_and_id
.GetWireFormat(protocol_version());
2510 builder
.WriteBytes(&id_and_flags_wire
, 4);
2512 builder
.WriteUInt16(static_cast<uint16
>(setting_id
));
2514 builder
.WriteUInt32(it
->second
.value
);
2516 DCHECK_EQ(size
, builder
.length());
2517 return builder
.take();
2520 SpdySerializedFrame
* SpdyFramer::SerializePing(const SpdyPingIR
& ping
) const {
2521 SpdyFrameBuilder
builder(GetPingSize(), protocol_version());
2522 if (protocol_version() <= SPDY3
) {
2523 builder
.WriteControlFrameHeader(*this, PING
, kNoFlags
);
2524 builder
.WriteUInt32(static_cast<uint32
>(ping
.id()));
2527 if (ping
.is_ack()) {
2528 flags
|= PING_FLAG_ACK
;
2530 builder
.BeginNewFrame(*this, PING
, flags
, 0);
2531 builder
.WriteUInt64(ping
.id());
2533 DCHECK_EQ(GetPingSize(), builder
.length());
2534 return builder
.take();
2537 SpdySerializedFrame
* SpdyFramer::SerializeGoAway(
2538 const SpdyGoAwayIR
& goaway
) const {
2540 // Compute the output buffer size, take opaque data into account.
2541 size_t expected_length
= GetGoAwayMinimumSize();
2542 if (protocol_version() > SPDY3
) {
2543 expected_length
+= goaway
.description().size();
2545 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2547 // Serialize the GOAWAY frame.
2548 if (protocol_version() <= SPDY3
) {
2549 builder
.WriteControlFrameHeader(*this, GOAWAY
, kNoFlags
);
2551 builder
.BeginNewFrame(*this, GOAWAY
, 0, 0);
2554 // GOAWAY frames specify the last good stream id for all SPDY versions.
2555 builder
.WriteUInt32(goaway
.last_good_stream_id());
2557 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2558 if (protocol_version() >= SPDY3
) {
2559 // TODO(jgraettinger): Merge back to server-side.
2560 builder
.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2564 // In HTTP2 and up, GOAWAY frames may also specify opaque data.
2565 if ((protocol_version() > SPDY3
) && (goaway
.description().size() > 0)) {
2566 builder
.WriteBytes(goaway
.description().data(),
2567 goaway
.description().size());
2570 DCHECK_EQ(expected_length
, builder
.length());
2571 return builder
.take();
2574 SpdySerializedFrame
* SpdyFramer::SerializeHeaders(
2575 const SpdyHeadersIR
& headers
) {
2577 if (headers
.fin()) {
2578 flags
|= CONTROL_FLAG_FIN
;
2580 if (protocol_version() > SPDY3
) {
2581 // This will get overwritten if we overflow into a CONTINUATION frame.
2582 flags
|= HEADERS_FLAG_END_HEADERS
;
2583 if (headers
.has_priority()) {
2584 flags
|= HEADERS_FLAG_PRIORITY
;
2586 if (headers
.padded()) {
2587 flags
|= HEADERS_FLAG_PADDED
;
2591 // The size of this frame, including padding (if there is any) and
2592 // variable-length header block.
2593 size_t size
= GetHeadersMinimumSize();
2595 if (protocol_version() > SPDY3
&& headers
.padded()) {
2596 size
+= kPadLengthFieldSize
;
2597 size
+= headers
.padding_payload_len();
2600 SpdyPriority priority
= static_cast<SpdyPriority
>(headers
.priority());
2601 if (headers
.has_priority()) {
2602 if (headers
.priority() > GetLowestPriority()) {
2603 DLOG(DFATAL
) << "Priority out-of-bounds.";
2604 priority
= GetLowestPriority();
2609 string hpack_encoding
;
2610 if (protocol_version() > SPDY3
) {
2611 if (enable_compression_
) {
2612 GetHpackEncoder()->EncodeHeaderSet(headers
.header_block(),
2615 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2616 headers
.header_block(), &hpack_encoding
);
2618 size
+= hpack_encoding
.size();
2619 if (size
> kMaxControlFrameSize
) {
2620 size
+= GetNumberRequiredContinuationFrames(size
) *
2621 GetContinuationMinimumSize();
2622 flags
&= ~HEADERS_FLAG_END_HEADERS
;
2625 size
+= GetSerializedLength(headers
.header_block());
2628 SpdyFrameBuilder
builder(size
, protocol_version());
2629 if (protocol_version() <= SPDY3
) {
2630 builder
.WriteControlFrameHeader(*this, HEADERS
, flags
);
2631 builder
.WriteUInt32(headers
.stream_id());
2633 builder
.BeginNewFrame(*this,
2636 headers
.stream_id());
2638 if (protocol_version() <= SPDY2
) {
2639 builder
.WriteUInt16(0); // Unused.
2641 DCHECK_EQ(GetHeadersMinimumSize(), builder
.length());
2643 if (protocol_version() > SPDY3
) {
2644 int padding_payload_len
= 0;
2645 if (headers
.padded()) {
2646 builder
.WriteUInt8(headers
.padding_payload_len());
2647 padding_payload_len
= headers
.padding_payload_len();
2649 if (headers
.has_priority()) {
2650 builder
.WriteUInt32(PackStreamDependencyValues(
2651 headers
.exclusive(), headers
.parent_stream_id()));
2652 builder
.WriteUInt8(MapPriorityToWeight(priority
));
2654 WritePayloadWithContinuation(&builder
,
2656 headers
.stream_id(),
2658 padding_payload_len
);
2660 SerializeHeaderBlock(&builder
, headers
);
2663 if (debug_visitor_
) {
2664 // HTTP2 uses HPACK for header compression. However, continue to
2665 // use GetSerializedLength() for an apples-to-apples comparision of
2666 // compression performance between HPACK and SPDY w/ deflate.
2667 const size_t payload_len
=
2668 GetSerializedLength(protocol_version(), &(headers
.header_block()));
2669 debug_visitor_
->OnSendCompressedFrame(headers
.stream_id(),
2675 return builder
.take();
2678 SpdySerializedFrame
* SpdyFramer::SerializeWindowUpdate(
2679 const SpdyWindowUpdateIR
& window_update
) const {
2680 SpdyFrameBuilder
builder(GetWindowUpdateSize(), protocol_version());
2681 if (protocol_version() <= SPDY3
) {
2682 builder
.WriteControlFrameHeader(*this, WINDOW_UPDATE
, kNoFlags
);
2683 builder
.WriteUInt32(window_update
.stream_id());
2685 builder
.BeginNewFrame(*this,
2688 window_update
.stream_id());
2690 builder
.WriteUInt32(window_update
.delta());
2691 DCHECK_EQ(GetWindowUpdateSize(), builder
.length());
2692 return builder
.take();
2695 SpdyFrame
* SpdyFramer::SerializeBlocked(const SpdyBlockedIR
& blocked
) const {
2696 DCHECK_LT(SPDY3
, protocol_version());
2697 SpdyFrameBuilder
builder(GetBlockedSize(), protocol_version());
2698 builder
.BeginNewFrame(*this, BLOCKED
, kNoFlags
, blocked
.stream_id());
2699 return builder
.take();
2702 SpdyFrame
* SpdyFramer::SerializePushPromise(
2703 const SpdyPushPromiseIR
& push_promise
) {
2704 DCHECK_LT(SPDY3
, protocol_version());
2706 // This will get overwritten if we overflow into a CONTINUATION frame.
2707 flags
|= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2708 // The size of this frame, including variable-length name-value block.
2709 size_t size
= GetPushPromiseMinimumSize();
2711 if (push_promise
.padded()) {
2712 flags
|= PUSH_PROMISE_FLAG_PADDED
;
2713 size
+= kPadLengthFieldSize
;
2714 size
+= push_promise
.padding_payload_len();
2717 string hpack_encoding
;
2718 if (enable_compression_
) {
2719 GetHpackEncoder()->EncodeHeaderSet(push_promise
.header_block(),
2722 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2723 push_promise
.header_block(), &hpack_encoding
);
2725 size
+= hpack_encoding
.size();
2726 if (size
> kMaxControlFrameSize
) {
2727 size
+= GetNumberRequiredContinuationFrames(size
) *
2728 GetContinuationMinimumSize();
2729 flags
&= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2732 SpdyFrameBuilder
builder(size
, protocol_version());
2733 builder
.BeginNewFrame(*this,
2736 push_promise
.stream_id());
2737 int padding_payload_len
= 0;
2738 if (push_promise
.padded()) {
2739 builder
.WriteUInt8(push_promise
.padding_payload_len());
2740 builder
.WriteUInt32(push_promise
.promised_stream_id());
2741 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize
,
2744 padding_payload_len
= push_promise
.padding_payload_len();
2746 builder
.WriteUInt32(push_promise
.promised_stream_id());
2747 DCHECK_EQ(GetPushPromiseMinimumSize(), builder
.length());
2750 WritePayloadWithContinuation(&builder
,
2752 push_promise
.stream_id(),
2754 padding_payload_len
);
2756 if (debug_visitor_
) {
2757 // HTTP2 uses HPACK for header compression. However, continue to
2758 // use GetSerializedLength() for an apples-to-apples comparision of
2759 // compression performance between HPACK and SPDY w/ deflate.
2760 const size_t payload_len
=
2761 GetSerializedLength(protocol_version(), &(push_promise
.header_block()));
2762 debug_visitor_
->OnSendCompressedFrame(push_promise
.stream_id(),
2768 return builder
.take();
2771 // TODO(jgraettinger): This implementation is incorrect. The continuation
2772 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2773 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2774 SpdyFrame
* SpdyFramer::SerializeContinuation(
2775 const SpdyContinuationIR
& continuation
) {
2776 CHECK_LT(SPDY3
, protocol_version());
2778 if (continuation
.end_headers()) {
2779 flags
|= HEADERS_FLAG_END_HEADERS
;
2782 // The size of this frame, including variable-length name-value block.
2783 size_t size
= GetContinuationMinimumSize();
2784 string hpack_encoding
;
2785 if (enable_compression_
) {
2786 GetHpackEncoder()->EncodeHeaderSet(continuation
.header_block(),
2789 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2790 continuation
.header_block(), &hpack_encoding
);
2792 size
+= hpack_encoding
.size();
2794 SpdyFrameBuilder
builder(size
, protocol_version());
2795 builder
.BeginNewFrame(*this, CONTINUATION
, flags
,
2796 continuation
.stream_id());
2797 DCHECK_EQ(GetContinuationMinimumSize(), builder
.length());
2799 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2800 return builder
.take();
2803 SpdyFrame
* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR
& altsvc_ir
) {
2804 DCHECK_LT(SPDY3
, protocol_version());
2806 size_t size
= GetAltSvcMinimumSize();
2807 size
+= altsvc_ir
.origin().length();
2808 string value
= SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
2809 altsvc_ir
.altsvc_vector());
2810 size
+= value
.length();
2812 SpdyFrameBuilder
builder(size
, protocol_version());
2813 builder
.BeginNewFrame(*this, ALTSVC
, kNoFlags
, altsvc_ir
.stream_id());
2815 builder
.WriteUInt16(altsvc_ir
.origin().length());
2816 builder
.WriteBytes(altsvc_ir
.origin().data(), altsvc_ir
.origin().length());
2817 builder
.WriteBytes(value
.data(), value
.length());
2818 DCHECK_LT(GetAltSvcMinimumSize(), builder
.length());
2819 return builder
.take();
2822 SpdyFrame
* SpdyFramer::SerializePriority(const SpdyPriorityIR
& priority
) const {
2823 DCHECK_LT(SPDY3
, protocol_version());
2824 size_t size
= GetPrioritySize();
2826 SpdyFrameBuilder
builder(size
, protocol_version());
2827 builder
.BeginNewFrame(*this, PRIORITY
, kNoFlags
, priority
.stream_id());
2829 builder
.WriteUInt32(PackStreamDependencyValues(priority
.exclusive(),
2830 priority
.parent_stream_id()));
2831 builder
.WriteUInt8(priority
.weight());
2832 DCHECK_EQ(GetPrioritySize(), builder
.length());
2833 return builder
.take();
2838 class FrameSerializationVisitor
: public SpdyFrameVisitor
{
2840 explicit FrameSerializationVisitor(SpdyFramer
* framer
) : framer_(framer
) {}
2841 ~FrameSerializationVisitor() override
{}
2843 SpdySerializedFrame
* ReleaseSerializedFrame() { return frame_
.release(); }
2845 void VisitData(const SpdyDataIR
& data
) override
{
2846 frame_
.reset(framer_
->SerializeData(data
));
2848 void VisitSynStream(const SpdySynStreamIR
& syn_stream
) override
{
2849 frame_
.reset(framer_
->SerializeSynStream(syn_stream
));
2851 void VisitSynReply(const SpdySynReplyIR
& syn_reply
) override
{
2852 frame_
.reset(framer_
->SerializeSynReply(syn_reply
));
2854 void VisitRstStream(const SpdyRstStreamIR
& rst_stream
) override
{
2855 frame_
.reset(framer_
->SerializeRstStream(rst_stream
));
2857 void VisitSettings(const SpdySettingsIR
& settings
) override
{
2858 frame_
.reset(framer_
->SerializeSettings(settings
));
2860 void VisitPing(const SpdyPingIR
& ping
) override
{
2861 frame_
.reset(framer_
->SerializePing(ping
));
2863 void VisitGoAway(const SpdyGoAwayIR
& goaway
) override
{
2864 frame_
.reset(framer_
->SerializeGoAway(goaway
));
2866 void VisitHeaders(const SpdyHeadersIR
& headers
) override
{
2867 frame_
.reset(framer_
->SerializeHeaders(headers
));
2869 void VisitWindowUpdate(const SpdyWindowUpdateIR
& window_update
) override
{
2870 frame_
.reset(framer_
->SerializeWindowUpdate(window_update
));
2872 void VisitBlocked(const SpdyBlockedIR
& blocked
) override
{
2873 frame_
.reset(framer_
->SerializeBlocked(blocked
));
2875 void VisitPushPromise(const SpdyPushPromiseIR
& push_promise
) override
{
2876 frame_
.reset(framer_
->SerializePushPromise(push_promise
));
2878 void VisitContinuation(const SpdyContinuationIR
& continuation
) override
{
2879 frame_
.reset(framer_
->SerializeContinuation(continuation
));
2881 void VisitAltSvc(const SpdyAltSvcIR
& altsvc
) override
{
2882 frame_
.reset(framer_
->SerializeAltSvc(altsvc
));
2884 void VisitPriority(const SpdyPriorityIR
& priority
) override
{
2885 frame_
.reset(framer_
->SerializePriority(priority
));
2889 SpdyFramer
* framer_
;
2890 scoped_ptr
<SpdySerializedFrame
> frame_
;
2895 SpdySerializedFrame
* SpdyFramer::SerializeFrame(const SpdyFrameIR
& frame
) {
2896 FrameSerializationVisitor
visitor(this);
2897 frame
.Visit(&visitor
);
2898 return visitor
.ReleaseSerializedFrame();
2901 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock
& headers
) {
2902 CHECK_GE(SPDY3
, protocol_version());
2903 const size_t uncompressed_length
=
2904 GetSerializedLength(protocol_version(), &headers
);
2905 if (!enable_compression_
) {
2906 return uncompressed_length
;
2908 z_stream
* compressor
= GetHeaderCompressor();
2909 // Since we'll be performing lots of flushes when compressing the data,
2910 // zlib's lower bounds may be insufficient.
2911 return 2 * deflateBound(compressor
, uncompressed_length
);
2914 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size
) {
2915 DCHECK_GT(protocol_version(), SPDY3
);
2916 DCHECK_GT(size
, kMaxControlFrameSize
);
2917 size_t overflow
= size
- kMaxControlFrameSize
;
2918 size_t payload_size
= kMaxControlFrameSize
- GetContinuationMinimumSize();
2919 // This is ceiling(overflow/payload_size) using integer arithmetics.
2920 return (overflow
- 1) / payload_size
+ 1;
2923 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder
* builder
,
2924 const string
& hpack_encoding
,
2925 SpdyStreamId stream_id
,
2927 int padding_payload_len
) {
2930 if (type
== HEADERS
) {
2931 end_flag
= HEADERS_FLAG_END_HEADERS
;
2932 } else if (type
== PUSH_PROMISE
) {
2933 end_flag
= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2935 DLOG(FATAL
) << "CONTINUATION frames cannot be used with frame type "
2936 << FrameTypeToString(type
);
2939 // Write all the padding payload and as much of the data payload as possible
2940 // into the initial frame.
2941 size_t bytes_remaining
= 0;
2943 hpack_encoding
.size() -
2944 std::min(hpack_encoding
.size(),
2945 kMaxControlFrameSize
- builder
->length() - padding_payload_len
);
2946 builder
->WriteBytes(&hpack_encoding
[0],
2947 hpack_encoding
.size() - bytes_remaining
);
2948 if (padding_payload_len
> 0) {
2949 string padding
= string(padding_payload_len
, 0);
2950 builder
->WriteBytes(padding
.data(), padding
.length());
2952 if (bytes_remaining
> 0) {
2953 builder
->OverwriteLength(
2954 *this, kMaxControlFrameSize
- GetControlFrameHeaderSize());
2957 // Tack on CONTINUATION frames for the overflow.
2958 while (bytes_remaining
> 0) {
2959 size_t bytes_to_write
= std::min(
2960 bytes_remaining
, kMaxControlFrameSize
- GetContinuationMinimumSize());
2961 // Write CONTINUATION frame prefix.
2962 if (bytes_remaining
== bytes_to_write
) {
2965 builder
->BeginNewFrame(*this, CONTINUATION
, flags
, stream_id
);
2966 // Write payload fragment.
2967 builder
->WriteBytes(
2968 &hpack_encoding
[hpack_encoding
.size() - bytes_remaining
],
2970 bytes_remaining
-= bytes_to_write
;
2974 // The following compression setting are based on Brian Olson's analysis. See
2975 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2976 // for more details.
2977 #if defined(USE_SYSTEM_ZLIB)
2978 // System zlib is not expected to have workaround for http://crbug.com/139744,
2979 // so disable compression in that case.
2980 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2981 static const int kCompressorLevel
= 0;
2982 #else // !defined(USE_SYSTEM_ZLIB)
2983 static const int kCompressorLevel
= 9;
2984 #endif // !defined(USE_SYSTEM_ZLIB)
2985 static const int kCompressorWindowSizeInBits
= 11;
2986 static const int kCompressorMemLevel
= 1;
2988 z_stream
* SpdyFramer::GetHeaderCompressor() {
2989 if (header_compressor_
.get())
2990 return header_compressor_
.get(); // Already initialized.
2992 header_compressor_
.reset(new z_stream
);
2993 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
2995 int success
= deflateInit2(header_compressor_
.get(),
2998 kCompressorWindowSizeInBits
,
2999 kCompressorMemLevel
,
3000 Z_DEFAULT_STRATEGY
);
3001 if (success
== Z_OK
) {
3002 const char* dictionary
= (protocol_version() <= SPDY2
) ?
3003 kV2Dictionary
: kV3Dictionary
;
3004 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3005 kV2DictionarySize
: kV3DictionarySize
;
3006 success
= deflateSetDictionary(header_compressor_
.get(),
3007 reinterpret_cast<const Bytef
*>(dictionary
),
3010 if (success
!= Z_OK
) {
3011 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
3012 header_compressor_
.reset(NULL
);
3015 return header_compressor_
.get();
3018 z_stream
* SpdyFramer::GetHeaderDecompressor() {
3019 if (header_decompressor_
.get())
3020 return header_decompressor_
.get(); // Already initialized.
3022 header_decompressor_
.reset(new z_stream
);
3023 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
3025 int success
= inflateInit(header_decompressor_
.get());
3026 if (success
!= Z_OK
) {
3027 LOG(WARNING
) << "inflateInit failure: " << success
;
3028 header_decompressor_
.reset(NULL
);
3031 return header_decompressor_
.get();
3034 HpackEncoder
* SpdyFramer::GetHpackEncoder() {
3035 DCHECK_LT(SPDY3
, protocol_version());
3036 if (hpack_encoder_
.get() == nullptr) {
3037 hpack_encoder_
.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3039 return hpack_encoder_
.get();
3042 HpackDecoder
* SpdyFramer::GetHpackDecoder() {
3043 DCHECK_LT(SPDY3
, protocol_version());
3044 if (hpack_decoder_
.get() == nullptr) {
3045 hpack_decoder_
.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3047 return hpack_decoder_
.get();
3050 uint8
SpdyFramer::MapPriorityToWeight(SpdyPriority priority
) {
3051 const float kSteps
= 255.9f
/ 7.f
;
3052 return static_cast<uint8
>(kSteps
* (7.f
- priority
));
3055 SpdyPriority
SpdyFramer::MapWeightToPriority(uint8 weight
) {
3056 const float kSteps
= 255.9f
/ 7.f
;
3057 return static_cast<SpdyPriority
>(7.f
- weight
/ kSteps
);
3060 // Incrementally decompress the control frame's header block, feeding the
3061 // result to the visitor in chunks. Continue this until the visitor
3062 // indicates that it cannot process any more data, or (more commonly) we
3063 // run out of data to deliver.
3064 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3065 SpdyStreamId stream_id
,
3068 // Get a decompressor or set error.
3069 z_stream
* decomp
= GetHeaderDecompressor();
3070 if (decomp
== NULL
) {
3071 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
3072 set_error(SPDY_DECOMPRESS_FAILURE
);
3076 bool processed_successfully
= true;
3077 char buffer
[kHeaderDataChunkMaxSize
];
3079 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
3080 decomp
->avail_in
= len
;
3081 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3082 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3083 // reached this method successfully, stream_id should be nonzero.
3084 DCHECK_LT(0u, stream_id
);
3085 while (decomp
->avail_in
> 0 && processed_successfully
) {
3086 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
3087 decomp
->avail_out
= arraysize(buffer
);
3089 int rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3090 if (rv
== Z_NEED_DICT
) {
3091 const char* dictionary
= (protocol_version() <= SPDY2
) ? kV2Dictionary
3093 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3094 kV2DictionarySize
: kV3DictionarySize
;
3095 const DictionaryIds
& ids
= g_dictionary_ids
.Get();
3096 const uLong dictionary_id
= (protocol_version() <= SPDY2
) ?
3097 ids
.v2_dictionary_id
: ids
.v3_dictionary_id
;
3098 // Need to try again with the right dictionary.
3099 if (decomp
->adler
== dictionary_id
) {
3100 rv
= inflateSetDictionary(decomp
,
3101 reinterpret_cast<const Bytef
*>(dictionary
),
3104 rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3108 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3109 // without producing any output. The input is consumed and
3110 // buffered internally by zlib so we can detect this condition by
3111 // checking if avail_in is 0 after the call to inflate.
3112 bool input_exhausted
= ((rv
== Z_BUF_ERROR
) && (decomp
->avail_in
== 0));
3113 if ((rv
== Z_OK
) || input_exhausted
) {
3114 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
3115 if (decompressed_len
> 0) {
3116 processed_successfully
= visitor_
->OnControlFrameHeaderData(
3117 stream_id
, buffer
, decompressed_len
);
3119 if (!processed_successfully
) {
3120 // Assume that the problem was the header block was too large for the
3122 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3125 DLOG(WARNING
) << "inflate failure: " << rv
<< " " << len
;
3126 set_error(SPDY_DECOMPRESS_FAILURE
);
3127 processed_successfully
= false;
3130 return processed_successfully
;
3133 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3134 SpdyStreamId stream_id
, const char* data
, size_t len
) {
3135 bool read_successfully
= true;
3136 while (read_successfully
&& len
> 0) {
3137 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
3138 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
3140 data
+= bytes_to_deliver
;
3141 len
-= bytes_to_deliver
;
3142 if (!read_successfully
) {
3143 // Assume that the problem was the header block was too large for the
3145 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3148 return read_successfully
;
3151 void SpdyFramer::UpdateHeaderTableSizeSetting(uint32 value
) {
3152 header_table_size_bound_
= value
;
3153 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value
);
3154 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value
);
3157 // Return size bound of the header compression table.
3158 size_t SpdyFramer::header_table_size_bound() const {
3159 return header_table_size_bound_
;
3162 void SpdyFramer::SerializeHeaderBlockWithoutCompression(
3163 SpdyFrameBuilder
* builder
,
3164 const SpdyHeaderBlock
& header_block
) const {
3165 // Serialize number of headers.
3166 if (protocol_version() <= SPDY2
) {
3167 builder
->WriteUInt16(static_cast<uint16
>(header_block
.size()));
3169 builder
->WriteUInt32(header_block
.size());
3172 // Serialize each header.
3173 for (const auto& header
: header_block
) {
3174 if (protocol_version() <= SPDY2
) {
3175 builder
->WriteStringPiece16(header
.first
);
3176 builder
->WriteStringPiece16(header
.second
);
3178 builder
->WriteStringPiece32(header
.first
);
3179 builder
->WriteStringPiece32(header
.second
);
3184 void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder
* builder
,
3185 const SpdyFrameWithHeaderBlockIR
& frame
) {
3186 CHECK_GE(SPDY3
, protocol_version());
3187 if (!enable_compression_
) {
3188 return SerializeHeaderBlockWithoutCompression(builder
,
3189 frame
.header_block());
3192 // First build an uncompressed version to be fed into the compressor.
3193 const size_t uncompressed_len
=
3194 GetSerializedLength(protocol_version(), &(frame
.header_block()));
3195 SpdyFrameBuilder
uncompressed_builder(uncompressed_len
, protocol_version());
3196 SerializeHeaderBlockWithoutCompression(&uncompressed_builder
,
3197 frame
.header_block());
3198 scoped_ptr
<SpdyFrame
> uncompressed_payload(uncompressed_builder
.take());
3200 z_stream
* compressor
= GetHeaderCompressor();
3202 LOG(DFATAL
) << "Could not obtain compressor.";
3205 // Create an output frame.
3206 // Since we'll be performing lots of flushes when compressing the data,
3207 // zlib's lower bounds may be insufficient.
3209 // TODO(akalin): Avoid the duplicate calculation with
3210 // GetSerializedLength(const SpdyHeaderBlock&).
3211 const int compressed_max_size
=
3212 2 * deflateBound(compressor
, uncompressed_len
);
3214 // TODO(phajdan.jr): Clean up after we no longer need
3215 // to workaround http://crbug.com/139744.
3216 #if defined(USE_SYSTEM_ZLIB)
3217 compressor
->next_in
= reinterpret_cast<Bytef
*>(uncompressed_payload
->data());
3218 compressor
->avail_in
= uncompressed_len
;
3219 #endif // defined(USE_SYSTEM_ZLIB)
3220 compressor
->next_out
= reinterpret_cast<Bytef
*>(
3221 builder
->GetWritableBuffer(compressed_max_size
));
3222 compressor
->avail_out
= compressed_max_size
;
3224 // TODO(phajdan.jr): Clean up after we no longer need
3225 // to workaround http://crbug.com/139744.
3226 #if defined(USE_SYSTEM_ZLIB)
3227 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
3228 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
3229 // This shouldn't happen, right?
3230 LOG(WARNING
) << "deflate failure: " << rv
;
3231 // TODO(akalin): Upstream this return.
3235 WriteHeaderBlockToZ(&frame
.header_block(), compressor
);
3236 #endif // defined(USE_SYSTEM_ZLIB)
3238 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
3239 builder
->Seek(compressed_size
);
3240 builder
->RewriteLength(*this);