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 struct DictionaryIds
{
36 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary
, kV2DictionarySize
)),
37 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary
, kV3DictionarySize
))
39 const uLong v2_dictionary_id
;
40 const uLong v3_dictionary_id
;
43 // Adler ID for the SPDY header compressor dictionaries. Note that they are
44 // initialized lazily to avoid static initializers.
45 base::LazyInstance
<DictionaryIds
>::Leaky g_dictionary_ids
;
47 // Used to indicate no flags in a SPDY flags field.
48 const uint8 kNoFlags
= 0;
50 // Wire sizes of priority payloads.
51 const size_t kPriorityDependencyPayloadSize
= 4;
52 const size_t kPriorityWeightPayloadSize
= 1;
56 const SpdyStreamId
SpdyFramer::kInvalidStream
= -1;
57 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
58 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
59 // calculation details.
60 const size_t SpdyFramer::kControlFrameBufferSize
= 18;
62 #ifdef DEBUG_SPDY_STATE_CHANGES
63 #define CHANGE_STATE(newstate) \
65 DVLOG(1) << "Changing state from: " \
66 << StateToString(state_) \
67 << " to " << StateToString(newstate) << "\n"; \
68 DCHECK(state_ != SPDY_ERROR); \
69 DCHECK_EQ(previous_state_, state_); \
70 previous_state_ = state_; \
74 #define CHANGE_STATE(newstate) \
76 DCHECK(state_ != SPDY_ERROR); \
77 DCHECK_EQ(previous_state_, state_); \
78 previous_state_ = state_; \
83 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(
84 SpdyMajorVersion version
, uint32 wire
) {
85 if (version
< SPDY3
) {
86 ConvertFlagsAndIdForSpdy2(&wire
);
88 return SettingsFlagsAndId(ntohl(wire
) >> 24, ntohl(wire
) & 0x00ffffff);
91 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags
, uint32 id
)
92 : flags_(flags
), id_(id
& 0x00ffffff) {
93 LOG_IF(DFATAL
, id
> (1u << 24)) << "SPDY setting ID too large: " << id
;
96 uint32
SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version
)
98 uint32 wire
= htonl(id_
& 0x00ffffff) | htonl(flags_
<< 24);
99 if (version
< SPDY3
) {
100 ConvertFlagsAndIdForSpdy2(&wire
);
105 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
106 // This method is used to preserve buggy behavior and works on both
107 // little-endian and big-endian hosts.
108 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
109 // as well as vice versa).
110 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32
* val
) {
111 uint8
* wire_array
= reinterpret_cast<uint8
*>(val
);
112 std::swap(wire_array
[0], wire_array
[3]);
113 std::swap(wire_array
[1], wire_array
[2]);
116 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
117 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
119 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data
,
124 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
125 const char* rst_stream_data
,
130 SpdyFramer::SpdyFramer(SpdyMajorVersion version
)
131 : current_frame_buffer_(new char[kControlFrameBufferSize
]),
132 enable_compression_(true),
134 debug_visitor_(NULL
),
135 display_protocol_("SPDY"),
136 spdy_version_(version
),
137 syn_frame_processed_(false),
138 probable_http_response_(false),
139 expect_continuation_(0),
140 end_stream_when_done_(false) {
141 DCHECK_GE(spdy_version_
, SPDY_MIN_VERSION
);
142 DCHECK_LE(spdy_version_
, SPDY_MAX_VERSION
);
146 SpdyFramer::~SpdyFramer() {
147 if (header_compressor_
.get()) {
148 deflateEnd(header_compressor_
.get());
150 if (header_decompressor_
.get()) {
151 inflateEnd(header_decompressor_
.get());
155 void SpdyFramer::Reset() {
157 previous_state_
= SPDY_RESET
;
158 error_code_
= SPDY_NO_ERROR
;
159 remaining_data_length_
= 0;
160 remaining_control_header_
= 0;
161 current_frame_buffer_length_
= 0;
162 current_frame_type_
= DATA
;
163 current_frame_flags_
= 0;
164 current_frame_length_
= 0;
165 current_frame_stream_id_
= kInvalidStream
;
166 settings_scratch_
.Reset();
167 altsvc_scratch_
.Reset();
168 remaining_padding_payload_length_
= 0;
169 remaining_padding_length_fields_
= 0;
172 size_t SpdyFramer::GetDataFrameMinimumSize() const {
173 return SpdyConstants::GetDataFrameMinimumSize();
176 // Size, in bytes, of the control frame header.
177 size_t SpdyFramer::GetControlFrameHeaderSize() const {
178 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
181 size_t SpdyFramer::GetSynStreamMinimumSize() const {
182 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
184 if (protocol_version() <= SPDY3
) {
186 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
187 // + 1 (unused, was credential slot)
188 return GetControlFrameHeaderSize() + 10;
190 return GetControlFrameHeaderSize() +
191 kPriorityDependencyPayloadSize
+
192 kPriorityWeightPayloadSize
;
196 size_t SpdyFramer::GetSynReplyMinimumSize() const {
197 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
199 size_t size
= GetControlFrameHeaderSize();
200 if (protocol_version() <= SPDY3
) {
202 // control frame header + 4 (stream IDs)
206 // In SPDY 2, there were 2 unused bytes before payload.
207 if (protocol_version() < SPDY3
) {
214 size_t SpdyFramer::GetRstStreamMinimumSize() const {
215 // Size, in bytes, of a RST_STREAM frame.
216 if (protocol_version() <= SPDY3
) {
218 // control frame header + 4 (stream id) + 4 (status code)
219 return GetControlFrameHeaderSize() + 8;
222 // frame prefix + 4 (status code)
223 return GetControlFrameHeaderSize() + 4;
227 size_t SpdyFramer::GetSettingsMinimumSize() const {
228 // Size, in bytes, of a SETTINGS frame not including the IDs and values
229 // from the variable-length value block. Calculated as:
230 // control frame header + 4 (number of ID/value pairs)
231 if (protocol_version() <= SPDY3
) {
232 return GetControlFrameHeaderSize() + 4;
234 return GetControlFrameHeaderSize();
238 size_t SpdyFramer::GetPingSize() const {
239 // Size, in bytes, of this PING frame.
240 if (protocol_version() <= SPDY3
) {
242 // control frame header + 4 (id)
243 return GetControlFrameHeaderSize() + 4;
246 // control frame header + 8 (id)
247 return GetControlFrameHeaderSize() + 8;
251 size_t SpdyFramer::GetGoAwayMinimumSize() const {
252 // Size, in bytes, of this GOAWAY frame. Calculated as:
253 // 1. Control frame header size
254 size_t size
= GetControlFrameHeaderSize();
256 // 2. Last good stream id (4 bytes)
259 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
260 if (protocol_version() >= SPDY3
) {
267 size_t SpdyFramer::GetHeadersMinimumSize() const {
268 // Size, in bytes, of a HEADERS frame not including the variable-length
270 size_t size
= GetControlFrameHeaderSize();
271 if (protocol_version() <= SPDY3
) {
273 // control frame header + 4 (stream IDs)
277 // In SPDY 2, there were 2 unused bytes before payload.
278 if (protocol_version() <= SPDY2
) {
285 size_t SpdyFramer::GetWindowUpdateSize() const {
286 // Size, in bytes, of a WINDOW_UPDATE frame.
287 if (protocol_version() <= SPDY3
) {
289 // control frame header + 4 (stream id) + 4 (delta)
290 return GetControlFrameHeaderSize() + 8;
293 // frame prefix + 4 (delta)
294 return GetControlFrameHeaderSize() + 4;
298 size_t SpdyFramer::GetBlockedSize() const {
299 DCHECK_LT(SPDY3
, protocol_version());
300 // Size, in bytes, of a BLOCKED frame.
301 // The BLOCKED frame has no payload beyond the control frame header.
302 return GetControlFrameHeaderSize();
305 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
306 DCHECK_LT(SPDY3
, protocol_version());
307 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
308 // Calculated as frame prefix + 4 (promised stream id).
309 return GetControlFrameHeaderSize() + 4;
312 size_t SpdyFramer::GetContinuationMinimumSize() const {
313 // Size, in bytes, of a CONTINUATION frame not including the variable-length
314 // headers fragments.
315 return GetControlFrameHeaderSize();
318 size_t SpdyFramer::GetAltSvcMinimumSize() const {
319 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
320 // (optional) Origin fields, all of which can vary in length.
321 // Note that this gives a lower bound on the frame size rather than a true
322 // minimum; the actual frame should always be larger than this.
323 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
324 // + 1 (pid_len) + 1 (host_len).
325 return GetControlFrameHeaderSize() + 9;
328 size_t SpdyFramer::GetPrioritySize() const {
329 // Size, in bytes, of a PRIORITY frame.
330 return GetControlFrameHeaderSize() +
331 kPriorityDependencyPayloadSize
+
332 kPriorityWeightPayloadSize
;
335 size_t SpdyFramer::GetFrameMinimumSize() const {
336 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
339 size_t SpdyFramer::GetFrameMaximumSize() const {
340 return SpdyConstants::GetFrameMaximumSize(protocol_version());
343 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
344 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
347 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type
) const {
348 return SpdyConstants::GetPrefixLength(type
, protocol_version());
351 const char* SpdyFramer::StateToString(int state
) {
355 case SPDY_AUTO_RESET
:
359 case SPDY_READING_COMMON_HEADER
:
360 return "READING_COMMON_HEADER";
361 case SPDY_CONTROL_FRAME_PAYLOAD
:
362 return "CONTROL_FRAME_PAYLOAD";
363 case SPDY_READ_PADDING_LENGTH
:
364 return "SPDY_READ_PADDING_LENGTH";
365 case SPDY_CONSUME_PADDING
:
366 return "SPDY_CONSUME_PADDING";
367 case SPDY_IGNORE_REMAINING_PAYLOAD
:
368 return "IGNORE_REMAINING_PAYLOAD";
369 case SPDY_FORWARD_STREAM_FRAME
:
370 return "FORWARD_STREAM_FRAME";
371 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
372 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
373 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
374 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
375 case SPDY_GOAWAY_FRAME_PAYLOAD
:
376 return "SPDY_GOAWAY_FRAME_PAYLOAD";
377 case SPDY_RST_STREAM_FRAME_PAYLOAD
:
378 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
379 case SPDY_SETTINGS_FRAME_PAYLOAD
:
380 return "SPDY_SETTINGS_FRAME_PAYLOAD";
381 case SPDY_ALTSVC_FRAME_PAYLOAD
:
382 return "SPDY_ALTSVC_FRAME_PAYLOAD";
384 return "UNKNOWN_STATE";
387 void SpdyFramer::set_error(SpdyError error
) {
390 // These values will usually get reset once we come to the end
391 // of a header block, but if we run into an error that
392 // might not happen, so reset them here.
393 expect_continuation_
= 0;
394 end_stream_when_done_
= false;
396 CHANGE_STATE(SPDY_ERROR
);
397 visitor_
->OnError(this);
400 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
401 switch (error_code
) {
404 case SPDY_INVALID_CONTROL_FRAME
:
405 return "INVALID_CONTROL_FRAME";
406 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
407 return "CONTROL_PAYLOAD_TOO_LARGE";
408 case SPDY_ZLIB_INIT_FAILURE
:
409 return "ZLIB_INIT_FAILURE";
410 case SPDY_UNSUPPORTED_VERSION
:
411 return "UNSUPPORTED_VERSION";
412 case SPDY_DECOMPRESS_FAILURE
:
413 return "DECOMPRESS_FAILURE";
414 case SPDY_COMPRESS_FAILURE
:
415 return "COMPRESS_FAILURE";
416 case SPDY_INVALID_DATA_FRAME_FLAGS
:
417 return "SPDY_INVALID_DATA_FRAME_FLAGS";
418 case SPDY_INVALID_CONTROL_FRAME_FLAGS
:
419 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
420 case SPDY_UNEXPECTED_FRAME
:
421 return "UNEXPECTED_FRAME";
423 return "UNKNOWN_ERROR";
426 const char* SpdyFramer::StatusCodeToString(int status_code
) {
427 switch (status_code
) {
428 case RST_STREAM_INVALID
:
430 case RST_STREAM_PROTOCOL_ERROR
:
431 return "PROTOCOL_ERROR";
432 case RST_STREAM_INVALID_STREAM
:
433 return "INVALID_STREAM";
434 case RST_STREAM_REFUSED_STREAM
:
435 return "REFUSED_STREAM";
436 case RST_STREAM_UNSUPPORTED_VERSION
:
437 return "UNSUPPORTED_VERSION";
438 case RST_STREAM_CANCEL
:
440 case RST_STREAM_INTERNAL_ERROR
:
441 return "INTERNAL_ERROR";
442 case RST_STREAM_FLOW_CONTROL_ERROR
:
443 return "FLOW_CONTROL_ERROR";
444 case RST_STREAM_STREAM_IN_USE
:
445 return "STREAM_IN_USE";
446 case RST_STREAM_STREAM_ALREADY_CLOSED
:
447 return "STREAM_ALREADY_CLOSED";
448 case RST_STREAM_INVALID_CREDENTIALS
:
449 return "INVALID_CREDENTIALS";
450 case RST_STREAM_FRAME_TOO_LARGE
:
451 return "FRAME_TOO_LARGE";
452 case RST_STREAM_CONNECT_ERROR
:
453 return "CONNECT_ERROR";
454 case RST_STREAM_ENHANCE_YOUR_CALM
:
455 return "ENHANCE_YOUR_CALM";
457 return "UNKNOWN_STATUS";
460 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type
) {
481 return "WINDOW_UPDATE";
487 return "PUSH_PROMISE";
489 return "CONTINUATION";
495 return "UNKNOWN_CONTROL_TYPE";
498 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
502 size_t original_len
= len
;
504 previous_state_
= state_
;
509 case SPDY_AUTO_RESET
:
513 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
517 case SPDY_READING_COMMON_HEADER
: {
518 size_t bytes_read
= ProcessCommonHeader(data
, len
);
524 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
525 // Control frames that contain header blocks
526 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
527 // take a different path through the state machine - they
529 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
530 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
532 // SETTINGS frames take a slightly modified route:
533 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
534 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
536 // All other control frames will use the alternate route directly to
537 // SPDY_CONTROL_FRAME_PAYLOAD
538 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
544 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
545 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
551 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
552 int bytes_read
= ProcessControlFrameHeaderBlock(
553 data
, len
, protocol_version() > SPDY3
);
559 case SPDY_RST_STREAM_FRAME_PAYLOAD
: {
560 size_t bytes_read
= ProcessRstStreamFramePayload(data
, len
);
566 case SPDY_GOAWAY_FRAME_PAYLOAD
: {
567 size_t bytes_read
= ProcessGoAwayFramePayload(data
, len
);
573 case SPDY_ALTSVC_FRAME_PAYLOAD
: {
574 size_t bytes_read
= ProcessAltSvcFramePayload(data
, len
);
580 case SPDY_CONTROL_FRAME_PAYLOAD
: {
581 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
587 case SPDY_READ_PADDING_LENGTH
: {
588 size_t bytes_read
= ProcessFramePaddingLength(data
, len
);
594 case SPDY_CONSUME_PADDING
: {
595 size_t bytes_read
= ProcessFramePadding(data
, len
);
601 case SPDY_IGNORE_REMAINING_PAYLOAD
: {
602 size_t bytes_read
= ProcessIgnoredControlFramePayload(/*data,*/ len
);
608 case SPDY_FORWARD_STREAM_FRAME
: {
609 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
616 LOG(DFATAL
) << "Invalid value for " << display_protocol_
617 << " framer state: " << state_
;
618 // This ensures that we don't infinite-loop if state_ gets an
619 // invalid value somehow, such as due to a SpdyFramer getting deleted
620 // from a callback it calls.
623 } while (state_
!= previous_state_
);
625 DCHECK(len
== 0 || state_
== SPDY_ERROR
);
626 if (current_frame_buffer_length_
== 0 &&
627 remaining_data_length_
== 0 &&
628 remaining_control_header_
== 0) {
629 DCHECK(state_
== SPDY_RESET
|| state_
== SPDY_ERROR
)
630 << "State: " << StateToString(state_
);
633 return original_len
- len
;
636 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
637 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
639 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
641 size_t original_len
= len
;
643 // Update current frame buffer as needed.
644 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
645 size_t bytes_desired
=
646 GetControlFrameHeaderSize() - current_frame_buffer_length_
;
647 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
650 if (current_frame_buffer_length_
< GetControlFrameHeaderSize()) {
651 // Not enough information to do anything meaningful.
652 return original_len
- len
;
655 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
656 // when processing DATA frames below.
657 scoped_ptr
<SpdyFrameReader
> reader(
658 new SpdyFrameReader(current_frame_buffer_
.get(),
659 current_frame_buffer_length_
));
662 bool is_control_frame
= false;
664 uint16 control_frame_type_field
= DATA
;
665 // ProcessControlFrameHeader() will set current_frame_type_ to the
666 // correct value if this is a valid control frame.
667 current_frame_type_
= DATA
;
668 if (protocol_version() <= SPDY3
) {
669 bool successful_read
= reader
->ReadUInt16(&version
);
670 DCHECK(successful_read
);
671 is_control_frame
= (version
& kControlFlagMask
) != 0;
672 version
&= ~kControlFlagMask
; // Only valid for control frames.
673 if (is_control_frame
) {
674 // We check version before we check validity: version can never be
675 // 'invalid', it can only be unsupported.
676 if (version
< SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION
) ||
677 version
> SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION
) ||
678 SpdyConstants::ParseMajorVersion(version
) != protocol_version()) {
679 // Version does not match the version the framer was initialized with.
680 DVLOG(1) << "Unsupported SPDY version "
682 << " (expected " << protocol_version() << ")";
683 set_error(SPDY_UNSUPPORTED_VERSION
);
686 // Convert version from wire format to SpdyMajorVersion.
687 version
= SpdyConstants::ParseMajorVersion(version
);
689 // We check control_frame_type_field's validity in
690 // ProcessControlFrameHeader().
691 successful_read
= reader
->ReadUInt16(&control_frame_type_field
);
694 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
696 DCHECK(successful_read
);
698 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
699 DCHECK(successful_read
);
701 uint32 length_field
= 0;
702 successful_read
= reader
->ReadUInt24(&length_field
);
703 DCHECK(successful_read
);
704 remaining_data_length_
= length_field
;
705 current_frame_length_
= remaining_data_length_
+ reader
->GetBytesConsumed();
707 version
= protocol_version();
708 uint16 length_field
= 0;
709 bool successful_read
= reader
->ReadUInt16(&length_field
);
710 DCHECK(successful_read
);
712 uint8 control_frame_type_field_uint8
= DATA
;
713 successful_read
= reader
->ReadUInt8(&control_frame_type_field_uint8
);
714 DCHECK(successful_read
);
715 // We check control_frame_type_field's validity in
716 // ProcessControlFrameHeader().
717 control_frame_type_field
= control_frame_type_field_uint8
;
718 is_control_frame
= (control_frame_type_field
!= DATA
);
720 if (is_control_frame
) {
721 current_frame_length_
= length_field
+ GetControlFrameHeaderSize();
723 current_frame_length_
= length_field
+ GetDataFrameMinimumSize();
726 successful_read
= reader
->ReadUInt8(¤t_frame_flags_
);
727 DCHECK(successful_read
);
729 successful_read
= reader
->ReadUInt31(¤t_frame_stream_id_
);
730 DCHECK(successful_read
);
732 remaining_data_length_
= current_frame_length_
- reader
->GetBytesConsumed();
734 // Before we accept a DATA frame, we need to make sure we're not in the
735 // middle of processing a header block.
736 const bool is_continuation_frame
= (control_frame_type_field
==
737 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION
));
738 if ((expect_continuation_
!= 0) != is_continuation_frame
) {
739 if (expect_continuation_
!= 0) {
740 DLOG(ERROR
) << "The framer was expecting to receive a CONTINUATION "
741 << "frame, but instead received frame type "
742 << control_frame_type_field
;
744 DLOG(ERROR
) << "The framer received an unexpected CONTINUATION frame.";
746 set_error(SPDY_UNEXPECTED_FRAME
);
747 return original_len
- len
;
750 DCHECK_EQ(is_control_frame
? GetControlFrameHeaderSize()
751 : GetDataFrameMinimumSize(),
752 reader
->GetBytesConsumed());
753 DCHECK_EQ(current_frame_length_
,
754 remaining_data_length_
+ reader
->GetBytesConsumed());
756 // This is just a sanity check for help debugging early frame errors.
757 if (remaining_data_length_
> 1000000u) {
758 // The strncmp for 5 is safe because we only hit this point if we
759 // have kMinCommonHeader (8) bytes
760 if (!syn_frame_processed_
&&
761 strncmp(current_frame_buffer_
.get(), "HTTP/", 5) == 0) {
762 LOG(WARNING
) << "Unexpected HTTP response to " << display_protocol_
764 probable_http_response_
= true;
766 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
767 << " session is likely corrupt.";
771 // if we're here, then we have the common header all received.
772 if (!is_control_frame
) {
773 if (protocol_version() > SPDY3
) {
774 // Catch bogus tests sending oversized DATA frames.
775 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_
)
776 << "DATA frame too large for SPDY >= 4.";
779 uint8 valid_data_flags
= 0;
780 if (protocol_version() > SPDY3
) {
781 valid_data_flags
= DATA_FLAG_FIN
| DATA_FLAG_END_SEGMENT
|
782 DATA_FLAG_PAD_LOW
| DATA_FLAG_PAD_HIGH
;
784 valid_data_flags
= DATA_FLAG_FIN
;
787 if (current_frame_flags_
& ~valid_data_flags
) {
788 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
790 visitor_
->OnDataFrameHeader(current_frame_stream_id_
,
791 remaining_data_length_
,
792 current_frame_flags_
& DATA_FLAG_FIN
);
793 if (remaining_data_length_
> 0) {
794 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
797 if (current_frame_flags_
& DATA_FLAG_FIN
) {
798 visitor_
->OnStreamFrameData(
799 current_frame_stream_id_
, NULL
, 0, true);
801 CHANGE_STATE(SPDY_AUTO_RESET
);
805 ProcessControlFrameHeader(control_frame_type_field
);
808 return original_len
- len
;
811 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field
) {
812 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
813 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_
);
815 // Early detection of deprecated frames that we ignore.
816 if (protocol_version() <= SPDY3
) {
817 if (control_frame_type_field
== NOOP
) {
818 current_frame_type_
= NOOP
;
819 DVLOG(1) << "NOOP control frame found. Ignoring.";
820 CHANGE_STATE(SPDY_AUTO_RESET
);
824 if (control_frame_type_field
== CREDENTIAL
) {
825 current_frame_type_
= CREDENTIAL
;
826 DCHECK_EQ(SPDY3
, protocol_version());
827 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
828 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
833 if (!SpdyConstants::IsValidFrameType(protocol_version(),
834 control_frame_type_field
)) {
835 DLOG(WARNING
) << "Invalid control frame type " << control_frame_type_field
836 << " (protocol version: " << protocol_version() << ")";
837 set_error(SPDY_INVALID_CONTROL_FRAME
);
841 current_frame_type_
= SpdyConstants::ParseFrameType(protocol_version(),
842 control_frame_type_field
);
844 // Do some sanity checking on the control frame sizes and flags.
845 switch (current_frame_type_
) {
847 if (current_frame_length_
< GetSynStreamMinimumSize()) {
848 set_error(SPDY_INVALID_CONTROL_FRAME
);
849 } else if (current_frame_flags_
&
850 ~(CONTROL_FLAG_FIN
| CONTROL_FLAG_UNIDIRECTIONAL
)) {
851 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
855 if (current_frame_length_
< GetSynReplyMinimumSize()) {
856 set_error(SPDY_INVALID_CONTROL_FRAME
);
857 } else if (current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
858 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
862 // For SPDY versions < 4, the header has a fixed length.
863 // For SPDY version 4 and up, the RST_STREAM frame may include optional
864 // opaque data, so we only have a lower limit on the frame size.
865 if ((current_frame_length_
!= GetRstStreamMinimumSize() &&
866 protocol_version() <= SPDY3
) ||
867 (current_frame_length_
< GetRstStreamMinimumSize() &&
868 protocol_version() > SPDY3
)) {
869 set_error(SPDY_INVALID_CONTROL_FRAME
);
870 } else if (current_frame_flags_
!= 0) {
871 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
876 // Make sure that we have an integral number of 8-byte key/value pairs,
877 // plus a 4-byte length field in SPDY3 and below.
878 size_t values_prefix_size
= (protocol_version() <= SPDY3
? 4 : 0);
879 // Size of each key/value pair in bytes.
880 size_t setting_size
= (protocol_version() <= SPDY3
? 8 : 5);
881 if (current_frame_length_
< GetSettingsMinimumSize() ||
882 (current_frame_length_
- GetControlFrameHeaderSize())
883 % setting_size
!= values_prefix_size
) {
884 DLOG(WARNING
) << "Invalid length for SETTINGS frame: "
885 << current_frame_length_
;
886 set_error(SPDY_INVALID_CONTROL_FRAME
);
887 } else if (protocol_version() <= SPDY3
&&
888 current_frame_flags_
&
889 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
) {
890 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
891 } else if (protocol_version() > SPDY3
&&
892 current_frame_flags_
& ~SETTINGS_FLAG_ACK
) {
893 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
894 } else if (protocol_version() > SPDY3
&&
895 current_frame_flags_
& SETTINGS_FLAG_ACK
&&
896 current_frame_length_
> GetSettingsMinimumSize()) {
897 set_error(SPDY_INVALID_CONTROL_FRAME
);
902 if (current_frame_length_
!= GetPingSize()) {
903 set_error(SPDY_INVALID_CONTROL_FRAME
);
904 } else if ((protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) ||
905 (current_frame_flags_
& ~PING_FLAG_ACK
)) {
906 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
911 // For SPDY version < 4, there are only mandatory fields and the header
912 // has a fixed length. For SPDY version >= 4, optional opaque data may
913 // be appended to the GOAWAY frame, thus there is only a minimal length
915 if ((current_frame_length_
!= GetGoAwayMinimumSize() &&
916 protocol_version() <= SPDY3
) ||
917 (current_frame_length_
< GetGoAwayMinimumSize() &&
918 protocol_version() > SPDY3
)) {
919 set_error(SPDY_INVALID_CONTROL_FRAME
);
920 } else if (current_frame_flags_
!= 0) {
921 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
927 size_t min_size
= GetHeadersMinimumSize();
928 if (protocol_version() > SPDY3
&&
929 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
)) {
932 if (current_frame_length_
< min_size
) {
933 set_error(SPDY_INVALID_CONTROL_FRAME
);
934 } else if (protocol_version() <= SPDY3
&&
935 current_frame_flags_
& ~CONTROL_FLAG_FIN
) {
936 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
937 } else if (protocol_version() > SPDY3
&&
938 current_frame_flags_
&
939 ~(CONTROL_FLAG_FIN
| HEADERS_FLAG_PRIORITY
|
940 HEADERS_FLAG_END_HEADERS
| HEADERS_FLAG_END_SEGMENT
|
941 HEADERS_FLAG_PAD_LOW
| HEADERS_FLAG_PAD_HIGH
)) {
942 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
947 if (current_frame_length_
!= GetWindowUpdateSize()) {
948 set_error(SPDY_INVALID_CONTROL_FRAME
);
949 } else if (current_frame_flags_
!= 0) {
950 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
954 if (current_frame_length_
!= GetBlockedSize() ||
955 protocol_version() <= SPDY3
) {
956 // TODO(mlavan): BLOCKED frames are no longer part of SPDY4.
957 set_error(SPDY_INVALID_CONTROL_FRAME
);
958 } else if (current_frame_flags_
!= 0) {
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
963 if (current_frame_length_
< GetPushPromiseMinimumSize()) {
964 set_error(SPDY_INVALID_CONTROL_FRAME
);
965 } else if (protocol_version() <= SPDY3
&& current_frame_flags_
!= 0) {
966 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
967 } else if (protocol_version() > SPDY3
&&
968 current_frame_flags_
&
969 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE
|
970 HEADERS_FLAG_PAD_LOW
| HEADERS_FLAG_PAD_HIGH
)) {
971 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
975 if (current_frame_length_
< GetContinuationMinimumSize() ||
976 protocol_version() <= SPDY3
) {
977 set_error(SPDY_INVALID_CONTROL_FRAME
);
978 } else if (current_frame_flags_
&
979 ~(HEADERS_FLAG_END_HEADERS
| HEADERS_FLAG_PAD_LOW
|
980 HEADERS_FLAG_PAD_HIGH
)) {
981 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
985 if (current_frame_length_
<= GetAltSvcMinimumSize()) {
986 set_error(SPDY_INVALID_CONTROL_FRAME
);
987 } else if (current_frame_flags_
!= 0) {
988 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
992 if (current_frame_length_
!= GetPrioritySize() ||
993 protocol_version() <= SPDY3
) {
994 set_error(SPDY_INVALID_CONTROL_FRAME
);
995 } else if (current_frame_flags_
!= 0) {
996 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS
);
1000 LOG(WARNING
) << "Valid " << display_protocol_
1001 << " control frame with unhandled type: "
1002 << current_frame_type_
;
1003 // This branch should be unreachable because of the frame type bounds
1004 // check above. However, we DLOG(FATAL) here in an effort to painfully
1005 // club the head of the developer who failed to keep this file in sync
1006 // with spdy_protocol.h.
1008 set_error(SPDY_INVALID_CONTROL_FRAME
);
1012 if (state_
== SPDY_ERROR
) {
1016 if (current_frame_length_
> GetControlFrameBufferMaxSize()) {
1017 DLOG(WARNING
) << "Received control frame with way too big of a payload: "
1018 << current_frame_length_
;
1019 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1023 if (current_frame_type_
== GOAWAY
) {
1024 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD
);
1028 if (current_frame_type_
== RST_STREAM
) {
1029 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD
);
1033 if (current_frame_type_
== ALTSVC
) {
1034 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD
);
1037 // Determine the frame size without variable-length data.
1038 int32 frame_size_without_variable_data
;
1039 switch (current_frame_type_
) {
1041 syn_frame_processed_
= true;
1042 frame_size_without_variable_data
= GetSynStreamMinimumSize();
1045 syn_frame_processed_
= true;
1046 frame_size_without_variable_data
= GetSynReplyMinimumSize();
1049 frame_size_without_variable_data
= GetSettingsMinimumSize();
1052 frame_size_without_variable_data
= GetHeadersMinimumSize();
1053 if (protocol_version() > SPDY3
&&
1054 current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1055 frame_size_without_variable_data
+=
1056 kPriorityDependencyPayloadSize
+
1057 kPriorityWeightPayloadSize
;
1061 frame_size_without_variable_data
= GetPushPromiseMinimumSize();
1064 frame_size_without_variable_data
= GetContinuationMinimumSize();
1067 frame_size_without_variable_data
= -1;
1071 if ((frame_size_without_variable_data
== -1) &&
1072 (current_frame_length_
> kControlFrameBufferSize
)) {
1073 // We should already be in an error state. Double-check.
1074 DCHECK_EQ(SPDY_ERROR
, state_
);
1075 if (state_
!= SPDY_ERROR
) {
1076 LOG(DFATAL
) << display_protocol_
1077 << " control frame buffer too small for fixed-length frame.";
1078 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1083 if (frame_size_without_variable_data
> 0) {
1084 // We have a control frame with a header block. We need to parse the
1085 // remainder of the control frame's header before we can parse the header
1086 // block. The start of the header block varies with the control type.
1087 DCHECK_GE(frame_size_without_variable_data
,
1088 static_cast<int32
>(current_frame_buffer_length_
));
1089 remaining_control_header_
= frame_size_without_variable_data
-
1090 current_frame_buffer_length_
;
1092 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
1096 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
1099 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
1101 size_t bytes_to_read
= std::min(*len
, max_bytes
);
1102 if (bytes_to_read
> 0) {
1103 DCHECK_GE(kControlFrameBufferSize
,
1104 current_frame_buffer_length_
+ bytes_to_read
);
1105 memcpy(current_frame_buffer_
.get() + current_frame_buffer_length_
,
1108 current_frame_buffer_length_
+= bytes_to_read
;
1109 *data
+= bytes_to_read
;
1110 *len
-= bytes_to_read
;
1112 return bytes_to_read
;
1115 size_t SpdyFramer::GetSerializedLength(
1116 const SpdyMajorVersion spdy_version
,
1117 const SpdyHeaderBlock
* headers
) {
1118 const size_t num_name_value_pairs_size
1119 = (spdy_version
< SPDY3
) ? sizeof(uint16
) : sizeof(uint32
);
1120 const size_t length_of_name_size
= num_name_value_pairs_size
;
1121 const size_t length_of_value_size
= num_name_value_pairs_size
;
1123 size_t total_length
= num_name_value_pairs_size
;
1124 for (SpdyHeaderBlock::const_iterator it
= headers
->begin();
1125 it
!= headers
->end();
1127 // We add space for the length of the name and the length of the value as
1128 // well as the length of the name and the length of the value.
1129 total_length
+= length_of_name_size
+ it
->first
.size() +
1130 length_of_value_size
+ it
->second
.size();
1132 return total_length
;
1135 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder
* frame
,
1136 const SpdyMajorVersion spdy_version
,
1137 const SpdyHeaderBlock
* headers
) {
1138 if (spdy_version
< SPDY3
) {
1139 frame
->WriteUInt16(headers
->size()); // Number of headers.
1141 frame
->WriteUInt32(headers
->size()); // Number of headers.
1143 SpdyHeaderBlock::const_iterator it
;
1144 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1145 if (spdy_version
< SPDY3
) {
1146 frame
->WriteString(it
->first
);
1147 frame
->WriteString(it
->second
);
1149 frame
->WriteStringPiece32(it
->first
);
1150 frame
->WriteStringPiece32(it
->second
);
1155 // TODO(phajdan.jr): Clean up after we no longer need
1156 // to workaround http://crbug.com/139744.
1157 #if !defined(USE_SYSTEM_ZLIB)
1159 // These constants are used by zlib to differentiate between normal data and
1160 // cookie data. Cookie data is handled specially by zlib when compressing.
1162 // kZStandardData is compressed normally, save that it will never match
1163 // against any other class of data in the window.
1164 kZStandardData
= Z_CLASS_STANDARD
,
1165 // kZCookieData is compressed in its own Huffman blocks and only matches in
1166 // its entirety and only against other kZCookieData blocks. Any matches must
1167 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1168 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1170 kZCookieData
= Z_CLASS_COOKIE
,
1171 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1172 // against the window.
1173 kZHuffmanOnlyData
= Z_CLASS_HUFFMAN_ONLY
,
1176 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1177 // needed when switching between classes of data.
1178 static void WriteZ(const base::StringPiece
& data
,
1183 // If we are switching from standard to non-standard data then we need to end
1184 // the current Huffman context to avoid it leaking between them.
1185 if (out
->clas
== kZStandardData
&&
1186 clas
!= kZStandardData
) {
1188 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1189 DCHECK_EQ(Z_OK
, rv
);
1190 DCHECK_EQ(0u, out
->avail_in
);
1191 DCHECK_LT(0u, out
->avail_out
);
1194 out
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
.data()));
1195 out
->avail_in
= data
.size();
1197 if (clas
== kZStandardData
) {
1198 rv
= deflate(out
, Z_NO_FLUSH
);
1200 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
1202 if (!data
.empty()) {
1203 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1204 DCHECK_EQ(Z_OK
, rv
);
1206 DCHECK_EQ(0u, out
->avail_in
);
1207 DCHECK_LT(0u, out
->avail_out
);
1210 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1211 static void WriteLengthZ(size_t n
,
1216 DCHECK_LE(length
, sizeof(buf
));
1217 for (unsigned i
= 1; i
<= length
; i
++) {
1218 buf
[length
- i
] = n
;
1221 WriteZ(base::StringPiece(buf
, length
), clas
, out
);
1224 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1225 // manner that resists the length of the compressed data from compromising
1227 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
1228 z_stream
* z
) const {
1229 unsigned length_length
= 4;
1230 if (spdy_version_
< 3)
1233 WriteLengthZ(headers
->size(), length_length
, kZStandardData
, z
);
1235 std::map
<std::string
, std::string
>::const_iterator it
;
1236 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
1237 WriteLengthZ(it
->first
.size(), length_length
, kZStandardData
, z
);
1238 WriteZ(it
->first
, kZStandardData
, z
);
1240 if (it
->first
== "cookie") {
1241 // We require the cookie values (save for the last) to end with a
1242 // semicolon and (save for the first) to start with a space. This is
1243 // typically the format that we are given them in but we reserialize them
1246 std::vector
<base::StringPiece
> cookie_values
;
1247 size_t cookie_length
= 0;
1248 base::StringPiece
cookie_data(it
->second
);
1251 while (!cookie_data
.empty() &&
1252 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
1253 cookie_data
.remove_prefix(1);
1255 if (cookie_data
.empty())
1259 for (i
= 0; i
< cookie_data
.size(); i
++) {
1260 if (cookie_data
[i
] == ';')
1263 if (i
< cookie_data
.size()) {
1264 cookie_values
.push_back(cookie_data
.substr(0, i
));
1265 cookie_length
+= i
+ 2 /* semicolon and space */;
1266 cookie_data
.remove_prefix(i
+ 1);
1268 cookie_values
.push_back(cookie_data
);
1269 cookie_length
+= cookie_data
.size();
1270 cookie_data
.remove_prefix(i
);
1274 WriteLengthZ(cookie_length
, length_length
, kZStandardData
, z
);
1275 for (size_t i
= 0; i
< cookie_values
.size(); i
++) {
1277 // Since zlib will only back-reference complete cookies, a cookie that
1278 // is currently last (and so doesn't have a trailing semicolon) won't
1279 // match if it's later in a non-final position. The same is true of
1280 // the first cookie.
1281 if (i
== 0 && cookie_values
.size() == 1) {
1282 cookie
= cookie_values
[i
].as_string();
1283 } else if (i
== 0) {
1284 cookie
= cookie_values
[i
].as_string() + ";";
1285 } else if (i
< cookie_values
.size() - 1) {
1286 cookie
= " " + cookie_values
[i
].as_string() + ";";
1288 cookie
= " " + cookie_values
[i
].as_string();
1290 WriteZ(cookie
, kZCookieData
, z
);
1292 } else if (it
->first
== "accept" ||
1293 it
->first
== "accept-charset" ||
1294 it
->first
== "accept-encoding" ||
1295 it
->first
== "accept-language" ||
1296 it
->first
== "host" ||
1297 it
->first
== "version" ||
1298 it
->first
== "method" ||
1299 it
->first
== "scheme" ||
1300 it
->first
== ":host" ||
1301 it
->first
== ":version" ||
1302 it
->first
== ":method" ||
1303 it
->first
== ":scheme" ||
1304 it
->first
== "user-agent") {
1305 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1306 WriteZ(it
->second
, kZStandardData
, z
);
1308 // Non-whitelisted headers are Huffman compressed in their own block, but
1309 // don't match against the window.
1310 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
1311 WriteZ(it
->second
, kZHuffmanOnlyData
, z
);
1316 int rv
= deflate(z
, Z_SYNC_FLUSH
);
1317 DCHECK_EQ(Z_OK
, rv
);
1318 z
->clas
= kZStandardData
;
1320 #endif // !defined(USE_SYSTEM_ZLIB)
1322 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
1324 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
1325 const size_t original_len
= len
;
1327 if (remaining_control_header_
> 0) {
1328 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1329 remaining_control_header_
);
1330 remaining_control_header_
-= bytes_read
;
1331 remaining_data_length_
-= bytes_read
;
1334 if (remaining_control_header_
== 0) {
1335 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1336 current_frame_buffer_length_
);
1337 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1339 switch (current_frame_type_
) {
1342 DCHECK_GE(SPDY3
, protocol_version());
1343 bool successful_read
= true;
1344 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1345 DCHECK(successful_read
);
1346 if (current_frame_stream_id_
== 0) {
1347 set_error(SPDY_INVALID_CONTROL_FRAME
);
1351 SpdyStreamId associated_to_stream_id
= kInvalidStream
;
1352 successful_read
= reader
.ReadUInt31(&associated_to_stream_id
);
1353 DCHECK(successful_read
);
1355 SpdyPriority priority
= 0;
1356 successful_read
= reader
.ReadUInt8(&priority
);
1357 DCHECK(successful_read
);
1358 if (protocol_version() <= SPDY2
) {
1359 priority
= priority
>> 6;
1361 priority
= priority
>> 5;
1364 // Seek past unused byte; used to be credential slot in SPDY 3.
1367 DCHECK(reader
.IsDoneReading());
1368 if (debug_visitor_
) {
1369 debug_visitor_
->OnReceiveCompressedFrame(
1370 current_frame_stream_id_
,
1371 current_frame_type_
,
1372 current_frame_length_
);
1374 visitor_
->OnSynStream(
1375 current_frame_stream_id_
,
1376 associated_to_stream_id
,
1378 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1379 (current_frame_flags_
& CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
1381 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
1384 if (protocol_version() > SPDY3
&&
1385 current_frame_flags_
& SETTINGS_FLAG_ACK
) {
1386 visitor_
->OnSettingsAck();
1387 CHANGE_STATE(SPDY_AUTO_RESET
);
1389 visitor_
->OnSettings(current_frame_flags_
&
1390 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
);
1391 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
1396 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1398 if (protocol_version() > SPDY3
) {
1399 DCHECK_EQ(HEADERS
, current_frame_type_
);
1401 bool successful_read
= true;
1402 if (protocol_version() <= SPDY3
) {
1403 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1404 DCHECK(successful_read
);
1406 if (current_frame_stream_id_
== 0) {
1407 set_error(SPDY_INVALID_CONTROL_FRAME
);
1410 if (protocol_version() <= SPDY2
) {
1411 // SPDY 2 had two unused bytes here. Seek past them.
1414 if (protocol_version() > SPDY3
&&
1415 !(current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) &&
1416 current_frame_type_
== HEADERS
) {
1417 expect_continuation_
= current_frame_stream_id_
;
1418 end_stream_when_done_
= current_frame_flags_
& CONTROL_FLAG_FIN
;
1420 const bool has_priority
=
1421 (current_frame_flags_
& HEADERS_FLAG_PRIORITY
) != 0;
1422 uint32 priority
= 0;
1423 if (protocol_version() > SPDY3
&& has_priority
) {
1424 // TODO(jgraettinger): Process dependency rather than ignoring it.
1425 reader
.Seek(kPriorityDependencyPayloadSize
);
1427 successful_read
= reader
.ReadUInt8(&weight
);
1428 if (successful_read
) {
1429 priority
= MapWeightToPriority(weight
);
1432 DCHECK(reader
.IsDoneReading());
1433 if (debug_visitor_
) {
1434 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1435 SpdyFrameType reported_type
= current_frame_type_
;
1436 if (protocol_version() > SPDY3
&& has_priority
) {
1437 reported_type
= SYN_STREAM
;
1439 debug_visitor_
->OnReceiveCompressedFrame(
1440 current_frame_stream_id_
,
1442 current_frame_length_
);
1444 if (current_frame_type_
== SYN_REPLY
) {
1445 visitor_
->OnSynReply(
1446 current_frame_stream_id_
,
1447 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0);
1448 } else if (protocol_version() > SPDY3
&&
1449 current_frame_flags_
& HEADERS_FLAG_PRIORITY
) {
1450 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1451 // can be made independent of wire changes.
1452 visitor_
->OnSynStream(
1453 current_frame_stream_id_
,
1454 0, // associated_to_stream_id
1456 current_frame_flags_
& CONTROL_FLAG_FIN
,
1457 false); // unidirectional
1459 visitor_
->OnHeaders(
1460 current_frame_stream_id_
,
1461 (current_frame_flags_
& CONTROL_FLAG_FIN
) != 0,
1462 expect_continuation_
== 0);
1465 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
1469 DCHECK_LT(SPDY3
, protocol_version());
1470 if (current_frame_stream_id_
== 0) {
1471 set_error(SPDY_INVALID_CONTROL_FRAME
);
1474 SpdyStreamId promised_stream_id
= kInvalidStream
;
1475 bool successful_read
= reader
.ReadUInt31(&promised_stream_id
);
1476 DCHECK(successful_read
);
1477 DCHECK(reader
.IsDoneReading());
1478 if (promised_stream_id
== 0) {
1479 set_error(SPDY_INVALID_CONTROL_FRAME
);
1482 if (!(current_frame_flags_
& PUSH_PROMISE_FLAG_END_PUSH_PROMISE
)) {
1483 expect_continuation_
= current_frame_stream_id_
;
1485 if (debug_visitor_
) {
1486 debug_visitor_
->OnReceiveCompressedFrame(
1487 current_frame_stream_id_
,
1488 current_frame_type_
,
1489 current_frame_length_
);
1491 visitor_
->OnPushPromise(current_frame_stream_id_
,
1493 (current_frame_flags_
&
1494 PUSH_PROMISE_FLAG_END_PUSH_PROMISE
) != 0);
1496 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
1500 // Check to make sure the stream id of the current frame is
1501 // the same as that of the preceding frame.
1502 // If we're at this point we should already know that
1503 // expect_continuation_ != 0, so this doubles as a check
1504 // that current_frame_stream_id != 0.
1505 if (current_frame_stream_id_
!= expect_continuation_
) {
1506 set_error(SPDY_INVALID_CONTROL_FRAME
);
1509 if (current_frame_flags_
& HEADERS_FLAG_END_HEADERS
) {
1510 expect_continuation_
= 0;
1512 if (debug_visitor_
) {
1513 debug_visitor_
->OnReceiveCompressedFrame(
1514 current_frame_stream_id_
,
1515 current_frame_type_
,
1516 current_frame_length_
);
1518 visitor_
->OnContinuation(current_frame_stream_id_
,
1519 (current_frame_flags_
&
1520 HEADERS_FLAG_END_HEADERS
) != 0);
1522 CHANGE_STATE(SPDY_READ_PADDING_LENGTH
);
1528 return original_len
- len
;
1531 // Does not buffer the control payload. Instead, either passes directly to the
1532 // visitor or decompresses and then passes directly to the visitor, via
1533 // IncrementallyDeliverControlFrameHeaderData() or
1534 // IncrementallyDecompressControlFrameHeaderData() respectively.
1535 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
1537 bool is_hpack_header_block
) {
1538 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
1540 bool processed_successfully
= true;
1541 if (current_frame_type_
!= SYN_STREAM
&&
1542 current_frame_type_
!= SYN_REPLY
&&
1543 current_frame_type_
!= HEADERS
&&
1544 current_frame_type_
!= PUSH_PROMISE
&&
1545 current_frame_type_
!= CONTINUATION
) {
1546 LOG(DFATAL
) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1548 size_t process_bytes
= std::min(
1549 data_len
, remaining_data_length_
- remaining_padding_payload_length_
);
1550 if (is_hpack_header_block
) {
1551 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1552 current_frame_stream_id_
, data
, process_bytes
)) {
1553 // TODO(jgraettinger): Finer-grained HPACK error codes.
1554 set_error(SPDY_DECOMPRESS_FAILURE
);
1555 processed_successfully
= false;
1557 } else if (process_bytes
> 0) {
1558 if (enable_compression_
&& protocol_version() <= SPDY3
) {
1559 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
1560 current_frame_stream_id_
, data
, process_bytes
);
1562 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
1563 current_frame_stream_id_
, data
, process_bytes
);
1566 remaining_data_length_
-= process_bytes
;
1568 // Handle the case that there is no futher data in this frame.
1569 if (remaining_data_length_
== remaining_padding_payload_length_
&&
1570 processed_successfully
) {
1571 if (expect_continuation_
== 0) {
1572 if (is_hpack_header_block
) {
1573 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1574 current_frame_stream_id_
)) {
1575 set_error(SPDY_DECOMPRESS_FAILURE
);
1576 processed_successfully
= false;
1578 // TODO(jgraettinger): To be removed with migration to
1579 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1580 // block, delivered via reentrant call to
1581 // ProcessControlFrameHeaderBlock().
1582 DeliverHpackBlockAsSpdy3Block();
1583 return process_bytes
;
1586 // The complete header block has been delivered. We send a zero-length
1587 // OnControlFrameHeaderData() to indicate this.
1588 visitor_
->OnControlFrameHeaderData(current_frame_stream_id_
, NULL
, 0);
1591 if (processed_successfully
) {
1592 CHANGE_STATE(SPDY_CONSUME_PADDING
);
1597 if (!processed_successfully
) {
1601 // Return amount processed.
1602 return process_bytes
;
1605 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
1607 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD
, state_
);
1608 DCHECK_EQ(SETTINGS
, current_frame_type_
);
1609 size_t unprocessed_bytes
= std::min(data_len
, remaining_data_length_
);
1610 size_t processed_bytes
= 0;
1612 size_t setting_size
= protocol_version() <= SPDY3
? 8 : 5;
1614 // Loop over our incoming data.
1615 while (unprocessed_bytes
> 0) {
1616 // Process up to one setting at a time.
1617 size_t processing
= std::min(
1619 static_cast<size_t>(setting_size
- settings_scratch_
.setting_buf_len
));
1621 // Check if we have a complete setting in our input.
1622 if (processing
== setting_size
) {
1623 // Parse the setting directly out of the input without buffering.
1624 if (!ProcessSetting(data
+ processed_bytes
)) {
1625 set_error(SPDY_INVALID_CONTROL_FRAME
);
1626 return processed_bytes
;
1629 // Continue updating settings_scratch_.setting_buf.
1630 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
1631 data
+ processed_bytes
,
1633 settings_scratch_
.setting_buf_len
+= processing
;
1635 // Check if we have a complete setting buffered.
1636 if (settings_scratch_
.setting_buf_len
== setting_size
) {
1637 if (!ProcessSetting(settings_scratch_
.setting_buf
)) {
1638 set_error(SPDY_INVALID_CONTROL_FRAME
);
1639 return processed_bytes
;
1641 // Reset settings_scratch_.setting_buf for our next setting.
1642 settings_scratch_
.setting_buf_len
= 0;
1647 unprocessed_bytes
-= processing
;
1648 processed_bytes
+= processing
;
1651 // Check if we're done handling this SETTINGS frame.
1652 remaining_data_length_
-= processed_bytes
;
1653 if (remaining_data_length_
== 0) {
1654 visitor_
->OnSettingsEnd();
1655 CHANGE_STATE(SPDY_AUTO_RESET
);
1658 return processed_bytes
;
1661 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1662 DCHECK_LT(SPDY3
, protocol_version());
1663 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
1665 const SpdyNameValueBlock
& block
= GetHpackDecoder()->decoded_block();
1666 if (block
.empty()) {
1667 // Special-case this to make tests happy.
1668 ProcessControlFrameHeaderBlock(NULL
, 0, false);
1671 SpdyFrameBuilder
builder(
1672 GetSerializedLength(protocol_version(), &block
),
1675 SerializeNameValueBlockWithoutCompression(&builder
, block
);
1676 scoped_ptr
<SpdyFrame
> frame(builder
.take());
1678 // Preserve padding length, and reset it after the re-entrant call.
1679 size_t remaining_padding
= remaining_padding_payload_length_
;
1681 remaining_padding_payload_length_
= 0;
1682 remaining_data_length_
= frame
->size();
1684 ProcessControlFrameHeaderBlock(frame
->data(), frame
->size(), false);
1686 remaining_padding_payload_length_
= remaining_padding
;
1687 remaining_data_length_
= remaining_padding
;
1690 bool SpdyFramer::ProcessSetting(const char* data
) {
1697 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1698 if (protocol_version() <= SPDY3
) {
1699 const uint32 id_and_flags_wire
= *(reinterpret_cast<const uint32
*>(data
));
1700 SettingsFlagsAndId id_and_flags
=
1701 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire
);
1702 id_field
= id_and_flags
.id();
1703 flags
= id_and_flags
.flags();
1704 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 4)));
1706 id_field
= *(reinterpret_cast<const uint8
*>(data
));
1707 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 1)));
1711 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field
)) {
1712 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_field
;
1715 id
= SpdyConstants::ParseSettingId(protocol_version(), id_field
);
1717 if (protocol_version() <= SPDY3
) {
1718 // Detect duplicates.
1719 if (id
<= settings_scratch_
.last_setting_id
) {
1720 DLOG(WARNING
) << "Duplicate entry or invalid ordering for id " << id
1721 << " in " << display_protocol_
<< " SETTINGS frame "
1722 << "(last setting id was "
1723 << settings_scratch_
.last_setting_id
<< ").";
1726 settings_scratch_
.last_setting_id
= id
;
1729 uint8 kFlagsMask
= SETTINGS_FLAG_PLEASE_PERSIST
| SETTINGS_FLAG_PERSISTED
;
1730 if ((flags
& ~(kFlagsMask
)) != 0) {
1731 DLOG(WARNING
) << "Unknown SETTINGS flags provided for id " << id
<< ": "
1737 // Validation succeeded. Pass on to visitor.
1738 visitor_
->OnSetting(id
, flags
, value
);
1742 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
1743 size_t original_len
= len
;
1744 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1745 remaining_data_length_
);
1746 remaining_data_length_
-= bytes_read
;
1747 if (remaining_data_length_
== 0) {
1748 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1749 current_frame_buffer_length_
);
1750 reader
.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1752 // Use frame-specific handlers.
1753 switch (current_frame_type_
) {
1756 bool is_ack
= protocol_version() > SPDY3
&&
1757 (current_frame_flags_
& PING_FLAG_ACK
);
1758 bool successful_read
= true;
1759 if (protocol_version() <= SPDY3
) {
1761 successful_read
= reader
.ReadUInt32(&id32
);
1764 successful_read
= reader
.ReadUInt64(&id
);
1766 DCHECK(successful_read
);
1767 DCHECK(reader
.IsDoneReading());
1768 visitor_
->OnPing(id
, is_ack
);
1771 case WINDOW_UPDATE
: {
1772 uint32 delta_window_size
= 0;
1773 bool successful_read
= true;
1774 if (protocol_version() <= SPDY3
) {
1775 successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1776 DCHECK(successful_read
);
1778 successful_read
= reader
.ReadUInt32(&delta_window_size
);
1779 DCHECK(successful_read
);
1780 DCHECK(reader
.IsDoneReading());
1781 visitor_
->OnWindowUpdate(current_frame_stream_id_
,
1786 DCHECK_LT(SPDY3
, protocol_version());
1787 DCHECK(reader
.IsDoneReading());
1788 visitor_
->OnBlocked(current_frame_stream_id_
);
1792 DCHECK_LT(SPDY3
, protocol_version());
1793 // TODO(hkhalil): Process PRIORITY frames rather than ignore them.
1795 DCHECK(reader
.IsDoneReading());
1800 LOG(FATAL
) << "Unhandled control frame " << current_frame_type_
;
1803 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
1805 return original_len
- len
;
1808 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data
, size_t len
) {
1812 // Clamp to the actual remaining payload.
1813 if (len
> remaining_data_length_
) {
1814 len
= remaining_data_length_
;
1816 size_t original_len
= len
;
1818 // Check if we had already read enough bytes to parse the GOAWAY header.
1819 const size_t header_size
= GetGoAwayMinimumSize();
1820 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1821 bool already_parsed_header
= (unread_header_bytes
== 0);
1822 if (!already_parsed_header
) {
1823 // Buffer the new GOAWAY header bytes we got.
1824 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1826 // Do we have enough to parse the constant size GOAWAY header?
1827 if (current_frame_buffer_length_
== header_size
) {
1828 // Parse out the last good stream id.
1829 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1830 current_frame_buffer_length_
);
1831 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1832 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1833 DCHECK(successful_read
);
1835 // In SPDYv3 and up, frames also specify a status code - parse it out.
1836 SpdyGoAwayStatus status
= GOAWAY_OK
;
1837 if (protocol_version() >= SPDY3
) {
1838 uint32 status_raw
= GOAWAY_OK
;
1839 successful_read
= reader
.ReadUInt32(&status_raw
);
1840 DCHECK(successful_read
);
1841 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1843 status
= SpdyConstants::ParseGoAwayStatus(protocol_version(),
1847 // Throw an error for SPDY4+, keep liberal behavior
1848 // for earlier versions.
1849 if (protocol_version() > SPDY3
) {
1850 DLOG(WARNING
) << "Invalid GO_AWAY status " << status_raw
;
1851 set_error(SPDY_INVALID_CONTROL_FRAME
);
1856 // Finished parsing the GOAWAY header, call frame handler.
1857 visitor_
->OnGoAway(current_frame_stream_id_
, status
);
1861 // Handle remaining data as opaque.
1862 bool processed_successfully
= true;
1864 processed_successfully
= visitor_
->OnGoAwayFrameData(data
, len
);
1866 remaining_data_length_
-= original_len
;
1867 if (!processed_successfully
) {
1868 set_error(SPDY_GOAWAY_FRAME_CORRUPT
);
1869 } else if (remaining_data_length_
== 0) {
1870 // Signal that there is not more opaque data.
1871 visitor_
->OnGoAwayFrameData(NULL
, 0);
1872 CHANGE_STATE(SPDY_AUTO_RESET
);
1874 return original_len
;
1877 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data
, size_t len
) {
1881 // Clamp to the actual remaining payload.
1882 if (len
> remaining_data_length_
) {
1883 len
= remaining_data_length_
;
1885 size_t original_len
= len
;
1887 // Check if we had already read enough bytes to parse the fixed-length portion
1888 // of the RST_STREAM frame.
1889 const size_t header_size
= GetRstStreamMinimumSize();
1890 size_t unread_header_bytes
= header_size
- current_frame_buffer_length_
;
1891 bool already_parsed_header
= (unread_header_bytes
== 0);
1892 if (!already_parsed_header
) {
1893 // Buffer the new RST_STREAM header bytes we got.
1894 UpdateCurrentFrameBuffer(&data
, &len
, unread_header_bytes
);
1896 // Do we have enough to parse the constant size RST_STREAM header?
1897 if (current_frame_buffer_length_
== header_size
) {
1898 // Parse out the last good stream id.
1899 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1900 current_frame_buffer_length_
);
1901 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1902 if (protocol_version() <= SPDY3
) {
1903 bool successful_read
= reader
.ReadUInt31(¤t_frame_stream_id_
);
1904 DCHECK(successful_read
);
1907 SpdyRstStreamStatus status
= RST_STREAM_INVALID
;
1908 uint32 status_raw
= status
;
1909 bool successful_read
= reader
.ReadUInt32(&status_raw
);
1910 DCHECK(successful_read
);
1911 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1913 status
= static_cast<SpdyRstStreamStatus
>(status_raw
);
1915 // Throw an error for SPDY4+, keep liberal behavior
1916 // for earlier versions.
1917 if (protocol_version() > SPDY3
) {
1918 DLOG(WARNING
) << "Invalid RST_STREAM status " << status_raw
;
1919 set_error(SPDY_INVALID_CONTROL_FRAME
);
1923 // Finished parsing the RST_STREAM header, call frame handler.
1924 visitor_
->OnRstStream(current_frame_stream_id_
, status
);
1928 // Handle remaining data as opaque.
1929 bool processed_successfully
= true;
1931 processed_successfully
= visitor_
->OnRstStreamFrameData(data
, len
);
1933 remaining_data_length_
-= original_len
;
1934 if (!processed_successfully
) {
1935 set_error(SPDY_RST_STREAM_FRAME_CORRUPT
);
1936 } else if (remaining_data_length_
== 0) {
1937 // Signal that there is not more opaque data.
1938 visitor_
->OnRstStreamFrameData(NULL
, 0);
1939 CHANGE_STATE(SPDY_AUTO_RESET
);
1941 return original_len
;
1944 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data
, size_t len
) {
1949 // Clamp to the actual remaining payload.
1950 len
= std::min(len
, remaining_data_length_
);
1952 size_t processed_bytes
= 0;
1953 size_t processing
= 0;
1954 size_t bytes_remaining
;
1959 if (altsvc_scratch_
.pid_len
== 0) {
1960 // The size of the frame up to the PID_LEN field.
1961 size_t fixed_len_portion
= GetAltSvcMinimumSize() - 1;
1962 bytes_remaining
= fixed_len_portion
- current_frame_buffer_length_
;
1963 processing
= std::min(len
, bytes_remaining
);
1964 // Buffer the new ALTSVC bytes we got.
1965 UpdateCurrentFrameBuffer(&data
, &len
, processing
);
1967 // Do we have enough to parse the length of the protocol id?
1968 if (current_frame_buffer_length_
== fixed_len_portion
) {
1969 // Parse out the max age, port, and pid_len.
1970 SpdyFrameReader
reader(current_frame_buffer_
.get(),
1971 current_frame_buffer_length_
);
1972 reader
.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1973 bool successful_read
= reader
.ReadUInt32(&altsvc_scratch_
.max_age
);
1974 reader
.ReadUInt16(&altsvc_scratch_
.port
);
1975 reader
.Seek(1); // Reserved byte.
1976 successful_read
= successful_read
&&
1977 reader
.ReadUInt8(&altsvc_scratch_
.pid_len
);
1978 DCHECK(successful_read
);
1979 // Sanity check length value.
1980 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
>=
1981 current_frame_length_
) {
1982 set_error(SPDY_INVALID_CONTROL_FRAME
);
1985 altsvc_scratch_
.protocol_id
.reset(
1986 new char[size_t(altsvc_scratch_
.pid_len
)]);
1988 processed_bytes
+= processing
;
1990 } else if (altsvc_scratch_
.pid_buf_len
< altsvc_scratch_
.pid_len
) {
1991 // Buffer protocol id field as in comes in.
1992 buffer
= altsvc_scratch_
.protocol_id
.get();
1993 buffer_len
= &altsvc_scratch_
.pid_buf_len
;
1994 bytes_remaining
= altsvc_scratch_
.pid_len
- altsvc_scratch_
.pid_buf_len
;
1995 } else if (altsvc_scratch_
.host_len
== 0) {
1996 // Parse out the host length.
1998 altsvc_scratch_
.host_len
= *reinterpret_cast<const uint8
*>(data
);
1999 // Sanity check length value.
2000 if (GetAltSvcMinimumSize() + altsvc_scratch_
.pid_len
+
2001 altsvc_scratch_
.host_len
> current_frame_length_
) {
2002 set_error(SPDY_INVALID_CONTROL_FRAME
);
2005 altsvc_scratch_
.host
.reset(new char[altsvc_scratch_
.host_len
]);
2006 // Once we have host length, we can also determine the origin length
2007 // by process of elimination.
2008 altsvc_scratch_
.origin_len
= current_frame_length_
-
2009 GetAltSvcMinimumSize() -
2010 altsvc_scratch_
.pid_len
-
2011 altsvc_scratch_
.host_len
;
2012 if (altsvc_scratch_
.origin_len
> 0) {
2013 altsvc_scratch_
.origin
.reset(new char[altsvc_scratch_
.origin_len
]);
2016 processed_bytes
+= processing
;
2019 } else if (altsvc_scratch_
.host_buf_len
< altsvc_scratch_
.host_len
) {
2020 // Buffer host field as it comes in.
2021 // TODO(mlavan): check formatting for host and origin
2022 buffer
= altsvc_scratch_
.host
.get();
2023 buffer_len
= &altsvc_scratch_
.host_buf_len
;
2024 bytes_remaining
= altsvc_scratch_
.host_len
- altsvc_scratch_
.host_buf_len
;
2026 // Buffer (optional) origin field as it comes in.
2027 if (altsvc_scratch_
.origin_len
<= 0) {
2028 set_error(SPDY_INVALID_CONTROL_FRAME
);
2031 buffer
= altsvc_scratch_
.origin
.get();
2032 buffer_len
= &altsvc_scratch_
.origin_buf_len
;
2033 bytes_remaining
= remaining_data_length_
-
2035 altsvc_scratch_
.origin_buf_len
;
2036 if (len
> bytes_remaining
) {
2037 // This is our last field; there shouldn't be any more bytes.
2038 set_error(SPDY_INVALID_CONTROL_FRAME
);
2043 // Copy data bytes into the appropriate field.
2044 processing
= std::min(len
, bytes_remaining
);
2045 memcpy(buffer
+ *buffer_len
,
2048 *buffer_len
+= processing
;
2050 processed_bytes
+= processing
;
2054 remaining_data_length_
-= processed_bytes
;
2055 if (remaining_data_length_
== 0) {
2056 visitor_
->OnAltSvc(current_frame_stream_id_
,
2057 altsvc_scratch_
.max_age
,
2058 altsvc_scratch_
.port
,
2059 StringPiece(altsvc_scratch_
.protocol_id
.get(),
2060 altsvc_scratch_
.pid_len
),
2061 StringPiece(altsvc_scratch_
.host
.get(),
2062 altsvc_scratch_
.host_len
),
2063 StringPiece(altsvc_scratch_
.origin
.get(),
2064 altsvc_scratch_
.origin_len
));
2065 CHANGE_STATE(SPDY_AUTO_RESET
);
2068 return processed_bytes
;
2071 size_t SpdyFramer::ProcessFramePaddingLength(const char* data
, size_t len
) {
2072 DCHECK_EQ(SPDY_READ_PADDING_LENGTH
, state_
);
2074 size_t original_len
= len
;
2075 if (remaining_padding_length_fields_
== 0) {
2076 DCHECK_EQ(remaining_padding_payload_length_
, 0u);
2077 bool pad_low
= false;
2078 bool pad_high
= false;
2079 if (current_frame_flags_
& DATA_FLAG_PAD_LOW
) {
2081 ++remaining_padding_length_fields_
;
2083 if (current_frame_flags_
& DATA_FLAG_PAD_HIGH
) {
2085 ++remaining_padding_length_fields_
;
2087 if ((pad_high
&& !pad_low
) ||
2088 remaining_data_length_
< remaining_padding_length_fields_
) {
2089 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2094 // Parse the padding length.
2095 while (len
!= 0 && remaining_padding_length_fields_
!= 0) {
2096 remaining_padding_payload_length_
=
2097 (remaining_padding_payload_length_
<< 8) +
2098 *reinterpret_cast<const uint8
*>(data
);
2101 --remaining_padding_length_fields_
;
2102 --remaining_data_length_
;
2105 if (remaining_padding_length_fields_
== 0) {
2106 if (remaining_padding_payload_length_
> remaining_data_length_
) {
2107 set_error(SPDY_INVALID_DATA_FRAME_FLAGS
);
2110 if (current_frame_type_
== DATA
) {
2111 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
2113 DCHECK(current_frame_type_
== HEADERS
||
2114 current_frame_type_
== PUSH_PROMISE
||
2115 current_frame_type_
== CONTINUATION
||
2116 current_frame_type_
== SYN_STREAM
||
2117 current_frame_type_
== SYN_REPLY
)
2118 << current_frame_type_
;
2119 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
2122 return original_len
- len
;
2125 size_t SpdyFramer::ProcessFramePadding(const char* data
, size_t len
) {
2126 DCHECK_EQ(SPDY_CONSUME_PADDING
, state_
);
2128 size_t original_len
= len
;
2129 if (remaining_padding_payload_length_
> 0) {
2130 DCHECK_EQ(remaining_padding_payload_length_
, remaining_data_length_
);
2131 size_t amount_to_discard
= std::min(remaining_padding_payload_length_
, len
);
2132 if (current_frame_type_
== DATA
&& amount_to_discard
> 0) {
2133 // The visitor needs to know about padding so it can send window updates.
2134 // Communicate the padding to the visitor through a NULL data pointer,
2135 // with a nonzero size.
2136 visitor_
->OnStreamFrameData(
2137 current_frame_stream_id_
, NULL
, amount_to_discard
, false);
2139 data
+= amount_to_discard
;
2140 len
-= amount_to_discard
;
2141 remaining_padding_payload_length_
-= amount_to_discard
;
2142 remaining_data_length_
-= amount_to_discard
;
2145 if (remaining_data_length_
== 0) {
2146 // If the FIN flag is set, or this ends a header block which set FIN,
2147 // inform the visitor of EOF via a 0-length data frame.
2148 if (expect_continuation_
== 0 &&
2149 ((current_frame_flags_
& CONTROL_FLAG_FIN
) != 0 ||
2150 end_stream_when_done_
)) {
2151 end_stream_when_done_
= false;
2152 visitor_
->OnStreamFrameData(current_frame_stream_id_
, NULL
, 0, true);
2154 CHANGE_STATE(SPDY_AUTO_RESET
);
2156 return original_len
- len
;
2159 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
2160 size_t original_len
= len
;
2161 if (remaining_data_length_
- remaining_padding_payload_length_
> 0) {
2162 size_t amount_to_forward
= std::min(
2163 remaining_data_length_
- remaining_padding_payload_length_
, len
);
2164 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
2165 // Only inform the visitor if there is data.
2166 if (amount_to_forward
) {
2167 visitor_
->OnStreamFrameData(
2168 current_frame_stream_id_
, data
, amount_to_forward
, false);
2171 data
+= amount_to_forward
;
2172 len
-= amount_to_forward
;
2173 remaining_data_length_
-= amount_to_forward
;
2176 if (remaining_data_length_
== remaining_padding_payload_length_
) {
2177 CHANGE_STATE(SPDY_CONSUME_PADDING
);
2179 return original_len
- len
;
2182 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2184 size_t original_len
= len
;
2185 if (remaining_data_length_
> 0) {
2186 size_t amount_to_ignore
= std::min(remaining_data_length_
, len
);
2187 len
-= amount_to_ignore
;
2188 remaining_data_length_
-= amount_to_ignore
;
2191 if (remaining_data_length_
== 0) {
2192 CHANGE_STATE(SPDY_AUTO_RESET
);
2194 return original_len
- len
;
2197 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
2198 size_t header_length
,
2199 SpdyHeaderBlock
* block
) const {
2200 SpdyFrameReader
reader(header_data
, header_length
);
2202 // Read number of headers.
2204 if (protocol_version() <= SPDY2
) {
2206 if (!reader
.ReadUInt16(&temp
)) {
2207 DVLOG(1) << "Unable to read number of headers.";
2212 if (!reader
.ReadUInt32(&num_headers
)) {
2213 DVLOG(1) << "Unable to read number of headers.";
2218 // Read each header.
2219 for (uint32 index
= 0; index
< num_headers
; ++index
) {
2220 base::StringPiece temp
;
2222 // Read header name.
2223 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2224 : !reader
.ReadStringPiece32(&temp
)) {
2225 DVLOG(1) << "Unable to read header name (" << index
+ 1 << " of "
2226 << num_headers
<< ").";
2229 std::string name
= temp
.as_string();
2231 // Read header value.
2232 if ((protocol_version() <= SPDY2
) ? !reader
.ReadStringPiece16(&temp
)
2233 : !reader
.ReadStringPiece32(&temp
)) {
2234 DVLOG(1) << "Unable to read header value (" << index
+ 1 << " of "
2235 << num_headers
<< ").";
2238 std::string value
= temp
.as_string();
2240 // Ensure no duplicates.
2241 if (block
->find(name
) != block
->end()) {
2242 DVLOG(1) << "Duplicate header '" << name
<< "' (" << index
+ 1 << " of "
2243 << num_headers
<< ").";
2248 (*block
)[name
] = value
;
2250 return reader
.GetBytesConsumed();
2253 SpdySerializedFrame
* SpdyFramer::SerializeData(
2254 const SpdyDataIR
& data_ir
) const {
2255 uint8 flags
= DATA_FLAG_NONE
;
2256 if (data_ir
.fin()) {
2257 flags
= DATA_FLAG_FIN
;
2260 if (protocol_version() > SPDY3
) {
2261 int num_padding_fields
= 0;
2262 if (data_ir
.pad_low()) {
2263 flags
|= DATA_FLAG_PAD_LOW
;
2264 ++num_padding_fields
;
2266 if (data_ir
.pad_high()) {
2267 flags
|= DATA_FLAG_PAD_HIGH
;
2268 ++num_padding_fields
;
2271 const size_t size_with_padding
= num_padding_fields
+
2272 data_ir
.data().length() + data_ir
.padding_payload_len() +
2273 GetDataFrameMinimumSize();
2274 SpdyFrameBuilder
builder(size_with_padding
, protocol_version());
2275 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2276 if (data_ir
.pad_high()) {
2277 builder
.WriteUInt8(data_ir
.padding_payload_len() >> 8);
2279 if (data_ir
.pad_low()) {
2280 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2282 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2283 if (data_ir
.padding_payload_len() > 0) {
2284 string padding
= string(data_ir
.padding_payload_len(), '0');
2285 builder
.WriteBytes(padding
.data(), padding
.length());
2287 DCHECK_EQ(size_with_padding
, builder
.length());
2288 return builder
.take();
2290 const size_t size
= GetDataFrameMinimumSize() + data_ir
.data().length();
2291 SpdyFrameBuilder
builder(size
, protocol_version());
2292 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2293 builder
.WriteBytes(data_ir
.data().data(), data_ir
.data().length());
2294 DCHECK_EQ(size
, builder
.length());
2295 return builder
.take();
2299 SpdySerializedFrame
* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2300 const SpdyDataIR
& data_ir
) const {
2301 uint8 flags
= DATA_FLAG_NONE
;
2302 if (data_ir
.fin()) {
2303 flags
= DATA_FLAG_FIN
;
2306 size_t frame_size
= GetDataFrameMinimumSize();
2307 size_t num_padding_fields
= 0;
2308 if (protocol_version() > SPDY3
) {
2309 if (data_ir
.pad_low()) {
2310 flags
|= DATA_FLAG_PAD_LOW
;
2311 ++num_padding_fields
;
2313 if (data_ir
.pad_high()) {
2314 flags
|= DATA_FLAG_PAD_HIGH
;
2315 ++num_padding_fields
;
2317 frame_size
+= num_padding_fields
;
2320 SpdyFrameBuilder
builder(frame_size
, protocol_version());
2321 builder
.WriteDataFrameHeader(*this, data_ir
.stream_id(), flags
);
2322 if (protocol_version() > SPDY3
) {
2323 if (data_ir
.pad_high()) {
2324 builder
.WriteUInt8(data_ir
.padding_payload_len() >> 8);
2326 if (data_ir
.pad_low()) {
2327 builder
.WriteUInt8(data_ir
.padding_payload_len() & 0xff);
2329 builder
.OverwriteLength(*this, num_padding_fields
+
2330 data_ir
.data().length() + data_ir
.padding_payload_len());
2332 builder
.OverwriteLength(*this, data_ir
.data().length());
2334 DCHECK_EQ(frame_size
, builder
.length());
2335 return builder
.take();
2338 SpdySerializedFrame
* SpdyFramer::SerializeSynStream(
2339 const SpdySynStreamIR
& syn_stream
) {
2341 if (syn_stream
.fin()) {
2342 flags
|= CONTROL_FLAG_FIN
;
2344 if (syn_stream
.unidirectional()) {
2345 // TODO(hkhalil): invalid for HTTP2.
2346 flags
|= CONTROL_FLAG_UNIDIRECTIONAL
;
2348 // In SPDY >= 4, SYN_STREAM frames are HEADERS frames, but for now
2349 // we never expect to have to overflow into a CONTINUATION frame.
2350 if (protocol_version() > SPDY3
) {
2351 flags
|= HEADERS_FLAG_PRIORITY
;
2352 flags
|= HEADERS_FLAG_END_HEADERS
;
2355 // Sanitize priority.
2356 uint8 priority
= syn_stream
.priority();
2357 if (priority
> GetLowestPriority()) {
2358 DLOG(DFATAL
) << "Priority out-of-bounds.";
2359 priority
= GetLowestPriority();
2362 // The size of this frame, including variable-length name-value block.
2363 size_t size
= GetSynStreamMinimumSize();
2365 string hpack_encoding
;
2366 if (protocol_version() > SPDY3
) {
2367 if (enable_compression_
) {
2368 GetHpackEncoder()->EncodeHeaderSet(
2369 syn_stream
.name_value_block(), &hpack_encoding
);
2371 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2372 syn_stream
.name_value_block(), &hpack_encoding
);
2374 size
+= hpack_encoding
.size();
2376 size
+= GetSerializedLength(syn_stream
.name_value_block());
2379 SpdyFrameBuilder
builder(size
, protocol_version());
2380 if (protocol_version() <= SPDY3
) {
2381 builder
.WriteControlFrameHeader(*this, SYN_STREAM
, flags
);
2382 builder
.WriteUInt32(syn_stream
.stream_id());
2383 builder
.WriteUInt32(syn_stream
.associated_to_stream_id());
2384 builder
.WriteUInt8(priority
<< ((protocol_version() <= SPDY2
) ? 6 : 5));
2385 builder
.WriteUInt8(0); // Unused byte where credential slot used to be.
2387 builder
.BeginNewFrame(*this,
2390 syn_stream
.stream_id());
2391 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2392 builder
.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2393 builder
.WriteUInt8(MapPriorityToWeight(priority
));
2395 DCHECK_EQ(GetSynStreamMinimumSize(), builder
.length());
2396 if (protocol_version() > SPDY3
) {
2397 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2399 SerializeNameValueBlock(&builder
, syn_stream
);
2402 if (debug_visitor_
) {
2403 const size_t payload_len
= protocol_version() > SPDY3
?
2404 hpack_encoding
.size() :
2405 GetSerializedLength(protocol_version(),
2406 &(syn_stream
.name_value_block()));
2407 // SPDY 4 reports this compression as a SYN_STREAM compression.
2408 debug_visitor_
->OnSendCompressedFrame(syn_stream
.stream_id(),
2414 return builder
.take();
2417 SpdySerializedFrame
* SpdyFramer::SerializeSynReply(
2418 const SpdySynReplyIR
& syn_reply
) {
2420 if (syn_reply
.fin()) {
2421 flags
|= CONTROL_FLAG_FIN
;
2423 // In SPDY >= 4, SYN_REPLY frames are HEADERS frames, but for now
2424 // we never expect to have to overflow into a CONTINUATION frame.
2425 if (protocol_version() > SPDY3
) {
2426 flags
|= HEADERS_FLAG_END_HEADERS
;
2429 // The size of this frame, including variable-length name-value block.
2430 size_t size
= GetSynReplyMinimumSize();
2432 string hpack_encoding
;
2433 if (protocol_version() > SPDY3
) {
2434 if (enable_compression_
) {
2435 GetHpackEncoder()->EncodeHeaderSet(
2436 syn_reply
.name_value_block(), &hpack_encoding
);
2438 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2439 syn_reply
.name_value_block(), &hpack_encoding
);
2441 size
+= hpack_encoding
.size();
2443 size
+= GetSerializedLength(syn_reply
.name_value_block());
2446 SpdyFrameBuilder
builder(size
, protocol_version());
2447 if (protocol_version() <= SPDY3
) {
2448 builder
.WriteControlFrameHeader(*this, SYN_REPLY
, flags
);
2449 builder
.WriteUInt32(syn_reply
.stream_id());
2451 builder
.BeginNewFrame(*this,
2454 syn_reply
.stream_id());
2456 if (protocol_version() < SPDY3
) {
2457 builder
.WriteUInt16(0); // Unused.
2459 DCHECK_EQ(GetSynReplyMinimumSize(), builder
.length());
2460 if (protocol_version() > SPDY3
) {
2461 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2463 SerializeNameValueBlock(&builder
, syn_reply
);
2466 if (debug_visitor_
) {
2467 const size_t payload_len
= protocol_version() > SPDY3
?
2468 hpack_encoding
.size() :
2469 GetSerializedLength(protocol_version(),
2470 &(syn_reply
.name_value_block()));
2471 debug_visitor_
->OnSendCompressedFrame(syn_reply
.stream_id(),
2477 return builder
.take();
2480 SpdySerializedFrame
* SpdyFramer::SerializeRstStream(
2481 const SpdyRstStreamIR
& rst_stream
) const {
2482 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2483 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2484 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2485 // commented but left in place to simplify future patching.
2486 // Compute the output buffer size, taking opaque data into account.
2487 uint16 expected_length
= GetRstStreamMinimumSize();
2488 if (protocol_version() > SPDY3
) {
2489 expected_length
+= rst_stream
.description().size();
2491 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2493 // Serialize the RST_STREAM frame.
2494 if (protocol_version() <= SPDY3
) {
2495 builder
.WriteControlFrameHeader(*this, RST_STREAM
, 0);
2496 builder
.WriteUInt32(rst_stream
.stream_id());
2498 builder
.BeginNewFrame(*this, RST_STREAM
, 0, rst_stream
.stream_id());
2501 builder
.WriteUInt32(rst_stream
.status());
2503 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2504 if (protocol_version() > SPDY3
&& rst_stream
.description().size() > 0) {
2505 builder
.WriteBytes(rst_stream
.description().data(),
2506 rst_stream
.description().size());
2509 DCHECK_EQ(expected_length
, builder
.length());
2510 return builder
.take();
2513 SpdySerializedFrame
* SpdyFramer::SerializeSettings(
2514 const SpdySettingsIR
& settings
) const {
2517 if (protocol_version() <= SPDY3
) {
2518 if (settings
.clear_settings()) {
2519 flags
|= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS
;
2522 if (settings
.is_ack()) {
2523 flags
|= SETTINGS_FLAG_ACK
;
2526 const SpdySettingsIR::ValueMap
* values
= &(settings
.values());
2528 size_t setting_size
= (protocol_version() <= SPDY3
? 8 : 5);
2529 // Size, in bytes, of this SETTINGS frame.
2530 const size_t size
= GetSettingsMinimumSize() +
2531 (values
->size() * setting_size
);
2532 SpdyFrameBuilder
builder(size
, protocol_version());
2533 if (protocol_version() <= SPDY3
) {
2534 builder
.WriteControlFrameHeader(*this, SETTINGS
, flags
);
2536 builder
.BeginNewFrame(*this, SETTINGS
, flags
, 0);
2539 // If this is an ACK, payload should be empty.
2540 if (protocol_version() > SPDY3
&& settings
.is_ack()) {
2541 return builder
.take();
2544 if (protocol_version() <= SPDY3
) {
2545 builder
.WriteUInt32(values
->size());
2547 DCHECK_EQ(GetSettingsMinimumSize(), builder
.length());
2548 for (SpdySettingsIR::ValueMap::const_iterator it
= values
->begin();
2549 it
!= values
->end();
2551 if (protocol_version() <= SPDY3
) {
2552 uint8 setting_flags
= 0;
2553 if (it
->second
.persist_value
) {
2554 setting_flags
|= SETTINGS_FLAG_PLEASE_PERSIST
;
2556 if (it
->second
.persisted
) {
2557 setting_flags
|= SETTINGS_FLAG_PERSISTED
;
2559 SettingsFlagsAndId
flags_and_id(
2561 SpdyConstants::SerializeSettingId(protocol_version(), it
->first
));
2562 uint32 id_and_flags_wire
= flags_and_id
.GetWireFormat(protocol_version());
2563 builder
.WriteBytes(&id_and_flags_wire
, 4);
2565 builder
.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(),
2568 builder
.WriteUInt32(it
->second
.value
);
2570 DCHECK_EQ(size
, builder
.length());
2571 return builder
.take();
2574 SpdySerializedFrame
* SpdyFramer::SerializePing(const SpdyPingIR
& ping
) const {
2575 SpdyFrameBuilder
builder(GetPingSize(), protocol_version());
2576 if (protocol_version() <= SPDY3
) {
2577 builder
.WriteControlFrameHeader(*this, PING
, kNoFlags
);
2578 builder
.WriteUInt32(static_cast<uint32
>(ping
.id()));
2581 if (ping
.is_ack()) {
2582 flags
|= PING_FLAG_ACK
;
2584 builder
.BeginNewFrame(*this, PING
, flags
, 0);
2585 builder
.WriteUInt64(ping
.id());
2587 DCHECK_EQ(GetPingSize(), builder
.length());
2588 return builder
.take();
2591 SpdySerializedFrame
* SpdyFramer::SerializeGoAway(
2592 const SpdyGoAwayIR
& goaway
) const {
2594 // Compute the output buffer size, take opaque data into account.
2595 uint16 expected_length
= GetGoAwayMinimumSize();
2596 if (protocol_version() > SPDY3
) {
2597 expected_length
+= goaway
.description().size();
2599 SpdyFrameBuilder
builder(expected_length
, protocol_version());
2601 // Serialize the GOAWAY frame.
2602 if (protocol_version() <= SPDY3
) {
2603 builder
.WriteControlFrameHeader(*this, GOAWAY
, kNoFlags
);
2605 builder
.BeginNewFrame(*this, GOAWAY
, 0, 0);
2608 // GOAWAY frames specify the last good stream id for all SPDY versions.
2609 builder
.WriteUInt32(goaway
.last_good_stream_id());
2611 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2612 if (protocol_version() >= SPDY3
) {
2613 builder
.WriteUInt32(goaway
.status());
2616 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2617 if ((protocol_version() > SPDY3
) && (goaway
.description().size() > 0)) {
2618 builder
.WriteBytes(goaway
.description().data(),
2619 goaway
.description().size());
2622 DCHECK_EQ(expected_length
, builder
.length());
2623 return builder
.take();
2626 SpdySerializedFrame
* SpdyFramer::SerializeHeaders(
2627 const SpdyHeadersIR
& headers
) {
2629 if (headers
.fin()) {
2630 flags
|= CONTROL_FLAG_FIN
;
2632 if (protocol_version() > SPDY3
) {
2633 // This will get overwritten if we overflow into a CONTINUATION frame.
2634 flags
|= HEADERS_FLAG_END_HEADERS
;
2635 if (headers
.has_priority()) {
2636 flags
|= HEADERS_FLAG_PRIORITY
;
2640 // The size of this frame, including variable-length name-value block.
2641 size_t size
= GetHeadersMinimumSize();
2643 uint32 priority
= headers
.priority();
2644 if (headers
.has_priority()) {
2645 if (priority
> GetLowestPriority()) {
2646 DLOG(DFATAL
) << "Priority out-of-bounds.";
2647 priority
= GetLowestPriority();
2652 string hpack_encoding
;
2653 if (protocol_version() > SPDY3
) {
2654 if (enable_compression_
) {
2655 GetHpackEncoder()->EncodeHeaderSet(
2656 headers
.name_value_block(), &hpack_encoding
);
2658 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2659 headers
.name_value_block(), &hpack_encoding
);
2661 size
+= hpack_encoding
.size();
2662 if (size
> GetControlFrameBufferMaxSize()) {
2663 size
+= GetNumberRequiredContinuationFrames(size
) *
2664 GetContinuationMinimumSize();
2665 flags
&= ~HEADERS_FLAG_END_HEADERS
;
2668 size
+= GetSerializedLength(headers
.name_value_block());
2671 SpdyFrameBuilder
builder(size
, protocol_version());
2672 if (protocol_version() <= SPDY3
) {
2673 builder
.WriteControlFrameHeader(*this, HEADERS
, flags
);
2674 builder
.WriteUInt32(headers
.stream_id());
2676 builder
.BeginNewFrame(*this,
2679 headers
.stream_id());
2680 if (headers
.has_priority()) {
2681 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2682 builder
.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2683 builder
.WriteUInt8(MapPriorityToWeight(priority
));
2686 if (protocol_version() <= SPDY2
) {
2687 builder
.WriteUInt16(0); // Unused.
2689 DCHECK_EQ(GetHeadersMinimumSize(), builder
.length());
2691 if (protocol_version() > SPDY3
) {
2692 WritePayloadWithContinuation(&builder
,
2694 headers
.stream_id(),
2697 SerializeNameValueBlock(&builder
, headers
);
2700 if (debug_visitor_
) {
2701 const size_t payload_len
= protocol_version() > SPDY3
?
2702 hpack_encoding
.size() :
2703 GetSerializedLength(protocol_version(),
2704 &(headers
.name_value_block()));
2705 debug_visitor_
->OnSendCompressedFrame(headers
.stream_id(),
2711 return builder
.take();
2714 SpdySerializedFrame
* SpdyFramer::SerializeWindowUpdate(
2715 const SpdyWindowUpdateIR
& window_update
) const {
2716 SpdyFrameBuilder
builder(GetWindowUpdateSize(), protocol_version());
2717 if (protocol_version() <= SPDY3
) {
2718 builder
.WriteControlFrameHeader(*this, WINDOW_UPDATE
, kNoFlags
);
2719 builder
.WriteUInt32(window_update
.stream_id());
2721 builder
.BeginNewFrame(*this,
2724 window_update
.stream_id());
2726 builder
.WriteUInt32(window_update
.delta());
2727 DCHECK_EQ(GetWindowUpdateSize(), builder
.length());
2728 return builder
.take();
2731 SpdyFrame
* SpdyFramer::SerializeBlocked(const SpdyBlockedIR
& blocked
) const {
2732 DCHECK_LT(SPDY3
, protocol_version());
2733 SpdyFrameBuilder
builder(GetBlockedSize(), protocol_version());
2734 builder
.BeginNewFrame(*this, BLOCKED
, kNoFlags
, blocked
.stream_id());
2735 return builder
.take();
2738 SpdyFrame
* SpdyFramer::SerializePushPromise(
2739 const SpdyPushPromiseIR
& push_promise
) {
2740 DCHECK_LT(SPDY3
, protocol_version());
2742 // This will get overwritten if we overflow into a CONTINUATION frame.
2743 flags
|= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2744 // The size of this frame, including variable-length name-value block.
2745 size_t size
= GetPushPromiseMinimumSize();
2747 string hpack_encoding
;
2748 if (protocol_version() > SPDY3
) {
2749 if (enable_compression_
) {
2750 GetHpackEncoder()->EncodeHeaderSet(
2751 push_promise
.name_value_block(), &hpack_encoding
);
2753 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2754 push_promise
.name_value_block(), &hpack_encoding
);
2756 size
+= hpack_encoding
.size();
2757 if (size
> GetControlFrameBufferMaxSize()) {
2758 size
+= GetNumberRequiredContinuationFrames(size
) *
2759 GetContinuationMinimumSize();
2760 flags
&= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2763 size
+= GetSerializedLength(push_promise
.name_value_block());
2766 SpdyFrameBuilder
builder(size
, protocol_version());
2767 builder
.BeginNewFrame(*this,
2770 push_promise
.stream_id());
2771 builder
.WriteUInt32(push_promise
.promised_stream_id());
2772 DCHECK_EQ(GetPushPromiseMinimumSize(), builder
.length());
2774 if (protocol_version() > SPDY3
) {
2775 WritePayloadWithContinuation(&builder
,
2777 push_promise
.stream_id(),
2780 SerializeNameValueBlock(&builder
, push_promise
);
2783 if (debug_visitor_
) {
2784 const size_t payload_len
= protocol_version() > SPDY3
?
2785 hpack_encoding
.size() :
2786 GetSerializedLength(protocol_version(),
2787 &(push_promise
.name_value_block()));
2788 debug_visitor_
->OnSendCompressedFrame(push_promise
.stream_id(),
2789 PUSH_PROMISE
, payload_len
, builder
.length());
2792 return builder
.take();
2795 // TODO(jgraettinger): This implementation is incorrect. The continuation
2796 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2797 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2798 SpdyFrame
* SpdyFramer::SerializeContinuation(
2799 const SpdyContinuationIR
& continuation
) {
2800 CHECK_LT(SPDY3
, protocol_version());
2802 if (continuation
.end_headers()) {
2803 flags
|= HEADERS_FLAG_END_HEADERS
;
2806 // The size of this frame, including variable-length name-value block.
2807 size_t size
= GetContinuationMinimumSize();
2808 string hpack_encoding
;
2809 if (enable_compression_
) {
2810 GetHpackEncoder()->EncodeHeaderSet(
2811 continuation
.name_value_block(), &hpack_encoding
);
2813 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2814 continuation
.name_value_block(), &hpack_encoding
);
2816 size
+= hpack_encoding
.size();
2818 SpdyFrameBuilder
builder(size
, protocol_version());
2819 builder
.BeginNewFrame(*this, CONTINUATION
, flags
,
2820 continuation
.stream_id());
2821 DCHECK_EQ(GetContinuationMinimumSize(), builder
.length());
2823 builder
.WriteBytes(&hpack_encoding
[0], hpack_encoding
.size());
2825 if (debug_visitor_
) {
2826 const size_t payload_len
= hpack_encoding
.size();
2827 debug_visitor_
->OnSendCompressedFrame(continuation
.stream_id(),
2828 CONTINUATION
, payload_len
, builder
.length());
2831 return builder
.take();
2834 SpdyFrame
* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR
& altsvc
) {
2835 DCHECK_LT(SPDY3
, protocol_version());
2836 size_t size
= GetAltSvcMinimumSize();
2837 size
+= altsvc
.protocol_id().length();
2838 size
+= altsvc
.host().length();
2839 size
+= altsvc
.origin().length();
2841 SpdyFrameBuilder
builder(size
, protocol_version());
2842 builder
.BeginNewFrame(*this, ALTSVC
, kNoFlags
, altsvc
.stream_id());
2844 builder
.WriteUInt32(altsvc
.max_age());
2845 builder
.WriteUInt16(altsvc
.port());
2846 builder
.WriteUInt8(0); // Reserved.
2847 builder
.WriteUInt8(altsvc
.protocol_id().length());
2848 builder
.WriteBytes(altsvc
.protocol_id().data(),
2849 altsvc
.protocol_id().length());
2850 builder
.WriteUInt8(altsvc
.host().length());
2851 builder
.WriteBytes(altsvc
.host().data(), altsvc
.host().length());
2852 builder
.WriteBytes(altsvc
.origin().data(), altsvc
.origin().length());
2853 DCHECK_LT(GetAltSvcMinimumSize(), builder
.length());
2854 return builder
.take();
2859 class FrameSerializationVisitor
: public SpdyFrameVisitor
{
2861 explicit FrameSerializationVisitor(SpdyFramer
* framer
) : framer_(framer
) {}
2862 virtual ~FrameSerializationVisitor() {}
2864 SpdySerializedFrame
* ReleaseSerializedFrame() { return frame_
.release(); }
2866 virtual void VisitData(const SpdyDataIR
& data
) OVERRIDE
{
2867 frame_
.reset(framer_
->SerializeData(data
));
2869 virtual void VisitSynStream(const SpdySynStreamIR
& syn_stream
) OVERRIDE
{
2870 frame_
.reset(framer_
->SerializeSynStream(syn_stream
));
2872 virtual void VisitSynReply(const SpdySynReplyIR
& syn_reply
) OVERRIDE
{
2873 frame_
.reset(framer_
->SerializeSynReply(syn_reply
));
2875 virtual void VisitRstStream(const SpdyRstStreamIR
& rst_stream
) OVERRIDE
{
2876 frame_
.reset(framer_
->SerializeRstStream(rst_stream
));
2878 virtual void VisitSettings(const SpdySettingsIR
& settings
) OVERRIDE
{
2879 frame_
.reset(framer_
->SerializeSettings(settings
));
2881 virtual void VisitPing(const SpdyPingIR
& ping
) OVERRIDE
{
2882 frame_
.reset(framer_
->SerializePing(ping
));
2884 virtual void VisitGoAway(const SpdyGoAwayIR
& goaway
) OVERRIDE
{
2885 frame_
.reset(framer_
->SerializeGoAway(goaway
));
2887 virtual void VisitHeaders(const SpdyHeadersIR
& headers
) OVERRIDE
{
2888 frame_
.reset(framer_
->SerializeHeaders(headers
));
2890 virtual void VisitWindowUpdate(
2891 const SpdyWindowUpdateIR
& window_update
) OVERRIDE
{
2892 frame_
.reset(framer_
->SerializeWindowUpdate(window_update
));
2894 virtual void VisitBlocked(const SpdyBlockedIR
& blocked
) OVERRIDE
{
2895 frame_
.reset(framer_
->SerializeBlocked(blocked
));
2897 virtual void VisitPushPromise(
2898 const SpdyPushPromiseIR
& push_promise
) OVERRIDE
{
2899 frame_
.reset(framer_
->SerializePushPromise(push_promise
));
2901 virtual void VisitContinuation(
2902 const SpdyContinuationIR
& continuation
) OVERRIDE
{
2903 frame_
.reset(framer_
->SerializeContinuation(continuation
));
2905 virtual void VisitAltSvc(const SpdyAltSvcIR
& altsvc
) OVERRIDE
{
2906 frame_
.reset(framer_
->SerializeAltSvc(altsvc
));
2910 SpdyFramer
* framer_
;
2911 scoped_ptr
<SpdySerializedFrame
> frame_
;
2916 SpdySerializedFrame
* SpdyFramer::SerializeFrame(const SpdyFrameIR
& frame
) {
2917 FrameSerializationVisitor
visitor(this);
2918 frame
.Visit(&visitor
);
2919 return visitor
.ReleaseSerializedFrame();
2922 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock
& headers
) {
2923 CHECK_GE(SPDY3
, protocol_version());
2924 const size_t uncompressed_length
=
2925 GetSerializedLength(protocol_version(), &headers
);
2926 if (!enable_compression_
) {
2927 return uncompressed_length
;
2929 z_stream
* compressor
= GetHeaderCompressor();
2930 // Since we'll be performing lots of flushes when compressing the data,
2931 // zlib's lower bounds may be insufficient.
2932 return 2 * deflateBound(compressor
, uncompressed_length
);
2935 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size
) {
2936 const size_t kMaxControlFrameSize
= GetControlFrameBufferMaxSize();
2937 DCHECK_GT(protocol_version(), SPDY3
);
2938 DCHECK_GT(size
, kMaxControlFrameSize
);
2939 size_t overflow
= size
- kMaxControlFrameSize
;
2940 return overflow
/ (kMaxControlFrameSize
- GetContinuationMinimumSize()) + 1;
2943 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder
* builder
,
2944 const string
& hpack_encoding
,
2945 SpdyStreamId stream_id
,
2946 SpdyFrameType type
) {
2947 const size_t kMaxControlFrameSize
= GetControlFrameBufferMaxSize();
2949 // In addition to the prefix, fixed_field_size includes the size of
2950 // any fields that come before the variable-length name/value block.
2951 size_t fixed_field_size
= 0;
2954 if (type
== HEADERS
) {
2955 fixed_field_size
= GetHeadersMinimumSize();
2956 end_flag
= HEADERS_FLAG_END_HEADERS
;
2957 } else if (type
== PUSH_PROMISE
) {
2958 fixed_field_size
= GetPushPromiseMinimumSize();
2959 end_flag
= PUSH_PROMISE_FLAG_END_PUSH_PROMISE
;
2961 DLOG(FATAL
) << "CONTINUATION frames cannot be used with frame type "
2962 << FrameTypeToString(type
);
2965 // Write as much of the payload as possible into the initial frame.
2966 size_t bytes_remaining
= hpack_encoding
.size() -
2967 std::min(hpack_encoding
.size(),
2968 kMaxControlFrameSize
- fixed_field_size
);
2969 builder
->WriteBytes(&hpack_encoding
[0],
2970 hpack_encoding
.size() - bytes_remaining
);
2972 if (bytes_remaining
> 0) {
2973 builder
->OverwriteLength(*this,
2974 kMaxControlFrameSize
- GetControlFrameHeaderSize());
2977 // Tack on CONTINUATION frames for the overflow.
2978 while (bytes_remaining
> 0) {
2979 size_t bytes_to_write
= std::min(bytes_remaining
,
2980 kMaxControlFrameSize
-
2981 GetContinuationMinimumSize());
2982 // Write CONTINUATION frame prefix.
2983 if (bytes_remaining
== bytes_to_write
) {
2986 builder
->BeginNewFrame(*this,
2990 // Write payload fragment.
2991 builder
->WriteBytes(&hpack_encoding
[hpack_encoding
.size() -
2994 bytes_remaining
-= bytes_to_write
;
2998 // The following compression setting are based on Brian Olson's analysis. See
2999 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
3000 // for more details.
3001 #if defined(USE_SYSTEM_ZLIB)
3002 // System zlib is not expected to have workaround for http://crbug.com/139744,
3003 // so disable compression in that case.
3004 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
3005 static const int kCompressorLevel
= 0;
3006 #else // !defined(USE_SYSTEM_ZLIB)
3007 static const int kCompressorLevel
= 9;
3008 #endif // !defined(USE_SYSTEM_ZLIB)
3009 static const int kCompressorWindowSizeInBits
= 11;
3010 static const int kCompressorMemLevel
= 1;
3012 z_stream
* SpdyFramer::GetHeaderCompressor() {
3013 if (header_compressor_
.get())
3014 return header_compressor_
.get(); // Already initialized.
3016 header_compressor_
.reset(new z_stream
);
3017 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
3019 int success
= deflateInit2(header_compressor_
.get(),
3022 kCompressorWindowSizeInBits
,
3023 kCompressorMemLevel
,
3024 Z_DEFAULT_STRATEGY
);
3025 if (success
== Z_OK
) {
3026 const char* dictionary
= (protocol_version() <= SPDY2
) ?
3027 kV2Dictionary
: kV3Dictionary
;
3028 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3029 kV2DictionarySize
: kV3DictionarySize
;
3030 success
= deflateSetDictionary(header_compressor_
.get(),
3031 reinterpret_cast<const Bytef
*>(dictionary
),
3034 if (success
!= Z_OK
) {
3035 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
3036 header_compressor_
.reset(NULL
);
3039 return header_compressor_
.get();
3042 z_stream
* SpdyFramer::GetHeaderDecompressor() {
3043 if (header_decompressor_
.get())
3044 return header_decompressor_
.get(); // Already initialized.
3046 header_decompressor_
.reset(new z_stream
);
3047 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
3049 int success
= inflateInit(header_decompressor_
.get());
3050 if (success
!= Z_OK
) {
3051 LOG(WARNING
) << "inflateInit failure: " << success
;
3052 header_decompressor_
.reset(NULL
);
3055 return header_decompressor_
.get();
3058 HpackEncoder
* SpdyFramer::GetHpackEncoder() {
3059 DCHECK_LT(SPDY3
, spdy_version_
);
3060 if (hpack_encoder_
.get() == NULL
) {
3061 hpack_encoder_
.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3063 return hpack_encoder_
.get();
3066 HpackDecoder
* SpdyFramer::GetHpackDecoder() {
3067 DCHECK_LT(SPDY3
, spdy_version_
);
3068 if (hpack_decoder_
.get() == NULL
) {
3069 hpack_decoder_
.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3071 return hpack_decoder_
.get();
3074 uint8
SpdyFramer::MapPriorityToWeight(SpdyPriority priority
) {
3075 const float kSteps
= 255.9f
/ 7.f
;
3076 return static_cast<uint8
>(kSteps
* (7.f
- priority
));
3079 SpdyPriority
SpdyFramer::MapWeightToPriority(uint8 weight
) {
3080 const float kSteps
= 255.9f
/ 7.f
;
3081 return static_cast<SpdyPriority
>(7.f
- weight
/ kSteps
);
3084 // Incrementally decompress the control frame's header block, feeding the
3085 // result to the visitor in chunks. Continue this until the visitor
3086 // indicates that it cannot process any more data, or (more commonly) we
3087 // run out of data to deliver.
3088 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3089 SpdyStreamId stream_id
,
3092 // Get a decompressor or set error.
3093 z_stream
* decomp
= GetHeaderDecompressor();
3094 if (decomp
== NULL
) {
3095 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
3096 set_error(SPDY_DECOMPRESS_FAILURE
);
3100 bool processed_successfully
= true;
3101 char buffer
[kHeaderDataChunkMaxSize
];
3103 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
3104 decomp
->avail_in
= len
;
3105 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3106 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3107 // reached this method successfully, stream_id should be nonzero.
3108 DCHECK_LT(0u, stream_id
);
3109 while (decomp
->avail_in
> 0 && processed_successfully
) {
3110 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
3111 decomp
->avail_out
= arraysize(buffer
);
3113 int rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3114 if (rv
== Z_NEED_DICT
) {
3115 const char* dictionary
= (protocol_version() <= SPDY2
) ? kV2Dictionary
3117 const int dictionary_size
= (protocol_version() <= SPDY2
) ?
3118 kV2DictionarySize
: kV3DictionarySize
;
3119 const DictionaryIds
& ids
= g_dictionary_ids
.Get();
3120 const uLong dictionary_id
= (protocol_version() <= SPDY2
) ?
3121 ids
.v2_dictionary_id
: ids
.v3_dictionary_id
;
3122 // Need to try again with the right dictionary.
3123 if (decomp
->adler
== dictionary_id
) {
3124 rv
= inflateSetDictionary(decomp
,
3125 reinterpret_cast<const Bytef
*>(dictionary
),
3128 rv
= inflate(decomp
, Z_SYNC_FLUSH
);
3132 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3133 // without producing any output. The input is consumed and
3134 // buffered internally by zlib so we can detect this condition by
3135 // checking if avail_in is 0 after the call to inflate.
3136 bool input_exhausted
= ((rv
== Z_BUF_ERROR
) && (decomp
->avail_in
== 0));
3137 if ((rv
== Z_OK
) || input_exhausted
) {
3138 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
3139 if (decompressed_len
> 0) {
3140 processed_successfully
= visitor_
->OnControlFrameHeaderData(
3141 stream_id
, buffer
, decompressed_len
);
3143 if (!processed_successfully
) {
3144 // Assume that the problem was the header block was too large for the
3146 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3149 DLOG(WARNING
) << "inflate failure: " << rv
<< " " << len
;
3150 set_error(SPDY_DECOMPRESS_FAILURE
);
3151 processed_successfully
= false;
3154 return processed_successfully
;
3157 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3158 SpdyStreamId stream_id
, const char* data
, size_t len
) {
3159 bool read_successfully
= true;
3160 while (read_successfully
&& len
> 0) {
3161 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
3162 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
3164 data
+= bytes_to_deliver
;
3165 len
-= bytes_to_deliver
;
3166 if (!read_successfully
) {
3167 // Assume that the problem was the header block was too large for the
3169 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
3172 return read_successfully
;
3175 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3176 SpdyFrameBuilder
* builder
,
3177 const SpdyNameValueBlock
& name_value_block
) const {
3178 // Serialize number of headers.
3179 if (protocol_version() <= SPDY2
) {
3180 builder
->WriteUInt16(name_value_block
.size());
3182 builder
->WriteUInt32(name_value_block
.size());
3185 // Serialize each header.
3186 for (SpdyHeaderBlock::const_iterator it
= name_value_block
.begin();
3187 it
!= name_value_block
.end();
3189 if (protocol_version() <= SPDY2
) {
3190 builder
->WriteString(it
->first
);
3191 builder
->WriteString(it
->second
);
3193 builder
->WriteStringPiece32(it
->first
);
3194 builder
->WriteStringPiece32(it
->second
);
3199 void SpdyFramer::SerializeNameValueBlock(
3200 SpdyFrameBuilder
* builder
,
3201 const SpdyFrameWithNameValueBlockIR
& frame
) {
3202 CHECK_GE(SPDY3
, protocol_version());
3203 if (!enable_compression_
) {
3204 return SerializeNameValueBlockWithoutCompression(builder
,
3205 frame
.name_value_block());
3208 // First build an uncompressed version to be fed into the compressor.
3209 const size_t uncompressed_len
= GetSerializedLength(
3210 protocol_version(), &(frame
.name_value_block()));
3211 SpdyFrameBuilder
uncompressed_builder(uncompressed_len
, protocol_version());
3212 SerializeNameValueBlockWithoutCompression(&uncompressed_builder
,
3213 frame
.name_value_block());
3214 scoped_ptr
<SpdyFrame
> uncompressed_payload(uncompressed_builder
.take());
3216 z_stream
* compressor
= GetHeaderCompressor();
3218 LOG(DFATAL
) << "Could not obtain compressor.";
3222 base::StatsCounter
compressed_frames("spdy.CompressedFrames");
3223 base::StatsCounter
pre_compress_bytes("spdy.PreCompressSize");
3224 base::StatsCounter
post_compress_bytes("spdy.PostCompressSize");
3226 // Create an output frame.
3227 // Since we'll be performing lots of flushes when compressing the data,
3228 // zlib's lower bounds may be insufficient.
3230 // TODO(akalin): Avoid the duplicate calculation with
3231 // GetSerializedLength(const SpdyHeaderBlock&).
3232 const int compressed_max_size
=
3233 2 * deflateBound(compressor
, uncompressed_len
);
3235 // TODO(phajdan.jr): Clean up after we no longer need
3236 // to workaround http://crbug.com/139744.
3237 #if defined(USE_SYSTEM_ZLIB)
3238 compressor
->next_in
= reinterpret_cast<Bytef
*>(uncompressed_payload
->data());
3239 compressor
->avail_in
= uncompressed_len
;
3240 #endif // defined(USE_SYSTEM_ZLIB)
3241 compressor
->next_out
= reinterpret_cast<Bytef
*>(
3242 builder
->GetWritableBuffer(compressed_max_size
));
3243 compressor
->avail_out
= compressed_max_size
;
3245 // TODO(phajdan.jr): Clean up after we no longer need
3246 // to workaround http://crbug.com/139744.
3247 #if defined(USE_SYSTEM_ZLIB)
3248 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
3249 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
3250 // This shouldn't happen, right?
3251 LOG(WARNING
) << "deflate failure: " << rv
;
3252 // TODO(akalin): Upstream this return.
3256 WriteHeaderBlockToZ(&frame
.name_value_block(), compressor
);
3257 #endif // defined(USE_SYSTEM_ZLIB)
3259 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
3260 builder
->Seek(compressed_size
);
3261 builder
->RewriteLength(*this);
3263 pre_compress_bytes
.Add(uncompressed_len
);
3264 post_compress_bytes
.Add(compressed_size
);
3266 compressed_frames
.Increment();