1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_framer.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/stats_counters.h"
10 #include "base/third_party/valgrind/memcheck.h"
11 #include "net/spdy/spdy_frame_builder.h"
12 #include "net/spdy/spdy_frame_reader.h"
13 #include "net/spdy/spdy_bitmasks.h"
14 #include "third_party/zlib/zlib.h"
16 using base::StringPiece
;
24 // Compute the id of our dictionary so that we know we're using the
25 // right one when asked for it.
26 uLong
CalculateDictionaryId(const char* dictionary
,
27 const size_t dictionary_size
) {
28 uLong initial_value
= adler32(0L, Z_NULL
, 0);
29 return adler32(initial_value
,
30 reinterpret_cast<const Bytef
*>(dictionary
),
34 // Check to see if the name and value of a cookie are both empty.
35 bool IsCookieEmpty(const base::StringPiece
& cookie
) {
36 if (cookie
.size() == 0) {
39 size_t pos
= cookie
.find('=');
40 if (pos
== base::StringPiece::npos
) {
43 // Ignore leading whitespaces of cookie value.
44 size_t value_start
= pos
+ 1;
45 for (; value_start
< cookie
.size(); value_start
++) {
46 if (!(cookie
[value_start
] == ' ' || cookie
[value_start
] == '\t')) {
50 return (pos
== 0) && ((cookie
.size() - value_start
) == 0);
53 struct DictionaryIds
{
55 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary
, kV2DictionarySize
)),
56 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary
, kV3DictionarySize
))
58 const uLong v2_dictionary_id
;
59 const uLong v3_dictionary_id
;
62 // Adler ID for the SPDY header compressor dictionaries. Note that they are
63 // initialized lazily to avoid static initializers.
64 base::LazyInstance
<DictionaryIds
>::Leaky g_dictionary_ids
;
66 // Used to indicate no flags in a SPDY flags field.
67 const uint8 kNoFlags
= 0;
69 // Wire sizes of priority payloads.
70 const size_t kPriorityDependencyPayloadSize
= 4;
71 const size_t kPriorityWeightPayloadSize
= 1;
73 // Wire size of pad length field.
74 const size_t kPadLengthFieldSize
= 1;
78 const SpdyStreamId
SpdyFramer::kInvalidStream
= static_cast<SpdyStreamId
>(-1);
79 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
80 // We fragment sent control frames at smaller payload boundaries.
81 const size_t SpdyFramer::kMaxControlFrameSize
= 1024;
82 // The size of the control frame buffer. Must be >= the minimum size of the
83 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
84 // calculation details.
85 const size_t SpdyFramer::kControlFrameBufferSize
= 19;
87 #ifdef DEBUG_SPDY_STATE_CHANGES
88 #define CHANGE_STATE(newstate) \
90 DVLOG(1) << "Changing state from: " \
91 << StateToString(state_) \
92 << " to " << StateToString(newstate) << "\n"; \
93 DCHECK(state_ != SPDY_ERROR); \
94 DCHECK_EQ(previous_state_, state_); \
95 previous_state_ = state_; \
99 #define CHANGE_STATE(newstate) \
101 DCHECK(state_ != SPDY_ERROR); \
102 DCHECK_EQ(previous_state_, state_); \
103 previous_state_ = state_; \
108 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(
109 SpdyMajorVersion version
, uint32 wire
) {
110 if (version
< SPDY3
) {
111 ConvertFlagsAndIdForSpdy2(&wire
);
113 return SettingsFlagsAndId(ntohl(wire
) >> 24, ntohl(wire
) & 0x00ffffff);
116 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags
, uint32 id
)
117 : flags_(flags
), id_(id
& 0x00ffffff) {
118 LOG_IF(DFATAL
, id
> (1u << 24)) << "SPDY setting ID too large: " << id
;
121 uint32
SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version
)
123 uint32 wire
= htonl(id_
& 0x00ffffff) | htonl(flags_
<< 24);
124 if (version
< SPDY3
) {
125 ConvertFlagsAndIdForSpdy2(&wire
);
130 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
131 // This method is used to preserve buggy behavior and works on both
132 // little-endian and big-endian hosts.
133 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
134 // as well as vice versa).
135 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32
* val
) {
136 uint8
* wire_array
= reinterpret_cast<uint8
*>(val
);
137 std::swap(wire_array
[0], wire_array
[3]);
138 std::swap(wire_array
[1], wire_array
[2]);
141 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
142 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
144 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data
,
149 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
150 const char* rst_stream_data
,
155 SpdyFramer::SpdyFramer(SpdyMajorVersion version
)
156 : current_frame_buffer_(new char[kControlFrameBufferSize
]),
157 enable_compression_(true),
159 debug_visitor_(NULL
),
160 display_protocol_("SPDY"),
161 spdy_version_(version
),
162 syn_frame_processed_(false),
163 probable_http_response_(false),
164 expect_continuation_(0),
165 end_stream_when_done_(false) {
166 DCHECK_GE(spdy_version_
, SPDY_MIN_VERSION
);
167 DCHECK_LE(spdy_version_
, SPDY_MAX_VERSION
);
168 DCHECK_LE(kMaxControlFrameSize
,
169 SpdyConstants::GetFrameMaximumSize(spdy_version_
) +
170 SpdyConstants::GetControlFrameHeaderSize(spdy_version_
));
174 SpdyFramer::~SpdyFramer() {
175 if (header_compressor_
.get()) {
176 deflateEnd(header_compressor_
.get());
178 if (header_decompressor_
.get()) {
179 inflateEnd(header_decompressor_
.get());
183 void SpdyFramer::Reset() {
185 previous_state_
= SPDY_RESET
;
186 error_code_
= SPDY_NO_ERROR
;
187 remaining_data_length_
= 0;
188 remaining_control_header_
= 0;
189 current_frame_buffer_length_
= 0;
190 current_frame_type_
= DATA
;
191 current_frame_flags_
= 0;
192 current_frame_length_
= 0;
193 current_frame_stream_id_
= kInvalidStream
;
194 settings_scratch_
.Reset();
195 altsvc_scratch_
.Reset();
196 remaining_padding_payload_length_
= 0;
199 size_t SpdyFramer::GetDataFrameMinimumSize() const {
200 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
203 // Size, in bytes, of the control frame header.
204 size_t SpdyFramer::GetControlFrameHeaderSize() const {
205 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
208 size_t SpdyFramer::GetSynStreamMinimumSize() const {
209 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
211 if (protocol_version() <= SPDY3
) {
213 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
214 // + 1 (unused, was credential slot)
215 return GetControlFrameHeaderSize() + 10;
217 return GetControlFrameHeaderSize() +
218 kPriorityDependencyPayloadSize
+
219 kPriorityWeightPayloadSize
;
223 size_t SpdyFramer::GetSynReplyMinimumSize() const {
224 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
226 size_t size
= GetControlFrameHeaderSize();
227 if (protocol_version() <= SPDY3
) {
229 // control frame header + 4 (stream IDs)
233 // In SPDY 2, there were 2 unused bytes before payload.
234 if (protocol_version() < SPDY3
) {
241 size_t SpdyFramer::GetRstStreamMinimumSize() const {
242 // Size, in bytes, of a RST_STREAM frame.
243 if (protocol_version() <= SPDY3
) {
245 // control frame header + 4 (stream id) + 4 (status code)
246 return GetControlFrameHeaderSize() + 8;
249 // frame prefix + 4 (status code)
250 return GetControlFrameHeaderSize() + 4;
254 size_t SpdyFramer::GetSettingsMinimumSize() const {
255 // Size, in bytes, of a SETTINGS frame not including the IDs and values
256 // from the variable-length value block. Calculated as:
257 // control frame header + 4 (number of ID/value pairs)
258 if (protocol_version() <= SPDY3
) {
259 return GetControlFrameHeaderSize() + 4;
261 return GetControlFrameHeaderSize();
265 size_t SpdyFramer::GetPingSize() const {
266 // Size, in bytes, of this PING frame.
267 if (protocol_version() <= SPDY3
) {
269 // control frame header + 4 (id)
270 return GetControlFrameHeaderSize() + 4;
273 // control frame header + 8 (id)
274 return GetControlFrameHeaderSize() + 8;
278 size_t SpdyFramer::GetGoAwayMinimumSize() const {
279 // Size, in bytes, of this GOAWAY frame. Calculated as:
280 // 1. Control frame header size
281 size_t size
= GetControlFrameHeaderSize();
283 // 2. Last good stream id (4 bytes)
286 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
287 if (protocol_version() >= SPDY3
) {
294 size_t SpdyFramer::GetHeadersMinimumSize() const {
295 // Size, in bytes, of a HEADERS frame not including the variable-length
297 size_t size
= GetControlFrameHeaderSize();
298 if (protocol_version() <= SPDY3
) {
300 // control frame header + 4 (stream IDs)
304 // In SPDY 2, there were 2 unused bytes before payload.
305 if (protocol_version() <= SPDY2
) {
312 size_t SpdyFramer::GetWindowUpdateSize() const {
313 // Size, in bytes, of a WINDOW_UPDATE frame.
314 if (protocol_version() <= SPDY3
) {
316 // control frame header + 4 (stream id) + 4 (delta)
317 return GetControlFrameHeaderSize() + 8;
320 // frame prefix + 4 (delta)
321 return GetControlFrameHeaderSize() + 4;
325 size_t SpdyFramer::GetBlockedSize() const {
326 DCHECK_LT(SPDY3
, protocol_version());
327 // Size, in bytes, of a BLOCKED frame.
328 // The BLOCKED frame has no payload beyond the control frame header.
329 return GetControlFrameHeaderSize();
332 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
333 DCHECK_LT(SPDY3
, protocol_version());
334 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
335 // Calculated as frame prefix + 4 (promised stream id).
336 return GetControlFrameHeaderSize() + 4;
339 size_t SpdyFramer::GetContinuationMinimumSize() const {
340 // Size, in bytes, of a CONTINUATION frame not including the variable-length
341 // headers fragments.
342 return GetControlFrameHeaderSize();
345 size_t SpdyFramer::GetAltSvcMinimumSize() const {
346 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
347 // (optional) Origin fields, all of which can vary in length.
348 // Note that this gives a lower bound on the frame size rather than a true
349 // minimum; the actual frame should always be larger than this.
350 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
351 // + 1 (pid_len) + 1 (host_len).
352 return GetControlFrameHeaderSize() + 9;
355 size_t SpdyFramer::GetPrioritySize() const {
356 // Size, in bytes, of a PRIORITY frame.
357 return GetControlFrameHeaderSize() +
358 kPriorityDependencyPayloadSize
+
359 kPriorityWeightPayloadSize
;
362 size_t SpdyFramer::GetFrameMinimumSize() const {
363 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
366 size_t SpdyFramer::GetFrameMaximumSize() const {
367 return SpdyConstants::GetFrameMaximumSize(protocol_version());
370 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
371 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
374 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type
) const {
375 return SpdyConstants::GetPrefixLength(type
, protocol_version());
378 const char* SpdyFramer::StateToString(int state
) {
382 case SPDY_AUTO_RESET
:
386 case SPDY_READING_COMMON_HEADER
:
387 return "READING_COMMON_HEADER";
388 case SPDY_CONTROL_FRAME_PAYLOAD
:
389 return "CONTROL_FRAME_PAYLOAD";
390 case SPDY_READ_DATA_FRAME_PADDING_LENGTH
:
391 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
392 case SPDY_CONSUME_PADDING
:
393 return "SPDY_CONSUME_PADDING";
394 case SPDY_IGNORE_REMAINING_PAYLOAD
:
395 return "IGNORE_REMAINING_PAYLOAD";
396 case SPDY_FORWARD_STREAM_FRAME
:
397 return "FORWARD_STREAM_FRAME";
398 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
399 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
400 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
401 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
402 case SPDY_GOAWAY_FRAME_PAYLOAD
:
403 return "SPDY_GOAWAY_FRAME_PAYLOAD";
404 case SPDY_RST_STREAM_FRAME_PAYLOAD
:
405 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
406 case SPDY_SETTINGS_FRAME_PAYLOAD
:
407 return "SPDY_SETTINGS_FRAME_PAYLOAD";
408 case SPDY_ALTSVC_FRAME_PAYLOAD
:
409 return "SPDY_ALTSVC_FRAME_PAYLOAD";
411 return "UNKNOWN_STATE";
414 void SpdyFramer::set_error(SpdyError error
) {
417 // These values will usually get reset once we come to the end
418 // of a header block, but if we run into an error that
419 // might not happen, so reset them here.
420 expect_continuation_
= 0;
421 end_stream_when_done_
= false;
423 CHANGE_STATE(SPDY_ERROR
);
424 visitor_
->OnError(this);
427 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
428 switch (error_code
) {
431 case SPDY_INVALID_CONTROL_FRAME
:
432 return "INVALID_CONTROL_FRAME";
433 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
434 return "CONTROL_PAYLOAD_TOO_LARGE";
435 case SPDY_ZLIB_INIT_FAILURE
:
436 return "ZLIB_INIT_FAILURE";
437 case SPDY_UNSUPPORTED_VERSION
:
438 return "UNSUPPORTED_VERSION";
439 case SPDY_DECOMPRESS_FAILURE
:
440 return "DECOMPRESS_FAILURE";
441 case SPDY_COMPRESS_FAILURE
:
442 return "COMPRESS_FAILURE";
443 case SPDY_INVALID_DATA_FRAME_FLAGS
:
444 return "SPDY_INVALID_DATA_FRAME_FLAGS";
445 case SPDY_INVALID_CONTROL_FRAME_FLAGS
:
446 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
447 case SPDY_UNEXPECTED_FRAME
:
448 return "UNEXPECTED_FRAME";
450 return "UNKNOWN_ERROR";
453 const char* SpdyFramer::StatusCodeToString(int status_code
) {
454 switch (status_code
) {
455 case RST_STREAM_INVALID
:
457 case RST_STREAM_PROTOCOL_ERROR
:
458 return "PROTOCOL_ERROR";
459 case RST_STREAM_INVALID_STREAM
:
460 return "INVALID_STREAM";
461 case RST_STREAM_REFUSED_STREAM
:
462 return "REFUSED_STREAM";
463 case RST_STREAM_UNSUPPORTED_VERSION
:
464 return "UNSUPPORTED_VERSION";
465 case RST_STREAM_CANCEL
:
467 case RST_STREAM_INTERNAL_ERROR
:
468 return "INTERNAL_ERROR";
469 case RST_STREAM_FLOW_CONTROL_ERROR
:
470 return "FLOW_CONTROL_ERROR";
471 case RST_STREAM_STREAM_IN_USE
:
472 return "STREAM_IN_USE";
473 case RST_STREAM_STREAM_ALREADY_CLOSED
:
474 return "STREAM_ALREADY_CLOSED";
475 case RST_STREAM_INVALID_CREDENTIALS
:
476 return "INVALID_CREDENTIALS";
477 case RST_STREAM_FRAME_TOO_LARGE
:
478 return "FRAME_TOO_LARGE";
479 case RST_STREAM_CONNECT_ERROR
:
480 return "CONNECT_ERROR";
481 case RST_STREAM_ENHANCE_YOUR_CALM
:
482 return "ENHANCE_YOUR_CALM";
483 case RST_STREAM_INADEQUATE_SECURITY
:
484 return "INADEQUATE_SECURITY";
485 case RST_STREAM_HTTP_1_1_REQUIRED
:
486 return "HTTP_1_1_REQUIRED";
488 return "UNKNOWN_STATUS";
491 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type
) {
510 return "WINDOW_UPDATE";
514 return "PUSH_PROMISE";
516 return "CONTINUATION";
524 return "UNKNOWN_CONTROL_TYPE";
527 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
531 size_t original_len
= len
;
533 previous_state_
= state_
;
538 case SPDY_AUTO_RESET
:
542 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
546 case SPDY_READING_COMMON_HEADER
: {
547 size_t bytes_read
= ProcessCommonHeader(data
, len
);
553 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
554 // Control frames that contain header blocks
555 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
556 // take a different path through the state machine - they
558 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
559 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
561 // SETTINGS frames take a slightly modified route:
562 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
563 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
565 // All other control frames will use the alternate route directly to
566 // SPDY_CONTROL_FRAME_PAYLOAD
567 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
573 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
574 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
580 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
581 int bytes_read
= ProcessControlFrameHeaderBlock(
582 data
, len
, protocol_version() > SPDY3
);
588 case SPDY_RST_STREAM_FRAME_PAYLOAD
: {
589 size_t bytes_read
= ProcessRstStreamFramePayload(data
, len
);
595 case SPDY_GOAWAY_FRAME_PAYLOAD
: {
596 size_t bytes_read
= ProcessGoAwayFramePayload(data
, len
);
602 case SPDY_ALTSVC_FRAME_PAYLOAD
: {
603 size_t bytes_read
= ProcessAltSvcFramePayload(data
, len
);
609 case SPDY_CONTROL_FRAME_PAYLOAD
: {
610 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
616 case SPDY_READ_DATA_FRAME_PADDING_LENGTH
: {
617 size_t bytes_read
= ProcessDataFramePaddingLength(data
, len
);
623 case SPDY_CONSUME_PADDING
: {
624 size_t bytes_read
= ProcessFramePadding(data
, len
);
630 case SPDY_IGNORE_REMAINING_PAYLOAD
: {
631 size_t bytes_read
= ProcessIgnoredControlFramePayload(/*data,*/ len
);
637 case SPDY_FORWARD_STREAM_FRAME
: {
638 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
645 LOG(DFATAL
) << "Invalid value for " << display_protocol_
646 << " framer state: " << state_
;
647 // This ensures that we don't infinite-loop if state_ gets an
648 // invalid value somehow, such as due to a SpdyFramer getting deleted
649 // from a callback it calls.
652 } while (state_
!= previous_state_
);
654 DCHECK(len
== 0 || state_
== SPDY_ERROR
);
655 if (current_frame_buffer_length_
== 0 &&
656 remaining_data_length_
== 0 &&
657 remaining_control_header_
== 0) {
658 DCHECK(state_
== SPDY_RESET
|| state_
== SPDY_ERROR
)
659 << "State: " << StateToString(state_
);
662 return original_len
- len
;
665 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
666 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
668 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
670 size_t original_len
= len
;
672 // Update current frame buffer as needed.
673 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
674 size_t bytes_desired
=
675 GetControlFrameHeaderSize() - current_frame_buffer_length_
;
676 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
679 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
680 // Not enough information to do anything meaningful.
681 return original_len
- len
;
684 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
685 // when processing DATA frames below.
686 scoped_ptr
<SpdyFrameReader
> reader(
687 new SpdyFrameReader(current_frame_buffer_
.get(),
688 current_frame_buffer_length_
));
690 bool is_control_frame
= false;
692 uint16 control_frame_type_field
=
693 SpdyConstants::DataFrameType(protocol_version());
694 // ProcessControlFrameHeader() will set current_frame_type_ to the
695 // correct value if this is a valid control frame.
696 current_frame_type_
= DATA
;
697 if (protocol_version() <= SPDY3
) {
699 bool successful_read
= reader
->ReadUInt16(&version
);
700 DCHECK(successful_read
);
701 is_control_frame
= (version
& kControlFlagMask
) != 0;
702 version
&= ~kControlFlagMask
; // Only valid for control frames.
703 if (is_control_frame
) {
704 // We check version before we check validity: version can never be
705 // 'invalid', it can only be unsupported.
706 if (version
< SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION
) ||
707 version
> SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION
) ||
708 SpdyConstants::ParseMajorVersion(version
) != protocol_version()) {
709 // Version does not match the version the framer was initialized with.
710 DVLOG(1) << "Unsupported SPDY version "
712 << " (expected " << protocol_version() << ")";
713 set_error(SPDY_UNSUPPORTED_VERSION
);
716 // We check control_frame_type_field's validity in
717 // ProcessControlFrameHeader().
718 successful_read
= reader
->ReadUInt16(&control_frame_type_field
);
721 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
723 DCHECK(successful_read
);
725 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
726 DCHECK(successful_read
);
728 uint32 length_field
= 0;
729 successful_read
= reader
->ReadUInt24(&length_field
);
730 DCHECK(successful_read
);
731 remaining_data_length_
= length_field
;
732 current_frame_length_
= remaining_data_length_
+ reader
->GetBytesConsumed();
734 uint32 length_field
= 0;
735 bool successful_read
= reader
->ReadUInt24(&length_field
);
736 DCHECK(successful_read
);
738 uint8 control_frame_type_field_uint8
=
739 SpdyConstants::DataFrameType(protocol_version());
740 successful_read
= reader
->ReadUInt8(&control_frame_type_field_uint8
);
741 DCHECK(successful_read
);
742 // We check control_frame_type_field's validity in
743 // ProcessControlFrameHeader().
744 control_frame_type_field
= control_frame_type_field_uint8
;
745 is_control_frame
= (protocol_version() > SPDY3
) ?
746 control_frame_type_field
!=
747 SpdyConstants::SerializeFrameType(protocol_version(), DATA
) :
748 control_frame_type_field
!= 0;
750 if (is_control_frame
) {
751 current_frame_length_
= length_field
+ GetControlFrameHeaderSize();
753 current_frame_length_
= length_field
+ GetDataFrameMinimumSize();
756 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
757 DCHECK(successful_read
);
759 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
760 DCHECK(successful_read
);
762 remaining_data_length_
= current_frame_length_
- reader
->GetBytesConsumed();
764 // Before we accept a DATA frame, we need to make sure we're not in the
765 // middle of processing a header block.
766 const bool is_continuation_frame
= (control_frame_type_field
==
767 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION
));
768 if ((expect_continuation_
!= 0) != is_continuation_frame
) {
769 if (expect_continuation_
!= 0) {
770 DLOG(ERROR
) << "The framer was expecting to receive a CONTINUATION "
771 << "frame, but instead received frame type "
772 << control_frame_type_field
;
774 DLOG(ERROR
) << "The framer received an unexpected CONTINUATION frame.";
776 set_error(SPDY_UNEXPECTED_FRAME
);
777 return original_len
- len
;
780 DCHECK_EQ(is_control_frame
? GetControlFrameHeaderSize()
781 : GetDataFrameMinimumSize(),
782 reader
->GetBytesConsumed());
783 DCHECK_EQ(current_frame_length_
,
784 remaining_data_length_
+ reader
->GetBytesConsumed());
786 // This is just a sanity check for help debugging early frame errors.
787 if (remaining_data_length_
> 1000000u) {
788 // The strncmp for 5 is safe because we only hit this point if we
789 // have kMinCommonHeader (8) bytes
790 if (!syn_frame_processed_
&&
791 strncmp(current_frame_buffer_
.get(), "HTTP/", 5) == 0) {
792 LOG(WARNING
) << "Unexpected HTTP response to " << display_protocol_
794 probable_http_response_
= true;
796 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
797 << " session is likely corrupt.";
801 // if we're here, then we have the common header all received.
802 if (!is_control_frame
) {
803 if (protocol_version() > SPDY3
) {
804 // Catch bogus tests sending oversized DATA frames.
805 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_
)
806 << "DATA frame too large for SPDY >= 4.";
809 uint8 valid_data_flags
= 0;
810 if (protocol_version() > SPDY3
) {
812 DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
| DATA_FLAG_PADDED
;
814 valid_data_flags
= DATA_FLAG_FIN
;
817 if (current_frame_flags_
& ~valid_data_flags
) {
818 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
820 visitor_
->OnDataFrameHeader(current_frame_stream_id_
,
821 remaining_data_length_
,
822 current_frame_flags_
& DATA_FLAG_FIN
);
823 if (remaining_data_length_
> 0) {
824 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH
);
827 if (current_frame_flags_
& DATA_FLAG_FIN
) {
828 visitor_
->OnStreamFrameData(
829 current_frame_stream_id_
, NULL
, 0, true);
831 CHANGE_STATE(SPDY_AUTO_RESET
);
835 ProcessControlFrameHeader(control_frame_type_field
);
838 return original_len
- len
;
841 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field
) {
842 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
843 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_
);
845 // TODO(mlavan): Either remove credential frames from the code entirely,
846 // or add them to parsing + serialization methods for SPDY3.
847 // Early detection of deprecated frames that we ignore.
848 if (protocol_version() <= SPDY3
) {
849 if (control_frame_type_field
== CREDENTIAL
) {
850 current_frame_type_
= CREDENTIAL
;
851 DCHECK_EQ(SPDY3
, protocol_version());
852 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
853 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
858 if (!SpdyConstants::IsValidFrameType(protocol_version(),
859 control_frame_type_field
)) {
860 if (protocol_version() <= SPDY3
) {
861 DLOG(WARNING
) << "Invalid control frame type " << control_frame_type_field
862 << " (protocol version: " << protocol_version() << ")";
863 set_error(SPDY_INVALID_CONTROL_FRAME
);
866 // In HTTP2 we ignore unknown frame types for extensibility, as long as
867 // the rest of the control frame header is valid.
868 // We rely on the visitor to check validity of current_frame_stream_id_.
869 bool valid_stream
= visitor_
->OnUnknownFrame(current_frame_stream_id_
,
870 control_frame_type_field
);
872 DVLOG(1) << "Ignoring unknown frame type.";
873 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
875 // Report an invalid frame error and close the stream if the
876 // stream_id is not valid.
877 DLOG(WARNING
) << "Unknown control frame type "
878 << control_frame_type_field
879 << " received on invalid stream "
880 << current_frame_stream_id_
;
881 set_error(SPDY_INVALID_CONTROL_FRAME
);
887 current_frame_type_
= SpdyConstants::ParseFrameType(protocol_version(),
888 control_frame_type_field
);
890 // Do some sanity checking on the control frame sizes and flags.
891 switch (current_frame_type_
) {
893 if (current_frame_length_
< GetSynStreamMinimumSize()) {
894 set_error(SPDY_INVALID_CONTROL_FRAME
);
895 } else if (current_frame_flags_
&
896 ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
897 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
901 if (current_frame_length_
< GetSynReplyMinimumSize()) {
902 set_error(SPDY_INVALID_CONTROL_FRAME
);
903 } else if (current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
904 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
908 // For SPDY versions < 4, the header has a fixed length.
909 // For SPDY version 4 and up, the RST_STREAM frame may include optional
910 // opaque data, so we only have a lower limit on the frame size.
911 if ((current_frame_length_
!= GetRstStreamMinimumSize() &&
912 protocol_version() <= SPDY3
) ||
913 (current_frame_length_
< GetRstStreamMinimumSize() &&
914 protocol_version() > SPDY3
)) {
915 set_error(SPDY_INVALID_CONTROL_FRAME
);
916 } else if (current_frame_flags_
!= 0) {
917 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
922 // Make sure that we have an integral number of 8-byte key/value pairs,
923 // plus a 4-byte length field in SPDY3 and below.
924 size_t values_prefix_size
= (protocol_version() <= SPDY3
? 4 : 0);
925 // Size of each key/value pair in bytes.
926 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
927 if (current_frame_length_
< GetSettingsMinimumSize() ||
928 (current_frame_length_
- GetControlFrameHeaderSize())
929 % setting_size
!= values_prefix_size
) {
930 DLOG(WARNING
) << "Invalid length for SETTINGS frame: "
931 << current_frame_length_
;
932 set_error(SPDY_INVALID_CONTROL_FRAME
);
933 } else if (protocol_version() <= SPDY3
&&
934 current_frame_flags_
&
935 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
936 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
937 } else if (protocol_version() > SPDY3
&&
938 current_frame_flags_
& ~SETTINGS_FLAG_ACK
) {
939 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
940 } else if (protocol_version() > SPDY3
&&
941 current_frame_flags_
& SETTINGS_FLAG_ACK
&&
942 current_frame_length_
> GetSettingsMinimumSize()) {
943 set_error(SPDY_INVALID_CONTROL_FRAME
);
948 if (current_frame_length_
!= GetPingSize()) {
949 set_error(SPDY_INVALID_CONTROL_FRAME
);
950 } else if ((protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) ||
951 (current_frame_flags_
& ~PING_FLAG_ACK
)) {
952 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
957 // For SPDY version < 4, there are only mandatory fields and the header
958 // has a fixed length. For SPDY version >= 4, optional opaque data may
959 // be appended to the GOAWAY frame, thus there is only a minimal length
961 if ((current_frame_length_
!= GetGoAwayMinimumSize() &&
962 protocol_version() <= SPDY3
) ||
963 (current_frame_length_
< GetGoAwayMinimumSize() &&
964 protocol_version() > SPDY3
)) {
965 set_error(SPDY_INVALID_CONTROL_FRAME
);
966 } else if (current_frame_flags_
!= 0) {
967 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
973 size_t min_size
= GetHeadersMinimumSize();
974 if (protocol_version() > SPDY3
&&
975 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
)) {
978 if (current_frame_length_
< min_size
) {
979 // TODO(mlavan): check here for HEADERS with no payload?
980 // (not allowed in SPDY4)
981 set_error(SPDY_INVALID_CONTROL_FRAME
);
982 } else if (protocol_version() <= SPDY3
&&
983 current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
984 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
985 } else if (protocol_version() > SPDY3
&&
986 current_frame_flags_
&
987 ~(CONTROL_FLAG_FIN
| HEADERS_FLAG_PRIORITY
|
988 HEADERS_FLAG_END_HEADERS
| HEADERS_FLAG_END_SEGMENT
|
989 HEADERS_FLAG_PADDED
)) {
990 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
995 if (current_frame_length_
!= GetWindowUpdateSize()) {
996 set_error(SPDY_INVALID_CONTROL_FRAME
);
997 } else if (current_frame_flags_
!= 0) {
998 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1002 if (current_frame_length_
!= GetBlockedSize() ||
1003 protocol_version() <= SPDY3
) {
1004 set_error(SPDY_INVALID_CONTROL_FRAME
);
1005 } else if (current_frame_flags_
!= 0) {
1006 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1010 if (current_frame_length_
< GetPushPromiseMinimumSize()) {
1011 set_error(SPDY_INVALID_CONTROL_FRAME
);
1012 } else if (protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) {
1013 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1014 } else if (protocol_version() > SPDY3
&&
1015 current_frame_flags_
&
1016 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
1017 HEADERS_FLAG_PADDED
)) {
1018 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1022 if (current_frame_length_
< GetContinuationMinimumSize() ||
1023 protocol_version() <= SPDY3
) {
1024 set_error(SPDY_INVALID_CONTROL_FRAME
);
1025 } else if (current_frame_flags_
& ~HEADERS_FLAG_END_HEADERS
) {
1026 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1030 if (current_frame_length_
<= GetAltSvcMinimumSize()) {
1031 set_error(SPDY_INVALID_CONTROL_FRAME
);
1032 } else if (current_frame_flags_
!= 0) {
1033 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1037 if (current_frame_length_
!= GetPrioritySize() ||
1038 protocol_version() <= SPDY3
) {
1039 set_error(SPDY_INVALID_CONTROL_FRAME
);
1040 } else if (current_frame_flags_
!= 0) {
1041 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1045 LOG(WARNING
) << "Valid " << display_protocol_
1046 << " control frame with unhandled type: "
1047 << current_frame_type_
;
1048 // This branch should be unreachable because of the frame type bounds
1049 // check above. However, we DLOG(FATAL) here in an effort to painfully
1050 // club the head of the developer who failed to keep this file in sync
1051 // with spdy_protocol.h.
1053 set_error(SPDY_INVALID_CONTROL_FRAME
);
1057 if (state_
== SPDY_ERROR
) {
1061 if (current_frame_length_
>
1062 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1063 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1064 DLOG(WARNING
) << "Received control frame with way too big of a payload: "
1065 << current_frame_length_
;
1066 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1070 if (current_frame_type_
== GOAWAY
) {
1071 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD
);
1075 if (current_frame_type_
== RST_STREAM
) {
1076 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD
);
1080 if (current_frame_type_
== ALTSVC
) {
1081 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD
);
1084 // Determine the frame size without variable-length data.
1085 int32 frame_size_without_variable_data
;
1086 switch (current_frame_type_
) {
1088 syn_frame_processed_
= true;
1089 frame_size_without_variable_data
= GetSynStreamMinimumSize();
1092 syn_frame_processed_
= true;
1093 frame_size_without_variable_data
= GetSynReplyMinimumSize();
1096 frame_size_without_variable_data
= GetSettingsMinimumSize();
1099 frame_size_without_variable_data
= GetHeadersMinimumSize();
1100 if (protocol_version() > SPDY3
) {
1101 if (current_frame_flags_
& HEADERS_FLAG_PADDED
) {
1102 frame_size_without_variable_data
+= kPadLengthFieldSize
;
1104 if (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1105 frame_size_without_variable_data
+=
1106 kPriorityDependencyPayloadSize
+
1107 kPriorityWeightPayloadSize
;
1112 frame_size_without_variable_data
= GetPushPromiseMinimumSize();
1113 if (protocol_version() > SPDY3
&&
1114 current_frame_flags_
& PUSH_PROMISE_FLAG_PADDED
) {
1115 frame_size_without_variable_data
+= kPadLengthFieldSize
;
1119 frame_size_without_variable_data
= GetContinuationMinimumSize();
1122 frame_size_without_variable_data
= -1;
1126 if ((frame_size_without_variable_data
== -1) &&
1127 (current_frame_length_
> kControlFrameBufferSize
)) {
1128 // We should already be in an error state. Double-check.
1129 DCHECK_EQ(SPDY_ERROR
, state_
);
1130 if (state_
!= SPDY_ERROR
) {
1131 LOG(DFATAL
) << display_protocol_
1132 << " control frame buffer too small for fixed-length frame.";
1133 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1138 if (frame_size_without_variable_data
> 0) {
1139 // We have a control frame with a header block. We need to parse the
1140 // remainder of the control frame's header before we can parse the header
1141 // block. The start of the header block varies with the control type.
1142 DCHECK_GE(frame_size_without_variable_data
,
1143 static_cast<int32
>(current_frame_buffer_length_
));
1144 remaining_control_header_
= frame_size_without_variable_data
-
1145 current_frame_buffer_length_
;
1147 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
1151 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
1154 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
1156 size_t bytes_to_read
= std::min(*len
, max_bytes
);
1157 if (bytes_to_read
> 0) {
1158 DCHECK_GE(kControlFrameBufferSize
,
1159 current_frame_buffer_length_
+ bytes_to_read
);
1160 memcpy(current_frame_buffer_
.get() + current_frame_buffer_length_
,
1163 current_frame_buffer_length_
+= bytes_to_read
;
1164 *data
+= bytes_to_read
;
1165 *len
-= bytes_to_read
;
1167 return bytes_to_read
;
1170 size_t SpdyFramer::GetSerializedLength(
1171 const SpdyMajorVersion spdy_version
,
1172 const SpdyHeaderBlock
* headers
) {
1173 const size_t num_name_value_pairs_size
1174 = (spdy_version
< SPDY3
) ? sizeof(uint16
) : sizeof(uint32
);
1175 const size_t length_of_name_size
= num_name_value_pairs_size
;
1176 const size_t length_of_value_size
= num_name_value_pairs_size
;
1178 size_t total_length
= num_name_value_pairs_size
;
1179 for (SpdyHeaderBlock::const_iterator it
= headers
->begin();
1180 it
!= headers
->end();
1182 // We add space for the length of the name and the length of the value as
1183 // well as the length of the name and the length of the value.
1184 total_length
+= length_of_name_size
+ it
->first
.size() +
1185 length_of_value_size
+ it
->second
.size();
1187 return total_length
;
1190 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder
* frame
,
1191 const SpdyMajorVersion spdy_version
,
1192 const SpdyHeaderBlock
* headers
) {
1193 if (spdy_version
< SPDY3
) {
1194 frame
->WriteUInt16(headers
->size());
1196 frame
->WriteUInt32(headers
->size());
1198 SpdyHeaderBlock::const_iterator it
;
1199 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1200 if (spdy_version
< SPDY3
) {
1201 frame
->WriteString(it
->first
);
1202 frame
->WriteString(it
->second
);
1204 frame
->WriteStringPiece32(it
->first
);
1205 frame
->WriteStringPiece32(it
->second
);
1210 // TODO(phajdan.jr): Clean up after we no longer need
1211 // to workaround http://crbug.com/139744.
1212 #if !defined(USE_SYSTEM_ZLIB)
1214 // These constants are used by zlib to differentiate between normal data and
1215 // cookie data. Cookie data is handled specially by zlib when compressing.
1217 // kZStandardData is compressed normally, save that it will never match
1218 // against any other class of data in the window.
1219 kZStandardData
= Z_CLASS_STANDARD
,
1220 // kZCookieData is compressed in its own Huffman blocks and only matches in
1221 // its entirety and only against other kZCookieData blocks. Any matches must
1222 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1223 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1225 kZCookieData
= Z_CLASS_COOKIE
,
1226 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1227 // against the window.
1228 kZHuffmanOnlyData
= Z_CLASS_HUFFMAN_ONLY
,
1231 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1232 // needed when switching between classes of data.
1233 static void WriteZ(const base::StringPiece
& data
,
1238 // If we are switching from standard to non-standard data then we need to end
1239 // the current Huffman context to avoid it leaking between them.
1240 if (out
->clas
== kZStandardData
&&
1241 clas
!= kZStandardData
) {
1243 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1244 DCHECK_EQ(Z_OK
, rv
);
1245 DCHECK_EQ(0u, out
->avail_in
);
1246 DCHECK_LT(0u, out
->avail_out
);
1249 out
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
.data()));
1250 out
->avail_in
= data
.size();
1252 if (clas
== kZStandardData
) {
1253 rv
= deflate(out
, Z_NO_FLUSH
);
1255 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1257 if (!data
.empty()) {
1258 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1259 DCHECK_EQ(Z_OK
, rv
);
1261 DCHECK_EQ(0u, out
->avail_in
);
1262 DCHECK_LT(0u, out
->avail_out
);
1265 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1266 static void WriteLengthZ(size_t n
,
1271 DCHECK_LE(length
, sizeof(buf
));
1272 for (unsigned i
= 1; i
<= length
; i
++) {
1273 buf
[length
- i
] = n
;
1276 WriteZ(base::StringPiece(buf
, length
), clas
, out
);
1279 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1280 // manner that resists the length of the compressed data from compromising
1282 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
1283 z_stream
* z
) const {
1284 unsigned length_length
= 4;
1285 if (spdy_version_
< 3)
1288 WriteLengthZ(headers
->size(), length_length
, kZStandardData
, z
);
1290 std::map
<std::string
, std::string
>::const_iterator it
;
1291 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1292 WriteLengthZ(it
->first
.size(), length_length
, kZStandardData
, z
);
1293 WriteZ(it
->first
, kZStandardData
, z
);
1295 if (it
->first
== "cookie") {
1296 // We require the cookie values (save for the last) to end with a
1297 // semicolon and (save for the first) to start with a space. This is
1298 // typically the format that we are given them in but we reserialize them
1301 std::vector
<base::StringPiece
> cookie_values
;
1302 size_t cookie_length
= 0;
1303 base::StringPiece
cookie_data(it
->second
);
1306 while (!cookie_data
.empty() &&
1307 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
1308 cookie_data
.remove_prefix(1);
1310 if (cookie_data
.empty())
1314 for (i
= 0; i
< cookie_data
.size(); i
++) {
1315 if (cookie_data
[i
] == ';')
1318 if (i
< cookie_data
.size()) {
1319 if (!IsCookieEmpty(cookie_data
.substr(0, i
))) {
1320 cookie_values
.push_back(cookie_data
.substr(0, i
));
1321 cookie_length
+= i
+ 2 /* semicolon and space */;
1323 cookie_data
.remove_prefix(i
+ 1);
1325 if (!IsCookieEmpty(cookie_data
)) {
1326 cookie_values
.push_back(cookie_data
);
1327 cookie_length
+= cookie_data
.size();
1328 } else if (cookie_length
> 2) {
1329 cookie_length
-= 2 /* compensate for previously added length */;
1331 cookie_data
.remove_prefix(i
);
1335 WriteLengthZ(cookie_length
, length_length
, kZStandardData
, z
);
1336 for (size_t i
= 0; i
< cookie_values
.size(); i
++) {
1338 // Since zlib will only back-reference complete cookies, a cookie that
1339 // is currently last (and so doesn't have a trailing semicolon) won't
1340 // match if it's later in a non-final position. The same is true of
1341 // the first cookie.
1342 if (i
== 0 && cookie_values
.size() == 1) {
1343 cookie
= cookie_values
[i
].as_string();
1344 } else if (i
== 0) {
1345 cookie
= cookie_values
[i
].as_string() + ";";
1346 } else if (i
< cookie_values
.size() - 1) {
1347 cookie
= " " + cookie_values
[i
].as_string() + ";";
1349 cookie
= " " + cookie_values
[i
].as_string();
1351 WriteZ(cookie
, kZCookieData
, z
);
1353 } else if (it
->first
== "accept" ||
1354 it
->first
== "accept-charset" ||
1355 it
->first
== "accept-encoding" ||
1356 it
->first
== "accept-language" ||
1357 it
->first
== "host" ||
1358 it
->first
== "version" ||
1359 it
->first
== "method" ||
1360 it
->first
== "scheme" ||
1361 it
->first
== ":host" ||
1362 it
->first
== ":version" ||
1363 it
->first
== ":method" ||
1364 it
->first
== ":scheme" ||
1365 it
->first
== "user-agent") {
1366 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1367 WriteZ(it
->second
, kZStandardData
, z
);
1369 // Non-whitelisted headers are Huffman compressed in their own block, but
1370 // don't match against the window.
1371 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1372 WriteZ(it
->second
, kZHuffmanOnlyData
, z
);
1377 int rv
= deflate(z
, Z_SYNC_FLUSH
);
1378 DCHECK_EQ(Z_OK
, rv
);
1379 z
->clas
= kZStandardData
;
1382 #endif // !defined(USE_SYSTEM_ZLIB)
1384 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
1386 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
1387 const size_t original_len
= len
;
1389 if (remaining_control_header_
> 0) {
1390 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1391 remaining_control_header_
);
1392 remaining_control_header_
-= bytes_read
;
1393 remaining_data_length_
-= bytes_read
;
1396 if (remaining_control_header_
== 0) {
1397 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1398 current_frame_buffer_length_
);
1399 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1401 switch (current_frame_type_
) {
1404 DCHECK_GE(SPDY3
, protocol_version());
1405 bool successful_read
= true;
1406 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1407 DCHECK(successful_read
);
1408 if (current_frame_stream_id_
== 0) {
1409 set_error(SPDY_INVALID_CONTROL_FRAME
);
1413 SpdyStreamId associated_to_stream_id
= kInvalidStream
;
1414 successful_read
= reader
.ReadUInt31(&associated_to_stream_id
);
1415 DCHECK(successful_read
);
1417 SpdyPriority priority
= 0;
1418 successful_read
= reader
.ReadUInt8(&priority
);
1419 DCHECK(successful_read
);
1420 if (protocol_version() <= SPDY2
) {
1421 priority
= priority
>> 6;
1423 priority
= priority
>> 5;
1426 // Seek past unused byte; used to be credential slot in SPDY 3.
1429 DCHECK(reader
.IsDoneReading());
1430 if (debug_visitor_
) {
1431 debug_visitor_
->OnReceiveCompressedFrame(
1432 current_frame_stream_id_
,
1433 current_frame_type_
,
1434 current_frame_length_
);
1436 visitor_
->OnSynStream(
1437 current_frame_stream_id_
,
1438 associated_to_stream_id
,
1440 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1441 (current_frame_flags_
& CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
1443 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1446 if (protocol_version() > SPDY3
&&
1447 current_frame_flags_
& SETTINGS_FLAG_ACK
) {
1448 visitor_
->OnSettingsAck();
1449 CHANGE_STATE(SPDY_AUTO_RESET
);
1451 visitor_
->OnSettings(current_frame_flags_
&
1452 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
);
1453 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
1458 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1460 if (protocol_version() > SPDY3
) {
1461 DCHECK_EQ(HEADERS
, current_frame_type_
);
1463 bool successful_read
= true;
1464 if (protocol_version() <= SPDY3
) {
1465 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1466 DCHECK(successful_read
);
1468 if (current_frame_stream_id_
== 0) {
1469 set_error(SPDY_INVALID_CONTROL_FRAME
);
1472 if (protocol_version() <= SPDY2
) {
1473 // SPDY 2 had two unused bytes here. Seek past them.
1476 if (protocol_version() > SPDY3
&&
1477 !(current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) &&
1478 current_frame_type_
== HEADERS
) {
1479 expect_continuation_
= current_frame_stream_id_
;
1480 end_stream_when_done_
= current_frame_flags_
& CONTROL_FLAG_FIN
;
1482 if (protocol_version() > SPDY3
&&
1483 current_frame_flags_
& HEADERS_FLAG_PADDED
) {
1484 uint8 pad_payload_len
= 0;
1485 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
1486 successful_read
= reader
.ReadUInt8(&pad_payload_len
);
1487 DCHECK(successful_read
);
1488 remaining_padding_payload_length_
= pad_payload_len
;
1490 const bool has_priority
=
1491 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0;
1492 uint32 priority
= 0;
1493 if (protocol_version() > SPDY3
&& has_priority
) {
1494 // TODO(jgraettinger): Process dependency rather than ignoring it.
1495 reader
.Seek(kPriorityDependencyPayloadSize
);
1497 successful_read
= reader
.ReadUInt8(&weight
);
1498 if (successful_read
) {
1499 priority
= MapWeightToPriority(weight
);
1502 DCHECK(reader
.IsDoneReading());
1503 if (debug_visitor_
) {
1504 debug_visitor_
->OnReceiveCompressedFrame(
1505 current_frame_stream_id_
,
1506 current_frame_type_
,
1507 current_frame_length_
);
1509 if (current_frame_type_
== SYN_REPLY
) {
1510 visitor_
->OnSynReply(
1511 current_frame_stream_id_
,
1512 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0);
1514 visitor_
->OnHeaders(
1515 current_frame_stream_id_
,
1516 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0, priority
,
1517 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1518 expect_continuation_
== 0);
1521 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1525 DCHECK_LT(SPDY3
, protocol_version());
1526 if (current_frame_stream_id_
== 0) {
1527 set_error(SPDY_INVALID_CONTROL_FRAME
);
1530 bool successful_read
= true;
1531 if (protocol_version() > SPDY3
&&
1532 current_frame_flags_
& PUSH_PROMISE_FLAG_PADDED
) {
1533 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
1534 uint8 pad_payload_len
= 0;
1535 successful_read
= reader
.ReadUInt8(&pad_payload_len
);
1536 DCHECK(successful_read
);
1537 remaining_padding_payload_length_
= pad_payload_len
;
1541 SpdyStreamId promised_stream_id
= kInvalidStream
;
1542 bool successful_read
= reader
.ReadUInt31(&promised_stream_id
);
1543 DCHECK(successful_read
);
1544 DCHECK(reader
.IsDoneReading());
1545 if (promised_stream_id
== 0) {
1546 set_error(SPDY_INVALID_CONTROL_FRAME
);
1549 if (!(current_frame_flags_
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
1550 expect_continuation_
= current_frame_stream_id_
;
1552 if (debug_visitor_
) {
1553 debug_visitor_
->OnReceiveCompressedFrame(
1554 current_frame_stream_id_
,
1555 current_frame_type_
,
1556 current_frame_length_
);
1558 visitor_
->OnPushPromise(current_frame_stream_id_
,
1560 (current_frame_flags_
&
1561 PUSH_PROMISE_FLAG_END_PUSH_PROMISE
) != 0);
1563 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1567 // Check to make sure the stream id of the current frame is
1568 // the same as that of the preceding frame.
1569 // If we're at this point we should already know that
1570 // expect_continuation_ != 0, so this doubles as a check
1571 // that current_frame_stream_id != 0.
1572 if (current_frame_stream_id_
!= expect_continuation_
) {
1573 set_error(SPDY_INVALID_CONTROL_FRAME
);
1576 if (current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) {
1577 expect_continuation_
= 0;
1579 if (debug_visitor_
) {
1580 debug_visitor_
->OnReceiveCompressedFrame(
1581 current_frame_stream_id_
,
1582 current_frame_type_
,
1583 current_frame_length_
);
1585 visitor_
->OnContinuation(current_frame_stream_id_
,
1586 (current_frame_flags_
&
1587 HEADERS_FLAG_END_HEADERS
) != 0);
1589 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1595 return original_len
- len
;
1598 // Does not buffer the control payload. Instead, either passes directly to the
1599 // visitor or decompresses and then passes directly to the visitor, via
1600 // IncrementallyDeliverControlFrameHeaderData() or
1601 // IncrementallyDecompressControlFrameHeaderData() respectively.
1602 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
1604 bool is_hpack_header_block
) {
1605 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
1607 bool processed_successfully
= true;
1608 if (current_frame_type_
!= SYN_STREAM
&&
1609 current_frame_type_
!= SYN_REPLY
&&
1610 current_frame_type_
!= HEADERS
&&
1611 current_frame_type_
!= PUSH_PROMISE
&&
1612 current_frame_type_
!= CONTINUATION
) {
1613 LOG(DFATAL
) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1615 size_t process_bytes
= std::min(
1616 data_len
, remaining_data_length_
- remaining_padding_payload_length_
);
1617 if (is_hpack_header_block
) {
1618 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1619 current_frame_stream_id_
, data
, process_bytes
)) {
1620 // TODO(jgraettinger): Finer-grained HPACK error codes.
1621 set_error(SPDY_DECOMPRESS_FAILURE
);
1622 processed_successfully
= false;
1624 } else if (process_bytes
> 0) {
1625 if (enable_compression_
&& protocol_version() <= SPDY3
) {
1626 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
1627 current_frame_stream_id_
, data
, process_bytes
);
1629 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
1630 current_frame_stream_id_
, data
, process_bytes
);
1633 remaining_data_length_
-= process_bytes
;
1635 // Handle the case that there is no futher data in this frame.
1636 if (remaining_data_length_
== remaining_padding_payload_length_
&&
1637 processed_successfully
) {
1638 if (expect_continuation_
== 0) {
1639 if (is_hpack_header_block
) {
1640 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1641 current_frame_stream_id_
)) {
1642 set_error(SPDY_DECOMPRESS_FAILURE
);
1643 processed_successfully
= false;
1645 // TODO(jgraettinger): To be removed with migration to
1646 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1647 // block, delivered via reentrant call to
1648 // ProcessControlFrameHeaderBlock().
1649 DeliverHpackBlockAsSpdy3Block();
1650 return process_bytes
;
1653 // The complete header block has been delivered. We send a zero-length
1654 // OnControlFrameHeaderData() to indicate this.
1655 visitor_
->OnControlFrameHeaderData(current_frame_stream_id_
, NULL
, 0);
1658 if (processed_successfully
) {
1659 CHANGE_STATE(SPDY_CONSUME_PADDING
);
1664 if (!processed_successfully
) {
1668 // Return amount processed.
1669 return process_bytes
;
1672 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
1674 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD
, state_
);
1675 DCHECK_EQ(SETTINGS
, current_frame_type_
);
1676 size_t unprocessed_bytes
= std::min(data_len
, remaining_data_length_
);
1677 size_t processed_bytes
= 0;
1679 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
1681 // Loop over our incoming data.
1682 while (unprocessed_bytes
> 0) {
1683 // Process up to one setting at a time.
1684 size_t processing
= std::min(
1686 static_cast<size_t>(setting_size
- settings_scratch_
.setting_buf_len
));
1688 // Check if we have a complete setting in our input.
1689 if (processing
== setting_size
) {
1690 // Parse the setting directly out of the input without buffering.
1691 if (!ProcessSetting(data
+ processed_bytes
)) {
1692 set_error(SPDY_INVALID_CONTROL_FRAME
);
1693 return processed_bytes
;
1696 // Continue updating settings_scratch_.setting_buf.
1697 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
1698 data
+ processed_bytes
,
1700 settings_scratch_
.setting_buf_len
+= processing
;
1702 // Check if we have a complete setting buffered.
1703 if (settings_scratch_
.setting_buf_len
== setting_size
) {
1704 if (!ProcessSetting(settings_scratch_
.setting_buf
)) {
1705 set_error(SPDY_INVALID_CONTROL_FRAME
);
1706 return processed_bytes
;
1708 // Reset settings_scratch_.setting_buf for our next setting.
1709 settings_scratch_
.setting_buf_len
= 0;
1714 unprocessed_bytes
-= processing
;
1715 processed_bytes
+= processing
;
1718 // Check if we're done handling this SETTINGS frame.
1719 remaining_data_length_
-= processed_bytes
;
1720 if (remaining_data_length_
== 0) {
1721 visitor_
->OnSettingsEnd();
1722 CHANGE_STATE(SPDY_AUTO_RESET
);
1725 return processed_bytes
;
1728 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1729 DCHECK_LT(SPDY3
, protocol_version());
1730 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
1732 const SpdyNameValueBlock
& block
= GetHpackDecoder()->decoded_block();
1733 if (block
.empty()) {
1734 // Special-case this to make tests happy.
1735 ProcessControlFrameHeaderBlock(NULL
, 0, false);
1738 SpdyFrameBuilder
builder(
1739 GetSerializedLength(protocol_version(), &block
),
1742 SerializeNameValueBlockWithoutCompression(&builder
, block
);
1743 scoped_ptr
<SpdyFrame
> frame(builder
.take());
1745 // Preserve padding length, and reset it after the re-entrant call.
1746 size_t remaining_padding
= remaining_padding_payload_length_
;
1748 remaining_padding_payload_length_
= 0;
1749 remaining_data_length_
= frame
->size();
1751 ProcessControlFrameHeaderBlock(frame
->data(), frame
->size(), false);
1753 remaining_padding_payload_length_
= remaining_padding
;
1754 remaining_data_length_
= remaining_padding
;
1757 bool SpdyFramer::ProcessSetting(const char* data
) {
1764 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1765 if (protocol_version() <= SPDY3
) {
1766 const uint32 id_and_flags_wire
= *(reinterpret_cast<const uint32
*>(data
));
1767 SettingsFlagsAndId id_and_flags
=
1768 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire
);
1769 id_field
= id_and_flags
.id();
1770 flags
= id_and_flags
.flags();
1771 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 4)));
1773 id_field
= ntohs(*(reinterpret_cast<const uint16
*>(data
)));
1774 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 2)));
1778 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field
)) {
1779 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_field
;
1780 if (protocol_version() <= SPDY3
) {
1783 // In HTTP2 we ignore unknown settings for extensibility.
1787 id
= SpdyConstants::ParseSettingId(protocol_version(), id_field
);
1789 if (protocol_version() <= SPDY3
) {
1790 // Detect duplicates.
1791 if (id
<= settings_scratch_
.last_setting_id
) {
1792 DLOG(WARNING
) << "Duplicate entry or invalid ordering for id " << id
1793 << " in " << display_protocol_
<< " SETTINGS frame "
1794 << "(last setting id was "
1795 << settings_scratch_
.last_setting_id
<< ").";
1798 settings_scratch_
.last_setting_id
= id
;
1801 uint8 kFlagsMask
= SETTINGS_FLAG_PLEASE_PERSIST
| SETTINGS_FLAG_PERSISTED
;
1802 if ((flags
& ~(kFlagsMask
)) != 0) {
1803 DLOG(WARNING
) << "Unknown SETTINGS flags provided for id " << id
<< ": "
1809 // Validation succeeded. Pass on to visitor.
1810 visitor_
->OnSetting(id
, flags
, value
);
1814 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
1815 size_t original_len
= len
;
1816 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1817 remaining_data_length_
);
1818 remaining_data_length_
-= bytes_read
;
1819 if (remaining_data_length_
== 0) {
1820 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1821 current_frame_buffer_length_
);
1822 reader
.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1824 // Use frame-specific handlers.
1825 switch (current_frame_type_
) {
1828 bool is_ack
= protocol_version() > SPDY3
&&
1829 (current_frame_flags_
& PING_FLAG_ACK
);
1830 bool successful_read
= true;
1831 if (protocol_version() <= SPDY3
) {
1833 successful_read
= reader
.ReadUInt32(&id32
);
1836 successful_read
= reader
.ReadUInt64(&id
);
1838 DCHECK(successful_read
);
1839 DCHECK(reader
.IsDoneReading());
1840 visitor_
->OnPing(id
, is_ack
);
1843 case WINDOW_UPDATE
: {
1844 uint32 delta_window_size
= 0;
1845 bool successful_read
= true;
1846 if (protocol_version() <= SPDY3
) {
1847 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1848 DCHECK(successful_read
);
1850 successful_read
= reader
.ReadUInt32(&delta_window_size
);
1851 DCHECK(successful_read
);
1852 DCHECK(reader
.IsDoneReading());
1853 visitor_
->OnWindowUpdate(current_frame_stream_id_
,
1858 DCHECK_LT(SPDY3
, protocol_version());
1859 DCHECK(reader
.IsDoneReading());
1860 visitor_
->OnBlocked(current_frame_stream_id_
);
1864 DCHECK_LT(SPDY3
, protocol_version());
1865 uint32 parent_stream_id
;
1868 bool successful_read
= true;
1869 successful_read
= reader
.ReadUInt32(&parent_stream_id
);
1870 DCHECK(successful_read
);
1871 // Exclusivity is indicated by a single bit flag.
1872 exclusive
= (parent_stream_id
>> 31) != 0;
1873 // Zero out the highest-order bit to get the parent stream id.
1874 parent_stream_id
&= 0x7fffffff;
1875 successful_read
= reader
.ReadUInt8(&weight
);
1876 DCHECK(successful_read
);
1877 DCHECK(reader
.IsDoneReading());
1878 visitor_
->OnPriority(
1879 current_frame_stream_id_
, parent_stream_id
, weight
, exclusive
);
1884 LOG(FATAL
) << "Unhandled control frame " << current_frame_type_
;
1887 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
1889 return original_len
- len
;
1892 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data
, size_t len
) {
1896 // Clamp to the actual remaining payload.
1897 if (len
> remaining_data_length_
) {
1898 len
= remaining_data_length_
;
1900 size_t original_len
= len
;
1902 // Check if we had already read enough bytes to parse the GOAWAY header.
1903 const size_t header_size
= GetGoAwayMinimumSize();
1904 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1905 bool already_parsed_header
= (unread_header_bytes
== 0);
1906 if (!already_parsed_header
) {
1907 // Buffer the new GOAWAY header bytes we got.
1908 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1910 // Do we have enough to parse the constant size GOAWAY header?
1911 if (current_frame_buffer_length_
== header_size
) {
1912 // Parse out the last good stream id.
1913 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1914 current_frame_buffer_length_
);
1915 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1916 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1917 DCHECK(successful_read
);
1919 // In SPDYv3 and up, frames also specify a status code - parse it out.
1920 SpdyGoAwayStatus status
= GOAWAY_OK
;
1921 if (protocol_version() >= SPDY3
) {
1922 uint32 status_raw
= GOAWAY_OK
;
1923 successful_read
= reader
.ReadUInt32(&status_raw
);
1924 DCHECK(successful_read
);
1925 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1927 status
= SpdyConstants::ParseGoAwayStatus(protocol_version(),
1930 if (protocol_version() > SPDY3
) {
1931 // Treat unrecognized status codes as INTERNAL_ERROR as
1932 // recommended by the HTTP/2 spec.
1933 status
= GOAWAY_INTERNAL_ERROR
;
1937 // Finished parsing the GOAWAY header, call frame handler.
1938 visitor_
->OnGoAway(current_frame_stream_id_
, status
);
1942 // Handle remaining data as opaque.
1943 bool processed_successfully
= true;
1945 processed_successfully
= visitor_
->OnGoAwayFrameData(data
, len
);
1947 remaining_data_length_
-= original_len
;
1948 if (!processed_successfully
) {
1949 set_error(SPDY_GOAWAY_FRAME_CORRUPT
);
1950 } else if (remaining_data_length_
== 0) {
1951 // Signal that there is not more opaque data.
1952 visitor_
->OnGoAwayFrameData(NULL
, 0);
1953 CHANGE_STATE(SPDY_AUTO_RESET
);
1955 return original_len
;
1958 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data
, size_t len
) {
1962 // Clamp to the actual remaining payload.
1963 if (len
> remaining_data_length_
) {
1964 len
= remaining_data_length_
;
1966 size_t original_len
= len
;
1968 // Check if we had already read enough bytes to parse the fixed-length portion
1969 // of the RST_STREAM frame.
1970 const size_t header_size
= GetRstStreamMinimumSize();
1971 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1972 bool already_parsed_header
= (unread_header_bytes
== 0);
1973 if (!already_parsed_header
) {
1974 // Buffer the new RST_STREAM header bytes we got.
1975 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1977 // Do we have enough to parse the constant size RST_STREAM header?
1978 if (current_frame_buffer_length_
== header_size
) {
1979 // Parse out the last good stream id.
1980 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1981 current_frame_buffer_length_
);
1982 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1983 if (protocol_version() <= SPDY3
) {
1984 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1985 DCHECK(successful_read
);
1988 SpdyRstStreamStatus status
= RST_STREAM_INVALID
;
1989 uint32 status_raw
= status
;
1990 bool successful_read
= reader
.ReadUInt32(&status_raw
);
1991 DCHECK(successful_read
);
1992 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1994 status
= static_cast<SpdyRstStreamStatus
>(status_raw
);
1996 if (protocol_version() > SPDY3
) {
1997 // Treat unrecognized status codes as INTERNAL_ERROR as
1998 // recommended by the HTTP/2 spec.
1999 status
= RST_STREAM_INTERNAL_ERROR
;
2002 // Finished parsing the RST_STREAM header, call frame handler.
2003 visitor_
->OnRstStream(current_frame_stream_id_
, status
);
2007 // Handle remaining data as opaque.
2008 bool processed_successfully
= true;
2010 processed_successfully
= visitor_
->OnRstStreamFrameData(data
, len
);
2012 remaining_data_length_
-= original_len
;
2013 if (!processed_successfully
) {
2014 set_error(SPDY_RST_STREAM_FRAME_CORRUPT
);
2015 } else if (remaining_data_length_
== 0) {
2016 // Signal that there is not more opaque data.
2017 visitor_
->OnRstStreamFrameData(NULL
, 0);
2018 CHANGE_STATE(SPDY_AUTO_RESET
);
2020 return original_len
;
2023 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data
, size_t len
) {
2028 // Clamp to the actual remaining payload.
2029 len
= std::min(len
, remaining_data_length_
);
2031 size_t processed_bytes
= 0;
2032 size_t processing
= 0;
2033 size_t bytes_remaining
;
2038 if (altsvc_scratch_
.pid_len
== 0) {
2039 // The size of the frame up to the PID_LEN field.
2040 size_t fixed_len_portion
= GetAltSvcMinimumSize() - 1;
2041 bytes_remaining
= fixed_len_portion
- current_frame_buffer_length_
;
2042 processing
= std::min(len
, bytes_remaining
);
2043 // Buffer the new ALTSVC bytes we got.
2044 UpdateCurrentFrameBuffer(&data
, &len
, processing
);
2046 // Do we have enough to parse the length of the protocol id?
2047 if (current_frame_buffer_length_
== fixed_len_portion
) {
2048 // Parse out the max age, port, and pid_len.
2049 SpdyFrameReader
reader(current_frame_buffer_
.get(),
2050 current_frame_buffer_length_
);
2051 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2052 bool successful_read
= reader
.ReadUInt32(&altsvc_scratch_
.max_age
);
2053 reader
.ReadUInt16(&altsvc_scratch_
.port
);
2054 reader
.Seek(1); // Reserved byte.
2055 successful_read
= successful_read
&&
2056 reader
.ReadUInt8(&altsvc_scratch_
.pid_len
);
2057 DCHECK(successful_read
);
2058 // Sanity check length value.
2059 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
>=
2060 current_frame_length_
) {
2061 set_error(SPDY_INVALID_CONTROL_FRAME
);
2064 altsvc_scratch_
.protocol_id
.reset(
2065 new char[size_t(altsvc_scratch_
.pid_len
)]);
2067 processed_bytes
+= processing
;
2069 } else if (altsvc_scratch_
.pid_buf_len
< altsvc_scratch_
.pid_len
) {
2070 // Buffer protocol id field as in comes in.
2071 buffer
= altsvc_scratch_
.protocol_id
.get();
2072 buffer_len
= &altsvc_scratch_
.pid_buf_len
;
2073 bytes_remaining
= altsvc_scratch_
.pid_len
- altsvc_scratch_
.pid_buf_len
;
2074 } else if (altsvc_scratch_
.host_len
== 0) {
2075 // Parse out the host length.
2077 altsvc_scratch_
.host_len
= *reinterpret_cast<const uint8
*>(data
);
2078 // Sanity check length value.
2079 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
+
2080 altsvc_scratch_
.host_len
> current_frame_length_
) {
2081 set_error(SPDY_INVALID_CONTROL_FRAME
);
2084 altsvc_scratch_
.host
.reset(new char[altsvc_scratch_
.host_len
]);
2085 // Once we have host length, we can also determine the origin length
2086 // by process of elimination.
2087 altsvc_scratch_
.origin_len
= current_frame_length_
-
2088 GetAltSvcMinimumSize() -
2089 altsvc_scratch_
.pid_len
-
2090 altsvc_scratch_
.host_len
;
2091 if (altsvc_scratch_
.origin_len
> 0) {
2092 altsvc_scratch_
.origin
.reset(new char[altsvc_scratch_
.origin_len
]);
2095 processed_bytes
+= processing
;
2098 } else if (altsvc_scratch_
.host_buf_len
< altsvc_scratch_
.host_len
) {
2099 // Buffer host field as it comes in.
2100 // TODO(mlavan): check formatting for host and origin
2101 buffer
= altsvc_scratch_
.host
.get();
2102 buffer_len
= &altsvc_scratch_
.host_buf_len
;
2103 bytes_remaining
= altsvc_scratch_
.host_len
- altsvc_scratch_
.host_buf_len
;
2105 // Buffer (optional) origin field as it comes in.
2106 if (altsvc_scratch_
.origin_len
<= 0) {
2107 set_error(SPDY_INVALID_CONTROL_FRAME
);
2110 buffer
= altsvc_scratch_
.origin
.get();
2111 buffer_len
= &altsvc_scratch_
.origin_buf_len
;
2112 bytes_remaining
= remaining_data_length_
-
2114 altsvc_scratch_
.origin_buf_len
;
2115 if (len
> bytes_remaining
) {
2116 // This is our last field; there shouldn't be any more bytes.
2117 set_error(SPDY_INVALID_CONTROL_FRAME
);
2122 // Copy data bytes into the appropriate field.
2123 processing
= std::min(len
, bytes_remaining
);
2124 memcpy(buffer
+ *buffer_len
,
2127 *buffer_len
+= processing
;
2129 processed_bytes
+= processing
;
2133 remaining_data_length_
-= processed_bytes
;
2134 if (remaining_data_length_
== 0) {
2135 visitor_
->OnAltSvc(current_frame_stream_id_
,
2136 altsvc_scratch_
.max_age
,
2137 altsvc_scratch_
.port
,
2138 StringPiece(altsvc_scratch_
.protocol_id
.get(),
2139 altsvc_scratch_
.pid_len
),
2140 StringPiece(altsvc_scratch_
.host
.get(),
2141 altsvc_scratch_
.host_len
),
2142 StringPiece(altsvc_scratch_
.origin
.get(),
2143 altsvc_scratch_
.origin_len
));
2144 CHANGE_STATE(SPDY_AUTO_RESET
);
2147 return processed_bytes
;
2150 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data
, size_t len
) {
2151 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH
, state_
);
2152 DCHECK_EQ(0u, remaining_padding_payload_length_
);
2153 DCHECK_EQ(DATA
, current_frame_type_
);
2155 size_t original_len
= len
;
2156 if (current_frame_flags_
& DATA_FLAG_PADDED
) {
2158 if (remaining_data_length_
< kPadLengthFieldSize
) {
2159 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2163 remaining_padding_payload_length_
= *reinterpret_cast<const uint8
*>(data
);
2166 --remaining_data_length_
;
2168 // We don't have the data available for parsing the pad length field. Keep
2174 if (remaining_padding_payload_length_
> remaining_data_length_
) {
2175 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2178 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
2179 return original_len
- len
;
2182 size_t SpdyFramer::ProcessFramePadding(const char* data
, size_t len
) {
2183 DCHECK_EQ(SPDY_CONSUME_PADDING
, state_
);
2185 size_t original_len
= len
;
2186 if (remaining_padding_payload_length_
> 0) {
2187 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
2188 size_t amount_to_discard
= std::min(remaining_padding_payload_length_
, len
);
2189 if (current_frame_type_
== DATA
&& amount_to_discard
> 0) {
2190 // The visitor needs to know about padding so it can send window updates.
2191 // Communicate the padding to the visitor through a NULL data pointer,
2192 // with a nonzero size.
2193 visitor_
->OnStreamFrameData(
2194 current_frame_stream_id_
, NULL
, amount_to_discard
, false);
2196 data
+= amount_to_discard
;
2197 len
-= amount_to_discard
;
2198 remaining_padding_payload_length_
-= amount_to_discard
;
2199 remaining_data_length_
-= amount_to_discard
;
2202 if (remaining_data_length_
== 0) {
2203 // If the FIN flag is set, or this ends a header block which set FIN,
2204 // inform the visitor of EOF via a 0-length data frame.
2205 if (expect_continuation_
== 0 &&
2206 ((current_frame_flags_
& CONTROL_FLAG_FIN
) != 0 ||
2207 end_stream_when_done_
)) {
2208 end_stream_when_done_
= false;
2209 visitor_
->OnStreamFrameData(current_frame_stream_id_
, NULL
, 0, true);
2211 CHANGE_STATE(SPDY_AUTO_RESET
);
2213 return original_len
- len
;
2216 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
2217 size_t original_len
= len
;
2218 if (remaining_data_length_
- remaining_padding_payload_length_
> 0) {
2219 size_t amount_to_forward
= std::min(
2220 remaining_data_length_
- remaining_padding_payload_length_
, len
);
2221 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
2222 // Only inform the visitor if there is data.
2223 if (amount_to_forward
) {
2224 visitor_
->OnStreamFrameData(
2225 current_frame_stream_id_
, data
, amount_to_forward
, false);
2228 data
+= amount_to_forward
;
2229 len
-= amount_to_forward
;
2230 remaining_data_length_
-= amount_to_forward
;
2233 if (remaining_data_length_
== remaining_padding_payload_length_
) {
2234 CHANGE_STATE(SPDY_CONSUME_PADDING
);
2236 return original_len
- len
;
2239 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2241 size_t original_len
= len
;
2242 if (remaining_data_length_
> 0) {
2243 size_t amount_to_ignore
= std::min(remaining_data_length_
, len
);
2244 len
-= amount_to_ignore
;
2245 remaining_data_length_
-= amount_to_ignore
;
2248 if (remaining_data_length_
== 0) {
2249 CHANGE_STATE(SPDY_AUTO_RESET
);
2251 return original_len
- len
;
2254 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
2255 size_t header_length
,
2256 SpdyHeaderBlock
* block
) const {
2257 SpdyFrameReader
reader(header_data
, header_length
);
2259 // Read number of headers.
2261 if (protocol_version() <= SPDY2
) {
2263 if (!reader
.ReadUInt16(&temp
)) {
2264 DVLOG(1) << "Unable to read number of headers.";
2269 if (!reader
.ReadUInt32(&num_headers
)) {
2270 DVLOG(1) << "Unable to read number of headers.";
2275 // Read each header.
2276 for (uint32 index
= 0; index
< num_headers
; ++index
) {
2277 base::StringPiece temp
;
2279 // Read header name.
2280 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2281 : !reader
.ReadStringPiece32(&temp
)) {
2282 DVLOG(1) << "Unable to read header name (" << index
+ 1 << " of "
2283 << num_headers
<< ").";
2286 std::string name
= temp
.as_string();
2288 // Read header value.
2289 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2290 : !reader
.ReadStringPiece32(&temp
)) {
2291 DVLOG(1) << "Unable to read header value (" << index
+ 1 << " of "
2292 << num_headers
<< ").";
2295 std::string value
= temp
.as_string();
2297 // Ensure no duplicates.
2298 if (block
->find(name
) != block
->end()) {
2299 DVLOG(1) << "Duplicate header '" << name
<< "' (" << index
+ 1 << " of "
2300 << num_headers
<< ").";
2305 (*block
)[name
] = value
;
2307 return reader
.GetBytesConsumed();
2310 SpdySerializedFrame
* SpdyFramer::SerializeData(
2311 const SpdyDataIR
& data_ir
) const {
2312 uint8 flags
= DATA_FLAG_NONE
;
2313 if (data_ir
.fin()) {
2314 flags
= DATA_FLAG_FIN
;
2317 if (protocol_version() > SPDY3
) {
2318 int num_padding_fields
= 0;
2319 if (data_ir
.padded()) {
2320 flags
|= DATA_FLAG_PADDED
;
2321 ++num_padding_fields
;
2324 const size_t size_with_padding
= num_padding_fields
+
2325 data_ir
.data().length() + data_ir
.padding_payload_len() +
2326 GetDataFrameMinimumSize();
2327 SpdyFrameBuilder
builder(size_with_padding
, protocol_version());
2328 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2329 if (data_ir
.padded()) {
2330 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2332 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2333 if (data_ir
.padding_payload_len() > 0) {
2334 string
padding(data_ir
.padding_payload_len(), 0);
2335 builder
.WriteBytes(padding
.data(), padding
.length());
2337 DCHECK_EQ(size_with_padding
, builder
.length());
2338 return builder
.take();
2340 const size_t size
= GetDataFrameMinimumSize() + data_ir
.data().length();
2341 SpdyFrameBuilder
builder(size
, protocol_version());
2342 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2343 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2344 DCHECK_EQ(size
, builder
.length());
2345 return builder
.take();
2349 SpdySerializedFrame
* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2350 const SpdyDataIR
& data_ir
) const {
2351 uint8 flags
= DATA_FLAG_NONE
;
2352 if (data_ir
.fin()) {
2353 flags
= DATA_FLAG_FIN
;
2356 size_t frame_size
= GetDataFrameMinimumSize();
2357 size_t num_padding_fields
= 0;
2358 if (protocol_version() > SPDY3
) {
2359 if (data_ir
.padded()) {
2360 flags
|= DATA_FLAG_PADDED
;
2361 ++num_padding_fields
;
2363 frame_size
+= num_padding_fields
;
2366 SpdyFrameBuilder
builder(frame_size
, protocol_version());
2367 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2368 if (protocol_version() > SPDY3
) {
2369 if (data_ir
.padded()) {
2370 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2372 builder
.OverwriteLength(*this, num_padding_fields
+
2373 data_ir
.data().length() + data_ir
.padding_payload_len());
2375 builder
.OverwriteLength(*this, data_ir
.data().length());
2377 DCHECK_EQ(frame_size
, builder
.length());
2378 return builder
.take();
2381 SpdySerializedFrame
* SpdyFramer::SerializeSynStream(
2382 const SpdySynStreamIR
& syn_stream
) {
2383 DCHECK_GE(SPDY3
, protocol_version());
2385 if (syn_stream
.fin()) {
2386 flags
|= CONTROL_FLAG_FIN
;
2388 if (syn_stream
.unidirectional()) {
2389 // TODO(hkhalil): invalid for HTTP2.
2390 flags
|= CONTROL_FLAG_UNIDIRECTIONAL
;
2393 // Sanitize priority.
2394 uint8 priority
= syn_stream
.priority();
2395 if (priority
> GetLowestPriority()) {
2396 DLOG(DFATAL
) << "Priority out-of-bounds.";
2397 priority
= GetLowestPriority();
2400 // The size of this frame, including variable-length name-value block.
2401 size_t size
= GetSynStreamMinimumSize() +
2402 GetSerializedLength(syn_stream
.name_value_block());
2404 SpdyFrameBuilder
builder(size
, protocol_version());
2405 builder
.WriteControlFrameHeader(*this, SYN_STREAM
, flags
);
2406 builder
.WriteUInt32(syn_stream
.stream_id());
2407 builder
.WriteUInt32(syn_stream
.associated_to_stream_id());
2408 builder
.WriteUInt8(priority
<< ((protocol_version() <= SPDY2
) ? 6 : 5));
2409 builder
.WriteUInt8(0); // Unused byte where credential slot used to be.
2410 DCHECK_EQ(GetSynStreamMinimumSize(), builder
.length());
2411 SerializeNameValueBlock(&builder
, syn_stream
);
2413 if (debug_visitor_
) {
2414 const size_t payload_len
=
2415 GetSerializedLength(protocol_version(),
2416 &(syn_stream
.name_value_block()));
2417 debug_visitor_
->OnSendCompressedFrame(syn_stream
.stream_id(),
2423 return builder
.take();
2426 SpdySerializedFrame
* SpdyFramer::SerializeSynReply(
2427 const SpdySynReplyIR
& syn_reply
) {
2428 DCHECK_GE(SPDY3
, protocol_version());
2430 if (syn_reply
.fin()) {
2431 flags
|= CONTROL_FLAG_FIN
;
2434 // The size of this frame, including variable-length name-value block.
2435 const size_t size
= GetSynReplyMinimumSize() +
2436 GetSerializedLength(syn_reply
.name_value_block());
2438 SpdyFrameBuilder
builder(size
, protocol_version());
2439 if (protocol_version() <= SPDY3
) {
2440 builder
.WriteControlFrameHeader(*this, SYN_REPLY
, flags
);
2441 builder
.WriteUInt32(syn_reply
.stream_id());
2443 builder
.BeginNewFrame(*this,
2446 syn_reply
.stream_id());
2448 if (protocol_version() < SPDY3
) {
2449 builder
.WriteUInt16(0); // Unused.
2451 DCHECK_EQ(GetSynReplyMinimumSize(), builder
.length());
2452 SerializeNameValueBlock(&builder
, syn_reply
);
2454 if (debug_visitor_
) {
2455 const size_t payload_len
= GetSerializedLength(
2456 protocol_version(), &(syn_reply
.name_value_block()));
2457 debug_visitor_
->OnSendCompressedFrame(syn_reply
.stream_id(),
2463 return builder
.take();
2466 SpdySerializedFrame
* SpdyFramer::SerializeRstStream(
2467 const SpdyRstStreamIR
& rst_stream
) const {
2468 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2469 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2470 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2471 // commented but left in place to simplify future patching.
2472 // Compute the output buffer size, taking opaque data into account.
2473 uint16 expected_length
= GetRstStreamMinimumSize();
2474 if (protocol_version() > SPDY3
) {
2475 expected_length
+= rst_stream
.description().size();
2477 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2479 // Serialize the RST_STREAM frame.
2480 if (protocol_version() <= SPDY3
) {
2481 builder
.WriteControlFrameHeader(*this, RST_STREAM
, 0);
2482 builder
.WriteUInt32(rst_stream
.stream_id());
2484 builder
.BeginNewFrame(*this, RST_STREAM
, 0, rst_stream
.stream_id());
2487 builder
.WriteUInt32(rst_stream
.status());
2489 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2490 if (protocol_version() > SPDY3
&& rst_stream
.description().size() > 0) {
2491 builder
.WriteBytes(rst_stream
.description().data(),
2492 rst_stream
.description().size());
2495 DCHECK_EQ(expected_length
, builder
.length());
2496 return builder
.take();
2499 SpdySerializedFrame
* SpdyFramer::SerializeSettings(
2500 const SpdySettingsIR
& settings
) const {
2503 if (protocol_version() <= SPDY3
) {
2504 if (settings
.clear_settings()) {
2505 flags
|= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
2508 if (settings
.is_ack()) {
2509 flags
|= SETTINGS_FLAG_ACK
;
2512 const SpdySettingsIR::ValueMap
* values
= &(settings
.values());
2514 size_t setting_size
= SpdyConstants::GetSettingSize(protocol_version());
2515 // Size, in bytes, of this SETTINGS frame.
2516 const size_t size
= GetSettingsMinimumSize() +
2517 (values
->size() * setting_size
);
2518 SpdyFrameBuilder
builder(size
, protocol_version());
2519 if (protocol_version() <= SPDY3
) {
2520 builder
.WriteControlFrameHeader(*this, SETTINGS
, flags
);
2522 builder
.BeginNewFrame(*this, SETTINGS
, flags
, 0);
2525 // If this is an ACK, payload should be empty.
2526 if (protocol_version() > SPDY3
&& settings
.is_ack()) {
2527 return builder
.take();
2530 if (protocol_version() <= SPDY3
) {
2531 builder
.WriteUInt32(values
->size());
2533 DCHECK_EQ(GetSettingsMinimumSize(), builder
.length());
2534 for (SpdySettingsIR::ValueMap::const_iterator it
= values
->begin();
2535 it
!= values
->end();
2537 if (protocol_version() <= SPDY3
) {
2538 uint8 setting_flags
= 0;
2539 if (it
->second
.persist_value
) {
2540 setting_flags
|= SETTINGS_FLAG_PLEASE_PERSIST
;
2542 if (it
->second
.persisted
) {
2543 setting_flags
|= SETTINGS_FLAG_PERSISTED
;
2545 SettingsFlagsAndId
flags_and_id(
2547 SpdyConstants::SerializeSettingId(protocol_version(), it
->first
));
2548 uint32 id_and_flags_wire
= flags_and_id
.GetWireFormat(protocol_version());
2549 builder
.WriteBytes(&id_and_flags_wire
, 4);
2551 builder
.WriteUInt16(SpdyConstants::SerializeSettingId(protocol_version(),
2554 builder
.WriteUInt32(it
->second
.value
);
2556 DCHECK_EQ(size
, builder
.length());
2557 return builder
.take();
2560 SpdySerializedFrame
* SpdyFramer::SerializePing(const SpdyPingIR
& ping
) const {
2561 SpdyFrameBuilder
builder(GetPingSize(), protocol_version());
2562 if (protocol_version() <= SPDY3
) {
2563 builder
.WriteControlFrameHeader(*this, PING
, kNoFlags
);
2564 builder
.WriteUInt32(static_cast<uint32
>(ping
.id()));
2567 if (ping
.is_ack()) {
2568 flags
|= PING_FLAG_ACK
;
2570 builder
.BeginNewFrame(*this, PING
, flags
, 0);
2571 builder
.WriteUInt64(ping
.id());
2573 DCHECK_EQ(GetPingSize(), builder
.length());
2574 return builder
.take();
2577 SpdySerializedFrame
* SpdyFramer::SerializeGoAway(
2578 const SpdyGoAwayIR
& goaway
) const {
2580 // Compute the output buffer size, take opaque data into account.
2581 uint16 expected_length
= GetGoAwayMinimumSize();
2582 if (protocol_version() > SPDY3
) {
2583 expected_length
+= goaway
.description().size();
2585 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2587 // Serialize the GOAWAY frame.
2588 if (protocol_version() <= SPDY3
) {
2589 builder
.WriteControlFrameHeader(*this, GOAWAY
, kNoFlags
);
2591 builder
.BeginNewFrame(*this, GOAWAY
, 0, 0);
2594 // GOAWAY frames specify the last good stream id for all SPDY versions.
2595 builder
.WriteUInt32(goaway
.last_good_stream_id());
2597 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2598 if (protocol_version() >= SPDY3
) {
2599 // TODO(jgraettinger): Merge back to server-side.
2600 builder
.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2604 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2605 if ((protocol_version() > SPDY3
) && (goaway
.description().size() > 0)) {
2606 builder
.WriteBytes(goaway
.description().data(),
2607 goaway
.description().size());
2610 DCHECK_EQ(expected_length
, builder
.length());
2611 return builder
.take();
2614 SpdySerializedFrame
* SpdyFramer::SerializeHeaders(
2615 const SpdyHeadersIR
& headers
) {
2617 if (headers
.fin()) {
2618 flags
|= CONTROL_FLAG_FIN
;
2620 if (protocol_version() > SPDY3
) {
2621 // This will get overwritten if we overflow into a CONTINUATION frame.
2622 flags
|= HEADERS_FLAG_END_HEADERS
;
2623 if (headers
.has_priority()) {
2624 flags
|= HEADERS_FLAG_PRIORITY
;
2626 if (headers
.padded()) {
2627 flags
|= HEADERS_FLAG_PADDED
;
2631 // The size of this frame, including padding (if there is any)
2632 // and variable-length name-value block.
2633 size_t size
= GetHeadersMinimumSize();
2635 if (protocol_version() > SPDY3
&& headers
.padded()) {
2636 size
+= kPadLengthFieldSize
;
2637 size
+= headers
.padding_payload_len();
2640 uint32 priority
= headers
.priority();
2641 if (headers
.has_priority()) {
2642 if (priority
> GetLowestPriority()) {
2643 DLOG(DFATAL
) << "Priority out-of-bounds.";
2644 priority
= GetLowestPriority();
2649 string hpack_encoding
;
2650 if (protocol_version() > SPDY3
) {
2651 if (enable_compression_
) {
2652 GetHpackEncoder()->EncodeHeaderSet(
2653 headers
.name_value_block(), &hpack_encoding
);
2655 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2656 headers
.name_value_block(), &hpack_encoding
);
2658 size
+= hpack_encoding
.size();
2659 if (size
> kMaxControlFrameSize
) {
2660 size
+= GetNumberRequiredContinuationFrames(size
) *
2661 GetContinuationMinimumSize();
2662 flags
&= ~HEADERS_FLAG_END_HEADERS
;
2665 size
+= GetSerializedLength(headers
.name_value_block());
2668 SpdyFrameBuilder
builder(size
, protocol_version());
2669 if (protocol_version() <= SPDY3
) {
2670 builder
.WriteControlFrameHeader(*this, HEADERS
, flags
);
2671 builder
.WriteUInt32(headers
.stream_id());
2673 builder
.BeginNewFrame(*this,
2676 headers
.stream_id());
2678 if (protocol_version() <= SPDY2
) {
2679 builder
.WriteUInt16(0); // Unused.
2681 DCHECK_EQ(GetHeadersMinimumSize(), builder
.length());
2683 if (protocol_version() > SPDY3
) {
2684 int padding_payload_len
= 0;
2685 if (headers
.padded()) {
2686 builder
.WriteUInt8(headers
.padding_payload_len());
2687 padding_payload_len
= headers
.padding_payload_len();
2689 if (headers
.has_priority()) {
2690 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2691 builder
.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2692 builder
.WriteUInt8(MapPriorityToWeight(priority
));
2694 WritePayloadWithContinuation(&builder
,
2696 headers
.stream_id(),
2698 padding_payload_len
);
2700 SerializeNameValueBlock(&builder
, headers
);
2703 if (debug_visitor_
) {
2704 // SPDY4 uses HPACK for header compression. However, continue to
2705 // use GetSerializedLength() for an apples-to-apples comparision of
2706 // compression performance between HPACK and SPDY w/ deflate.
2707 const size_t payload_len
=
2708 GetSerializedLength(protocol_version(),
2709 &(headers
.name_value_block()));
2710 debug_visitor_
->OnSendCompressedFrame(headers
.stream_id(),
2716 return builder
.take();
2719 SpdySerializedFrame
* SpdyFramer::SerializeWindowUpdate(
2720 const SpdyWindowUpdateIR
& window_update
) const {
2721 SpdyFrameBuilder
builder(GetWindowUpdateSize(), protocol_version());
2722 if (protocol_version() <= SPDY3
) {
2723 builder
.WriteControlFrameHeader(*this, WINDOW_UPDATE
, kNoFlags
);
2724 builder
.WriteUInt32(window_update
.stream_id());
2726 builder
.BeginNewFrame(*this,
2729 window_update
.stream_id());
2731 builder
.WriteUInt32(window_update
.delta());
2732 DCHECK_EQ(GetWindowUpdateSize(), builder
.length());
2733 return builder
.take();
2736 SpdyFrame
* SpdyFramer::SerializeBlocked(const SpdyBlockedIR
& blocked
) const {
2737 DCHECK_LT(SPDY3
, protocol_version());
2738 SpdyFrameBuilder
builder(GetBlockedSize(), protocol_version());
2739 builder
.BeginNewFrame(*this, BLOCKED
, kNoFlags
, blocked
.stream_id());
2740 return builder
.take();
2743 SpdyFrame
* SpdyFramer::SerializePushPromise(
2744 const SpdyPushPromiseIR
& push_promise
) {
2745 DCHECK_LT(SPDY3
, protocol_version());
2747 // This will get overwritten if we overflow into a CONTINUATION frame.
2748 flags
|= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2749 // The size of this frame, including variable-length name-value block.
2750 size_t size
= GetPushPromiseMinimumSize();
2752 if (push_promise
.padded()) {
2753 flags
|= PUSH_PROMISE_FLAG_PADDED
;
2754 size
+= kPadLengthFieldSize
;
2755 size
+= push_promise
.padding_payload_len();
2758 string hpack_encoding
;
2759 if (enable_compression_
) {
2760 GetHpackEncoder()->EncodeHeaderSet(
2761 push_promise
.name_value_block(), &hpack_encoding
);
2763 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2764 push_promise
.name_value_block(), &hpack_encoding
);
2766 size
+= hpack_encoding
.size();
2767 if (size
> kMaxControlFrameSize
) {
2768 size
+= GetNumberRequiredContinuationFrames(size
) *
2769 GetContinuationMinimumSize();
2770 flags
&= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2773 SpdyFrameBuilder
builder(size
, protocol_version());
2774 builder
.BeginNewFrame(*this,
2777 push_promise
.stream_id());
2778 int padding_payload_len
= 0;
2779 if (push_promise
.padded()) {
2780 builder
.WriteUInt8(push_promise
.padding_payload_len());
2781 builder
.WriteUInt32(push_promise
.promised_stream_id());
2782 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize
,
2785 padding_payload_len
= push_promise
.padding_payload_len();
2787 builder
.WriteUInt32(push_promise
.promised_stream_id());
2788 DCHECK_EQ(GetPushPromiseMinimumSize(), builder
.length());
2791 WritePayloadWithContinuation(&builder
,
2793 push_promise
.stream_id(),
2795 padding_payload_len
);
2797 if (debug_visitor_
) {
2798 // SPDY4 uses HPACK for header compression. However, continue to
2799 // use GetSerializedLength() for an apples-to-apples comparision of
2800 // compression performance between HPACK and SPDY w/ deflate.
2801 const size_t payload_len
=
2802 GetSerializedLength(protocol_version(),
2803 &(push_promise
.name_value_block()));
2804 debug_visitor_
->OnSendCompressedFrame(push_promise
.stream_id(),
2810 return builder
.take();
2813 // TODO(jgraettinger): This implementation is incorrect. The continuation
2814 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2815 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2816 SpdyFrame
* SpdyFramer::SerializeContinuation(
2817 const SpdyContinuationIR
& continuation
) {
2818 CHECK_LT(SPDY3
, protocol_version());
2820 if (continuation
.end_headers()) {
2821 flags
|= HEADERS_FLAG_END_HEADERS
;
2824 // The size of this frame, including variable-length name-value block.
2825 size_t size
= GetContinuationMinimumSize();
2826 string hpack_encoding
;
2827 if (enable_compression_
) {
2828 GetHpackEncoder()->EncodeHeaderSet(
2829 continuation
.name_value_block(), &hpack_encoding
);
2831 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2832 continuation
.name_value_block(), &hpack_encoding
);
2834 size
+= hpack_encoding
.size();
2836 SpdyFrameBuilder
builder(size
, protocol_version());
2837 builder
.BeginNewFrame(*this, CONTINUATION
, flags
,
2838 continuation
.stream_id());
2839 DCHECK_EQ(GetContinuationMinimumSize(), builder
.length());
2841 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2842 return builder
.take();
2845 SpdyFrame
* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR
& altsvc
) {
2846 DCHECK_LT(SPDY3
, protocol_version());
2847 size_t size
= GetAltSvcMinimumSize();
2848 size
+= altsvc
.protocol_id().length();
2849 size
+= altsvc
.host().length();
2850 size
+= altsvc
.origin().length();
2852 SpdyFrameBuilder
builder(size
, protocol_version());
2853 builder
.BeginNewFrame(*this, ALTSVC
, kNoFlags
, altsvc
.stream_id());
2855 builder
.WriteUInt32(altsvc
.max_age());
2856 builder
.WriteUInt16(altsvc
.port());
2857 builder
.WriteUInt8(0); // Reserved.
2858 builder
.WriteUInt8(altsvc
.protocol_id().length());
2859 builder
.WriteBytes(altsvc
.protocol_id().data(),
2860 altsvc
.protocol_id().length());
2861 builder
.WriteUInt8(altsvc
.host().length());
2862 builder
.WriteBytes(altsvc
.host().data(), altsvc
.host().length());
2863 builder
.WriteBytes(altsvc
.origin().data(), altsvc
.origin().length());
2864 DCHECK_LT(GetAltSvcMinimumSize(), builder
.length());
2865 return builder
.take();
2868 SpdyFrame
* SpdyFramer::SerializePriority(const SpdyPriorityIR
& priority
) {
2869 DCHECK_LT(SPDY3
, protocol_version());
2870 size_t size
= GetPrioritySize();
2872 SpdyFrameBuilder
builder(size
, protocol_version());
2873 builder
.BeginNewFrame(*this, PRIORITY
, kNoFlags
, priority
.stream_id());
2875 // Make sure the highest-order bit in the parent stream id is zeroed out.
2876 uint32 parent_stream_id
= priority
.parent_stream_id() & 0x7fffffff;
2877 uint32 exclusive
= priority
.exclusive() ? 0x80000000 : 0;
2878 // Set the one-bit exclusivity flag.
2879 uint32 flag_and_parent_id
= parent_stream_id
| exclusive
;
2880 builder
.WriteUInt32(flag_and_parent_id
);
2881 builder
.WriteUInt8(priority
.weight());
2882 DCHECK_EQ(GetPrioritySize(), builder
.length());
2883 return builder
.take();
2888 class FrameSerializationVisitor
: public SpdyFrameVisitor
{
2890 explicit FrameSerializationVisitor(SpdyFramer
* framer
) : framer_(framer
) {}
2891 ~FrameSerializationVisitor() override
{}
2893 SpdySerializedFrame
* ReleaseSerializedFrame() { return frame_
.release(); }
2895 void VisitData(const SpdyDataIR
& data
) override
{
2896 frame_
.reset(framer_
->SerializeData(data
));
2898 void VisitSynStream(const SpdySynStreamIR
& syn_stream
) override
{
2899 frame_
.reset(framer_
->SerializeSynStream(syn_stream
));
2901 void VisitSynReply(const SpdySynReplyIR
& syn_reply
) override
{
2902 frame_
.reset(framer_
->SerializeSynReply(syn_reply
));
2904 void VisitRstStream(const SpdyRstStreamIR
& rst_stream
) override
{
2905 frame_
.reset(framer_
->SerializeRstStream(rst_stream
));
2907 void VisitSettings(const SpdySettingsIR
& settings
) override
{
2908 frame_
.reset(framer_
->SerializeSettings(settings
));
2910 void VisitPing(const SpdyPingIR
& ping
) override
{
2911 frame_
.reset(framer_
->SerializePing(ping
));
2913 void VisitGoAway(const SpdyGoAwayIR
& goaway
) override
{
2914 frame_
.reset(framer_
->SerializeGoAway(goaway
));
2916 void VisitHeaders(const SpdyHeadersIR
& headers
) override
{
2917 frame_
.reset(framer_
->SerializeHeaders(headers
));
2919 void VisitWindowUpdate(const SpdyWindowUpdateIR
& window_update
) override
{
2920 frame_
.reset(framer_
->SerializeWindowUpdate(window_update
));
2922 void VisitBlocked(const SpdyBlockedIR
& blocked
) override
{
2923 frame_
.reset(framer_
->SerializeBlocked(blocked
));
2925 void VisitPushPromise(const SpdyPushPromiseIR
& push_promise
) override
{
2926 frame_
.reset(framer_
->SerializePushPromise(push_promise
));
2928 void VisitContinuation(const SpdyContinuationIR
& continuation
) override
{
2929 frame_
.reset(framer_
->SerializeContinuation(continuation
));
2931 void VisitAltSvc(const SpdyAltSvcIR
& altsvc
) override
{
2932 frame_
.reset(framer_
->SerializeAltSvc(altsvc
));
2934 void VisitPriority(const SpdyPriorityIR
& priority
) override
{
2935 frame_
.reset(framer_
->SerializePriority(priority
));
2939 SpdyFramer
* framer_
;
2940 scoped_ptr
<SpdySerializedFrame
> frame_
;
2945 SpdySerializedFrame
* SpdyFramer::SerializeFrame(const SpdyFrameIR
& frame
) {
2946 FrameSerializationVisitor
visitor(this);
2947 frame
.Visit(&visitor
);
2948 return visitor
.ReleaseSerializedFrame();
2951 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock
& headers
) {
2952 CHECK_GE(SPDY3
, protocol_version());
2953 const size_t uncompressed_length
=
2954 GetSerializedLength(protocol_version(), &headers
);
2955 if (!enable_compression_
) {
2956 return uncompressed_length
;
2958 z_stream
* compressor
= GetHeaderCompressor();
2959 // Since we'll be performing lots of flushes when compressing the data,
2960 // zlib's lower bounds may be insufficient.
2961 return 2 * deflateBound(compressor
, uncompressed_length
);
2964 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size
) {
2965 DCHECK_GT(protocol_version(), SPDY3
);
2966 DCHECK_GT(size
, kMaxControlFrameSize
);
2967 size_t overflow
= size
- kMaxControlFrameSize
;
2968 return overflow
/ (kMaxControlFrameSize
- GetContinuationMinimumSize()) + 1;
2971 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder
* builder
,
2972 const string
& hpack_encoding
,
2973 SpdyStreamId stream_id
,
2975 int padding_payload_len
) {
2978 if (type
== HEADERS
) {
2979 end_flag
= HEADERS_FLAG_END_HEADERS
;
2980 } else if (type
== PUSH_PROMISE
) {
2981 end_flag
= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2983 DLOG(FATAL
) << "CONTINUATION frames cannot be used with frame type "
2984 << FrameTypeToString(type
);
2987 // Write all the padding payload and as much of the data payload as possible
2988 // into the initial frame.
2989 size_t bytes_remaining
= 0;
2990 bytes_remaining
= hpack_encoding
.size() -
2991 std::min(hpack_encoding
.size(),
2992 kMaxControlFrameSize
- builder
->length() -
2993 padding_payload_len
);
2994 builder
->WriteBytes(&hpack_encoding
[0],
2995 hpack_encoding
.size() - bytes_remaining
);
2996 if (padding_payload_len
> 0) {
2997 string padding
= string(padding_payload_len
, 0);
2998 builder
->WriteBytes(padding
.data(), padding
.length());
3000 if (bytes_remaining
> 0) {
3001 builder
->OverwriteLength(*this,
3002 kMaxControlFrameSize
- GetControlFrameHeaderSize());
3005 // Tack on CONTINUATION frames for the overflow.
3006 while (bytes_remaining
> 0) {
3007 size_t bytes_to_write
= std::min(bytes_remaining
,
3008 kMaxControlFrameSize
-
3009 GetContinuationMinimumSize());
3010 // Write CONTINUATION frame prefix.
3011 if (bytes_remaining
== bytes_to_write
) {
3014 builder
->BeginNewFrame(*this,
3018 // Write payload fragment.
3019 builder
->WriteBytes(&hpack_encoding
[hpack_encoding
.size() -
3022 bytes_remaining
-= bytes_to_write
;
3026 // The following compression setting are based on Brian Olson's analysis. See
3027 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
3028 // for more details.
3029 #if defined(USE_SYSTEM_ZLIB)
3030 // System zlib is not expected to have workaround for http://crbug.com/139744,
3031 // so disable compression in that case.
3032 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
3033 static const int kCompressorLevel
= 0;
3034 #else // !defined(USE_SYSTEM_ZLIB)
3035 static const int kCompressorLevel
= 9;
3036 #endif // !defined(USE_SYSTEM_ZLIB)
3037 static const int kCompressorWindowSizeInBits
= 11;
3038 static const int kCompressorMemLevel
= 1;
3040 z_stream
* SpdyFramer::GetHeaderCompressor() {
3041 if (header_compressor_
.get())
3042 return header_compressor_
.get(); // Already initialized.
3044 header_compressor_
.reset(new z_stream
);
3045 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
3047 int success
= deflateInit2(header_compressor_
.get(),
3050 kCompressorWindowSizeInBits
,
3051 kCompressorMemLevel
,
3052 Z_DEFAULT_STRATEGY
);
3053 if (success
== Z_OK
) {
3054 const char* dictionary
= (protocol_version() <= SPDY2
) ?
3055 kV2Dictionary
: kV3Dictionary
;
3056 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3057 kV2DictionarySize
: kV3DictionarySize
;
3058 success
= deflateSetDictionary(header_compressor_
.get(),
3059 reinterpret_cast<const Bytef
*>(dictionary
),
3062 if (success
!= Z_OK
) {
3063 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
3064 header_compressor_
.reset(NULL
);
3067 return header_compressor_
.get();
3070 z_stream
* SpdyFramer::GetHeaderDecompressor() {
3071 if (header_decompressor_
.get())
3072 return header_decompressor_
.get(); // Already initialized.
3074 header_decompressor_
.reset(new z_stream
);
3075 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
3077 int success
= inflateInit(header_decompressor_
.get());
3078 if (success
!= Z_OK
) {
3079 LOG(WARNING
) << "inflateInit failure: " << success
;
3080 header_decompressor_
.reset(NULL
);
3083 return header_decompressor_
.get();
3086 HpackEncoder
* SpdyFramer::GetHpackEncoder() {
3087 DCHECK_LT(SPDY3
, spdy_version_
);
3088 if (hpack_encoder_
.get() == NULL
) {
3089 hpack_encoder_
.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3091 return hpack_encoder_
.get();
3094 HpackDecoder
* SpdyFramer::GetHpackDecoder() {
3095 DCHECK_LT(SPDY3
, spdy_version_
);
3096 if (hpack_decoder_
.get() == NULL
) {
3097 hpack_decoder_
.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3099 return hpack_decoder_
.get();
3102 uint8
SpdyFramer::MapPriorityToWeight(SpdyPriority priority
) {
3103 const float kSteps
= 255.9f
/ 7.f
;
3104 return static_cast<uint8
>(kSteps
* (7.f
- priority
));
3107 SpdyPriority
SpdyFramer::MapWeightToPriority(uint8 weight
) {
3108 const float kSteps
= 255.9f
/ 7.f
;
3109 return static_cast<SpdyPriority
>(7.f
- weight
/ kSteps
);
3112 // Incrementally decompress the control frame's header block, feeding the
3113 // result to the visitor in chunks. Continue this until the visitor
3114 // indicates that it cannot process any more data, or (more commonly) we
3115 // run out of data to deliver.
3116 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3117 SpdyStreamId stream_id
,
3120 // Get a decompressor or set error.
3121 z_stream
* decomp
= GetHeaderDecompressor();
3122 if (decomp
== NULL
) {
3123 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
3124 set_error(SPDY_DECOMPRESS_FAILURE
);
3128 bool processed_successfully
= true;
3129 char buffer
[kHeaderDataChunkMaxSize
];
3131 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
3132 decomp
->avail_in
= len
;
3133 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3134 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3135 // reached this method successfully, stream_id should be nonzero.
3136 DCHECK_LT(0u, stream_id
);
3137 while (decomp
->avail_in
> 0 && processed_successfully
) {
3138 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
3139 decomp
->avail_out
= arraysize(buffer
);
3141 int rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3142 if (rv
== Z_NEED_DICT
) {
3143 const char* dictionary
= (protocol_version() <= SPDY2
) ? kV2Dictionary
3145 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3146 kV2DictionarySize
: kV3DictionarySize
;
3147 const DictionaryIds
& ids
= g_dictionary_ids
.Get();
3148 const uLong dictionary_id
= (protocol_version() <= SPDY2
) ?
3149 ids
.v2_dictionary_id
: ids
.v3_dictionary_id
;
3150 // Need to try again with the right dictionary.
3151 if (decomp
->adler
== dictionary_id
) {
3152 rv
= inflateSetDictionary(decomp
,
3153 reinterpret_cast<const Bytef
*>(dictionary
),
3156 rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3160 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3161 // without producing any output. The input is consumed and
3162 // buffered internally by zlib so we can detect this condition by
3163 // checking if avail_in is 0 after the call to inflate.
3164 bool input_exhausted
= ((rv
== Z_BUF_ERROR
) && (decomp
->avail_in
== 0));
3165 if ((rv
== Z_OK
) || input_exhausted
) {
3166 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
3167 if (decompressed_len
> 0) {
3168 processed_successfully
= visitor_
->OnControlFrameHeaderData(
3169 stream_id
, buffer
, decompressed_len
);
3171 if (!processed_successfully
) {
3172 // Assume that the problem was the header block was too large for the
3174 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3177 DLOG(WARNING
) << "inflate failure: " << rv
<< " " << len
;
3178 set_error(SPDY_DECOMPRESS_FAILURE
);
3179 processed_successfully
= false;
3182 return processed_successfully
;
3185 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3186 SpdyStreamId stream_id
, const char* data
, size_t len
) {
3187 bool read_successfully
= true;
3188 while (read_successfully
&& len
> 0) {
3189 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
3190 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
3192 data
+= bytes_to_deliver
;
3193 len
-= bytes_to_deliver
;
3194 if (!read_successfully
) {
3195 // Assume that the problem was the header block was too large for the
3197 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3200 return read_successfully
;
3203 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3204 SpdyFrameBuilder
* builder
,
3205 const SpdyNameValueBlock
& name_value_block
) const {
3206 // Serialize number of headers.
3207 if (protocol_version() <= SPDY2
) {
3208 builder
->WriteUInt16(name_value_block
.size());
3210 builder
->WriteUInt32(name_value_block
.size());
3213 // Serialize each header.
3214 for (SpdyHeaderBlock::const_iterator it
= name_value_block
.begin();
3215 it
!= name_value_block
.end();
3217 if (protocol_version() <= SPDY2
) {
3218 builder
->WriteString(it
->first
);
3219 builder
->WriteString(it
->second
);
3221 builder
->WriteStringPiece32(it
->first
);
3222 builder
->WriteStringPiece32(it
->second
);
3227 void SpdyFramer::SerializeNameValueBlock(
3228 SpdyFrameBuilder
* builder
,
3229 const SpdyFrameWithNameValueBlockIR
& frame
) {
3230 CHECK_GE(SPDY3
, protocol_version());
3231 if (!enable_compression_
) {
3232 return SerializeNameValueBlockWithoutCompression(builder
,
3233 frame
.name_value_block());
3236 // First build an uncompressed version to be fed into the compressor.
3237 const size_t uncompressed_len
= GetSerializedLength(
3238 protocol_version(), &(frame
.name_value_block()));
3239 SpdyFrameBuilder
uncompressed_builder(uncompressed_len
, protocol_version());
3240 SerializeNameValueBlockWithoutCompression(&uncompressed_builder
,
3241 frame
.name_value_block());
3242 scoped_ptr
<SpdyFrame
> uncompressed_payload(uncompressed_builder
.take());
3244 z_stream
* compressor
= GetHeaderCompressor();
3246 LOG(DFATAL
) << "Could not obtain compressor.";
3250 base::StatsCounter
compressed_frames("spdy.CompressedFrames");
3251 base::StatsCounter
pre_compress_bytes("spdy.PreCompressSize");
3252 base::StatsCounter
post_compress_bytes("spdy.PostCompressSize");
3254 // Create an output frame.
3255 // Since we'll be performing lots of flushes when compressing the data,
3256 // zlib's lower bounds may be insufficient.
3258 // TODO(akalin): Avoid the duplicate calculation with
3259 // GetSerializedLength(const SpdyHeaderBlock&).
3260 const int compressed_max_size
=
3261 2 * deflateBound(compressor
, uncompressed_len
);
3263 // TODO(phajdan.jr): Clean up after we no longer need
3264 // to workaround http://crbug.com/139744.
3265 #if defined(USE_SYSTEM_ZLIB)
3266 compressor
->next_in
= reinterpret_cast<Bytef
*>(uncompressed_payload
->data());
3267 compressor
->avail_in
= uncompressed_len
;
3268 #endif // defined(USE_SYSTEM_ZLIB)
3269 compressor
->next_out
= reinterpret_cast<Bytef
*>(
3270 builder
->GetWritableBuffer(compressed_max_size
));
3271 compressor
->avail_out
= compressed_max_size
;
3273 // TODO(phajdan.jr): Clean up after we no longer need
3274 // to workaround http://crbug.com/139744.
3275 #if defined(USE_SYSTEM_ZLIB)
3276 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
3277 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
3278 // This shouldn't happen, right?
3279 LOG(WARNING
) << "deflate failure: " << rv
;
3280 // TODO(akalin): Upstream this return.
3284 WriteHeaderBlockToZ(&frame
.name_value_block(), compressor
);
3285 #endif // defined(USE_SYSTEM_ZLIB)
3287 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
3288 builder
->Seek(compressed_size
);
3289 builder
->RewriteLength(*this);
3291 pre_compress_bytes
.Add(uncompressed_len
);
3292 post_compress_bytes
.Add(compressed_size
);
3294 compressed_frames
.Increment();