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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't
6 // constantly adding and subtracting header sizes; this is ugly and error-
9 #include "net/spdy/spdy_framer.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/stats_counters.h"
14 #include "base/third_party/valgrind/memcheck.h"
15 #include "net/spdy/spdy_frame_builder.h"
16 #include "net/spdy/spdy_frame_reader.h"
17 #include "net/spdy/spdy_bitmasks.h"
18 #include "third_party/zlib/zlib.h"
26 // Compute the id of our dictionary so that we know we're using the
27 // right one when asked for it.
28 uLong
CalculateDictionaryId(const char* dictionary
,
29 const size_t dictionary_size
) {
30 uLong initial_value
= adler32(0L, Z_NULL
, 0);
31 return adler32(initial_value
,
32 reinterpret_cast<const Bytef
*>(dictionary
),
36 struct DictionaryIds
{
38 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary
, kV2DictionarySize
)),
39 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary
, kV3DictionarySize
))
41 const uLong v2_dictionary_id
;
42 const uLong v3_dictionary_id
;
45 // Adler ID for the SPDY header compressor dictionaries. Note that they are
46 // initialized lazily to avoid static initializers.
47 base::LazyInstance
<DictionaryIds
>::Leaky g_dictionary_ids
;
51 const int SpdyFramer::kMinSpdyVersion
= 2;
52 const int SpdyFramer::kMaxSpdyVersion
= 3;
53 const SpdyStreamId
SpdyFramer::kInvalidStream
= -1;
54 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
55 const size_t SpdyFramer::kControlFrameBufferSize
=
56 sizeof(SpdySynStreamControlFrameBlock
);
57 const size_t SpdyFramer::kMaxControlFrameSize
= 16 * 1024;
59 #ifdef DEBUG_SPDY_STATE_CHANGES
60 #define CHANGE_STATE(newstate) \
62 LOG(INFO) << "Changing state from: " \
63 << StateToString(state_) \
64 << " to " << StateToString(newstate) << "\n"; \
65 DCHECK(state_ != SPDY_ERROR); \
66 DCHECK_EQ(previous_state_, state_); \
67 previous_state_ = state_; \
71 #define CHANGE_STATE(newstate) \
73 DCHECK(state_ != SPDY_ERROR); \
74 DCHECK_EQ(previous_state_, state_); \
75 previous_state_ = state_; \
80 SettingsFlagsAndId
SettingsFlagsAndId::FromWireFormat(int version
,
83 ConvertFlagsAndIdForSpdy2(&wire
);
85 return SettingsFlagsAndId(ntohl(wire
) >> 24, ntohl(wire
) & 0x00ffffff);
88 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags
, uint32 id
)
89 : flags_(flags
), id_(id
& 0x00ffffff) {
90 DCHECK_GT(1u << 24, id
) << "SPDY setting ID too large.";
93 uint32
SettingsFlagsAndId::GetWireFormat(int version
) const {
94 uint32 wire
= htonl(id_
& 0x00ffffff) | htonl(flags_
<< 24);
96 ConvertFlagsAndIdForSpdy2(&wire
);
101 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
102 // This method is used to preserve buggy behavior and works on both
103 // little-endian and big-endian hosts.
104 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
105 // as well as vice versa).
106 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32
* val
) {
107 uint8
* wire_array
= reinterpret_cast<uint8
*>(val
);
108 std::swap(wire_array
[0], wire_array
[3]);
109 std::swap(wire_array
[1], wire_array
[2]);
112 SpdyCredential::SpdyCredential() : slot(0) {}
113 SpdyCredential::~SpdyCredential() {}
115 SpdyFramer::SpdyFramer(int version
)
116 : state_(SPDY_RESET
),
117 previous_state_(SPDY_RESET
),
118 error_code_(SPDY_NO_ERROR
),
120 remaining_control_payload_(0),
121 remaining_control_header_(0),
122 current_frame_buffer_(new char[kControlFrameBufferSize
]),
123 current_frame_len_(0),
124 enable_compression_(true),
126 display_protocol_("SPDY"),
127 spdy_version_(version
),
128 syn_frame_processed_(false),
129 probable_http_response_(false) {
130 DCHECK_GE(kMaxSpdyVersion
, version
);
131 DCHECK_LE(kMinSpdyVersion
, version
);
134 SpdyFramer::~SpdyFramer() {
135 if (header_compressor_
.get()) {
136 deflateEnd(header_compressor_
.get());
138 if (header_decompressor_
.get()) {
139 inflateEnd(header_decompressor_
.get());
143 void SpdyFramer::Reset() {
145 previous_state_
= SPDY_RESET
;
146 error_code_
= SPDY_NO_ERROR
;
148 remaining_control_payload_
= 0;
149 remaining_control_header_
= 0;
150 current_frame_len_
= 0;
151 settings_scratch_
.Reset();
154 const char* SpdyFramer::StateToString(int state
) {
160 case SPDY_AUTO_RESET
:
164 case SPDY_READING_COMMON_HEADER
:
165 return "READING_COMMON_HEADER";
166 case SPDY_CONTROL_FRAME_PAYLOAD
:
167 return "CONTROL_FRAME_PAYLOAD";
168 case SPDY_IGNORE_REMAINING_PAYLOAD
:
169 return "IGNORE_REMAINING_PAYLOAD";
170 case SPDY_FORWARD_STREAM_FRAME
:
171 return "FORWARD_STREAM_FRAME";
172 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
173 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
174 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
175 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
176 case SPDY_CREDENTIAL_FRAME_PAYLOAD
:
177 return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
178 case SPDY_SETTINGS_FRAME_PAYLOAD
:
179 return "SPDY_SETTINGS_FRAME_PAYLOAD";
181 return "UNKNOWN_STATE";
184 void SpdyFramer::set_error(SpdyError error
) {
187 CHANGE_STATE(SPDY_ERROR
);
188 visitor_
->OnError(this);
191 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
192 switch (error_code
) {
195 case SPDY_INVALID_CONTROL_FRAME
:
196 return "INVALID_CONTROL_FRAME";
197 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
198 return "CONTROL_PAYLOAD_TOO_LARGE";
199 case SPDY_ZLIB_INIT_FAILURE
:
200 return "ZLIB_INIT_FAILURE";
201 case SPDY_UNSUPPORTED_VERSION
:
202 return "UNSUPPORTED_VERSION";
203 case SPDY_DECOMPRESS_FAILURE
:
204 return "DECOMPRESS_FAILURE";
205 case SPDY_COMPRESS_FAILURE
:
206 return "COMPRESS_FAILURE";
207 case SPDY_INVALID_DATA_FRAME_FLAGS
:
208 return "SPDY_INVALID_DATA_FRAME_FLAGS";
210 return "UNKNOWN_ERROR";
213 const char* SpdyFramer::StatusCodeToString(int status_code
) {
214 switch (status_code
) {
218 return "PROTOCOL_ERROR";
220 return "INVALID_STREAM";
222 return "REFUSED_STREAM";
223 case UNSUPPORTED_VERSION
:
224 return "UNSUPPORTED_VERSION";
228 return "INTERNAL_ERROR";
229 case FLOW_CONTROL_ERROR
:
230 return "FLOW_CONTROL_ERROR";
232 return "STREAM_IN_USE";
233 case STREAM_ALREADY_CLOSED
:
234 return "STREAM_ALREADY_CLOSED";
235 case INVALID_CREDENTIALS
:
236 return "INVALID_CREDENTIALS";
237 case FRAME_TOO_LARGE
:
238 return "FRAME_TOO_LARGE";
240 return "UNKNOWN_STATUS";
243 const char* SpdyFramer::ControlTypeToString(SpdyControlType type
) {
262 return "WINDOW_UPDATE";
265 case NUM_CONTROL_FRAME_TYPES
:
268 return "UNKNOWN_CONTROL_TYPE";
271 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
275 size_t original_len
= len
;
277 previous_state_
= state_
;
283 case SPDY_AUTO_RESET
:
287 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
291 case SPDY_READING_COMMON_HEADER
: {
292 size_t bytes_read
= ProcessCommonHeader(data
, len
);
298 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
299 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY,
300 // HEADERS) take a different path through the state machine - they
302 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
303 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
305 // SETTINGS frames take a slightly modified route:
306 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
307 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
309 // All other control frames will use the alternate route directly to
310 // SPDY_CONTROL_FRAME_PAYLOAD
311 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
317 case SPDY_SETTINGS_FRAME_PAYLOAD
: {
318 int bytes_read
= ProcessSettingsFramePayload(data
, len
);
324 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
325 int bytes_read
= ProcessControlFrameHeaderBlock(data
, len
);
331 case SPDY_CREDENTIAL_FRAME_PAYLOAD
: {
332 size_t bytes_read
= ProcessCredentialFramePayload(data
, len
);
338 case SPDY_CONTROL_FRAME_PAYLOAD
: {
339 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
345 case SPDY_IGNORE_REMAINING_PAYLOAD
:
346 // control frame has too-large payload
347 // intentional fallthrough
348 case SPDY_FORWARD_STREAM_FRAME
: {
349 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
355 LOG(DFATAL
) << "Invalid value for " << display_protocol_
356 << " framer state: " << state_
;
357 // This ensures that we don't infinite-loop if state_ gets an
358 // invalid value somehow, such as due to a SpdyFramer getting deleted
359 // from a callback it calls.
362 } while (state_
!= previous_state_
);
364 DCHECK(len
== 0 || state_
== SPDY_ERROR
);
365 if (current_frame_len_
== 0 &&
366 remaining_data_
== 0 &&
367 remaining_control_payload_
== 0 &&
368 remaining_control_header_
== 0) {
369 DCHECK(state_
== SPDY_RESET
|| state_
== SPDY_ERROR
)
370 << "State: " << StateToString(state_
);
373 return original_len
- len
;
376 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
377 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
379 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
381 size_t original_len
= len
;
382 SpdyFrame
current_frame(current_frame_buffer_
.get(), false);
384 // Update current frame buffer as needed.
385 if (current_frame_len_
< SpdyFrame::kHeaderSize
) {
386 size_t bytes_desired
= SpdyFrame::kHeaderSize
- current_frame_len_
;
387 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
390 if (current_frame_len_
< SpdyFrame::kHeaderSize
) {
391 // TODO(rch): remove this empty block
394 remaining_data_
= current_frame
.length();
396 // This is just a sanity check for help debugging early frame errors.
397 if (remaining_data_
> 1000000u) {
398 // The strncmp for 5 is safe because we only hit this point if we
399 // have SpdyFrame::kHeaderSize (8) bytes
400 if (!syn_frame_processed_
&&
401 strncmp(current_frame_buffer_
.get(), "HTTP/", 5) == 0) {
402 LOG(WARNING
) << "Unexpected HTTP response to spdy request";
403 probable_http_response_
= true;
405 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
406 << " session is likely corrupt.";
410 // if we're here, then we have the common header all received.
411 if (!current_frame
.is_control_frame()) {
412 SpdyDataFrame
data_frame(current_frame_buffer_
.get(), false);
413 visitor_
->OnDataFrameHeader(&data_frame
);
415 if (current_frame
.length() > 0) {
416 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
419 if (current_frame
.flags() & DATA_FLAG_FIN
) {
420 visitor_
->OnStreamFrameData(data_frame
.stream_id(),
421 NULL
, 0, DATA_FLAG_FIN
);
423 CHANGE_STATE(SPDY_AUTO_RESET
);
426 ProcessControlFrameHeader();
429 return original_len
- len
;
432 void SpdyFramer::ProcessControlFrameHeader() {
433 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
434 DCHECK_LE(static_cast<size_t>(SpdyFrame::kHeaderSize
), current_frame_len_
);
435 SpdyControlFrame
current_control_frame(current_frame_buffer_
.get(), false);
437 // We check version before we check validity: version can never be 'invalid',
438 // it can only be unsupported.
439 if (current_control_frame
.version() != spdy_version_
) {
440 DLOG(INFO
) << "Unsupported SPDY version " << current_control_frame
.version()
441 << " (expected " << spdy_version_
<< ")";
442 set_error(SPDY_UNSUPPORTED_VERSION
);
446 // Next up, check to see if we have valid data. This should be after version
447 // checking (otherwise if the the type were out of bounds due to a version
448 // upgrade we would misclassify the error) and before checking the type
449 // (type can definitely be out of bounds)
450 if (!current_control_frame
.AppearsToBeAValidControlFrame()) {
451 set_error(SPDY_INVALID_CONTROL_FRAME
);
455 if (current_control_frame
.type() == NOOP
) {
456 DLOG(INFO
) << "NOOP control frame found. Ignoring.";
457 CHANGE_STATE(SPDY_AUTO_RESET
);
461 // Do some sanity checking on the control frame sizes.
462 switch (current_control_frame
.type()) {
464 if (current_control_frame
.length() <
465 SpdySynStreamControlFrame::size() - SpdyControlFrame::kHeaderSize
)
466 set_error(SPDY_INVALID_CONTROL_FRAME
);
469 if (current_control_frame
.length() <
470 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize
)
471 set_error(SPDY_INVALID_CONTROL_FRAME
);
474 if (current_control_frame
.length() !=
475 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize
)
476 set_error(SPDY_INVALID_CONTROL_FRAME
);
479 // Make sure that we have an integral number of 8-byte key/value pairs,
480 // plus a 4-byte length field.
481 if (current_control_frame
.length() <
482 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize
||
483 (current_control_frame
.length() % 8 != 4)) {
484 DLOG(WARNING
) << "Invalid length for SETTINGS frame: "
485 << current_control_frame
.length();
486 set_error(SPDY_INVALID_CONTROL_FRAME
);
491 // SPDY 2 GOAWAY frames are 4 bytes smaller than in SPDY 3. We account
492 // for this difference via a separate offset variable, since
493 // SpdyGoAwayControlFrame::size() returns the SPDY 3 size.
494 const size_t goaway_offset
= (protocol_version() < 3) ? 4 : 0;
495 if (current_control_frame
.length() + goaway_offset
!=
496 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize
)
497 set_error(SPDY_INVALID_CONTROL_FRAME
);
501 if (current_control_frame
.length() <
502 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize
)
503 set_error(SPDY_INVALID_CONTROL_FRAME
);
506 if (current_control_frame
.length() !=
507 SpdyWindowUpdateControlFrame::size() -
508 SpdyControlFrame::kHeaderSize
)
509 set_error(SPDY_INVALID_CONTROL_FRAME
);
512 if (current_control_frame
.length() !=
513 SpdyPingControlFrame::size() - SpdyControlFrame::kHeaderSize
)
514 set_error(SPDY_INVALID_CONTROL_FRAME
);
517 if (current_control_frame
.length() <
518 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize
)
519 set_error(SPDY_INVALID_CONTROL_FRAME
);
522 LOG(WARNING
) << "Valid " << display_protocol_
523 << " control frame with unhandled type: "
524 << current_control_frame
.type();
526 set_error(SPDY_INVALID_CONTROL_FRAME
);
530 if (state_
== SPDY_ERROR
) {
534 remaining_control_payload_
= current_control_frame
.length();
535 const size_t total_frame_size
=
536 remaining_control_payload_
+ SpdyFrame::kHeaderSize
;
537 if (total_frame_size
> kMaxControlFrameSize
) {
538 DLOG(WARNING
) << "Received control frame with way too big of a payload: "
540 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
544 if (current_control_frame
.type() == CREDENTIAL
) {
545 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD
);
549 // Determine the frame size without variable-length data.
550 int32 frame_size_without_variable_data
;
551 switch (current_control_frame
.type()) {
553 syn_frame_processed_
= true;
554 frame_size_without_variable_data
= SpdySynStreamControlFrame::size();
557 syn_frame_processed_
= true;
558 frame_size_without_variable_data
= SpdySynReplyControlFrame::size();
559 // SPDY 2 had two bytes of unused space preceeding payload.
560 if (spdy_version_
< 3) {
561 frame_size_without_variable_data
+= 2;
565 frame_size_without_variable_data
= SpdyHeadersControlFrame::size();
566 // SPDY 2 had two bytes of unused space preceeding payload.
567 if (spdy_version_
< 3) {
568 frame_size_without_variable_data
+= 2;
572 frame_size_without_variable_data
= SpdySettingsControlFrame::size();
575 frame_size_without_variable_data
= -1;
579 if ((frame_size_without_variable_data
== -1) &&
580 (total_frame_size
> kControlFrameBufferSize
)) {
581 // We should already be in an error state. Double-check.
582 DCHECK_EQ(SPDY_ERROR
, state_
);
583 if (state_
!= SPDY_ERROR
) {
584 LOG(DFATAL
) << display_protocol_
585 << " control frame buffer too small for fixed-length frame.";
586 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
590 if (frame_size_without_variable_data
> 0) {
591 // We have a control frame with a header block. We need to parse the
592 // remainder of the control frame's header before we can parse the header
593 // block. The start of the header block varies with the control type.
594 DCHECK_GE(frame_size_without_variable_data
,
595 static_cast<int32
>(current_frame_len_
));
596 remaining_control_header_
= frame_size_without_variable_data
-
598 remaining_control_payload_
+= SpdyFrame::kHeaderSize
-
599 frame_size_without_variable_data
;
600 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
604 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
607 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
609 size_t bytes_to_read
= std::min(*len
, max_bytes
);
610 DCHECK_GE(kControlFrameBufferSize
, current_frame_len_
+ bytes_to_read
);
611 memcpy(current_frame_buffer_
.get() + current_frame_len_
,
614 current_frame_len_
+= bytes_to_read
;
615 *data
+= bytes_to_read
;
616 *len
-= bytes_to_read
;
617 return bytes_to_read
;
620 size_t SpdyFramer::GetSerializedLength(const int spdy_version
,
621 const SpdyHeaderBlock
* headers
) {
622 const size_t num_name_value_pairs_size
623 = (spdy_version
< 3) ? sizeof(uint16
) : sizeof(uint32
);
624 const size_t length_of_name_size
= num_name_value_pairs_size
;
625 const size_t length_of_value_size
= num_name_value_pairs_size
;
627 size_t total_length
= num_name_value_pairs_size
;
628 for (SpdyHeaderBlock::const_iterator it
= headers
->begin();
629 it
!= headers
->end();
631 // We add space for the length of the name and the length of the value as
632 // well as the length of the name and the length of the value.
633 total_length
+= length_of_name_size
+ it
->first
.size() +
634 length_of_value_size
+ it
->second
.size();
639 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder
* frame
,
640 const int spdy_version
,
641 const SpdyHeaderBlock
* headers
) {
642 if (spdy_version
< 3) {
643 frame
->WriteUInt16(headers
->size()); // Number of headers.
645 frame
->WriteUInt32(headers
->size()); // Number of headers.
647 SpdyHeaderBlock::const_iterator it
;
648 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
650 if (spdy_version
< 3) {
651 wrote_header
= frame
->WriteString(it
->first
);
652 wrote_header
&= frame
->WriteString(it
->second
);
654 wrote_header
= frame
->WriteStringPiece32(it
->first
);
655 wrote_header
&= frame
->WriteStringPiece32(it
->second
);
657 DCHECK(wrote_header
);
661 // TODO(phajdan.jr): Clean up after we no longer need
662 // to workaround http://crbug.com/139744.
663 #if !defined(USE_SYSTEM_ZLIB)
665 // These constants are used by zlib to differentiate between normal data and
666 // cookie data. Cookie data is handled specially by zlib when compressing.
668 // kZStandardData is compressed normally, save that it will never match
669 // against any other class of data in the window.
670 kZStandardData
= Z_CLASS_STANDARD
,
671 // kZCookieData is compressed in its own Huffman blocks and only matches in
672 // its entirety and only against other kZCookieData blocks. Any matches must
673 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
674 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
676 kZCookieData
= Z_CLASS_COOKIE
,
677 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
678 // against the window.
679 kZHuffmanOnlyData
= Z_CLASS_HUFFMAN_ONLY
,
682 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
683 // needed when switching between classes of data.
684 static void WriteZ(const base::StringPiece
& data
,
689 // If we are switching from standard to non-standard data then we need to end
690 // the current Huffman context to avoid it leaking between them.
691 if (out
->clas
== kZStandardData
&&
692 clas
!= kZStandardData
) {
694 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
696 DCHECK_EQ(0u, out
->avail_in
);
697 DCHECK_LT(0u, out
->avail_out
);
700 out
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
.data()));
701 out
->avail_in
= data
.size();
703 if (clas
== kZStandardData
) {
704 rv
= deflate(out
, Z_NO_FLUSH
);
706 rv
= deflate(out
, Z_PARTIAL_FLUSH
);
709 DCHECK_EQ(0u, out
->avail_in
);
710 DCHECK_LT(0u, out
->avail_out
);
713 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
714 static void WriteLengthZ(size_t n
,
719 DCHECK_LE(length
, sizeof(buf
));
720 for (unsigned i
= 1; i
<= length
; i
++) {
724 WriteZ(base::StringPiece(buf
, length
), clas
, out
);
727 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
728 // manner that resists the length of the compressed data from compromising
730 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock
* headers
,
732 unsigned length_length
= 4;
733 if (spdy_version_
< 3)
736 WriteLengthZ(headers
->size(), length_length
, kZStandardData
, z
);
738 std::map
<std::string
, std::string
>::const_iterator it
;
739 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
740 WriteLengthZ(it
->first
.size(), length_length
, kZStandardData
, z
);
741 WriteZ(it
->first
, kZStandardData
, z
);
743 if (it
->first
== "cookie") {
744 // We require the cookie values (save for the last) to end with a
745 // semicolon and (save for the first) to start with a space. This is
746 // typically the format that we are given them in but we reserialize them
749 std::vector
<base::StringPiece
> cookie_values
;
750 size_t cookie_length
= 0;
751 base::StringPiece
cookie_data(it
->second
);
754 while (!cookie_data
.empty() &&
755 (cookie_data
[0] == ' ' || cookie_data
[0] == '\t')) {
756 cookie_data
.remove_prefix(1);
758 if (cookie_data
.empty())
762 for (i
= 0; i
< cookie_data
.size(); i
++) {
763 if (cookie_data
[i
] == ';')
766 if (i
< cookie_data
.size()) {
767 cookie_values
.push_back(cookie_data
.substr(0, i
));
768 cookie_length
+= i
+ 2 /* semicolon and space */;
769 cookie_data
.remove_prefix(i
+ 1);
771 cookie_values
.push_back(cookie_data
);
772 cookie_length
+= cookie_data
.size();
773 cookie_data
.remove_prefix(i
);
777 WriteLengthZ(cookie_length
, length_length
, kZStandardData
, z
);
778 for (size_t i
= 0; i
< cookie_values
.size(); i
++) {
780 // Since zlib will only back-reference complete cookies, a cookie that
781 // is currently last (and so doesn't have a trailing semicolon) won't
782 // match if it's later in a non-final position. The same is true of
784 if (i
== 0 && cookie_values
.size() == 1) {
785 cookie
= cookie_values
[i
].as_string();
787 cookie
= cookie_values
[i
].as_string() + ";";
788 } else if (i
< cookie_values
.size() - 1) {
789 cookie
= " " + cookie_values
[i
].as_string() + ";";
791 cookie
= " " + cookie_values
[i
].as_string();
793 WriteZ(cookie
, kZCookieData
, z
);
795 } else if (it
->first
== "accept" ||
796 it
->first
== "accept-charset" ||
797 it
->first
== "accept-encoding" ||
798 it
->first
== "accept-language" ||
799 it
->first
== "host" ||
800 it
->first
== "version" ||
801 it
->first
== "method" ||
802 it
->first
== "scheme" ||
803 it
->first
== ":host" ||
804 it
->first
== ":version" ||
805 it
->first
== ":method" ||
806 it
->first
== ":scheme" ||
807 it
->first
== "user-agent") {
808 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
809 WriteZ(it
->second
, kZStandardData
, z
);
811 // Non-whitelisted headers are Huffman compressed in their own block, but
812 // don't match against the window.
813 WriteLengthZ(it
->second
.size(), length_length
, kZStandardData
, z
);
814 WriteZ(it
->second
, kZHuffmanOnlyData
, z
);
819 int rv
= deflate(z
, Z_SYNC_FLUSH
);
821 z
->clas
= kZStandardData
;
823 #endif // !defined(USE_SYSTEM_ZLIB)
825 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
827 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
828 size_t original_len
= len
;
830 if (remaining_control_header_
> 0) {
831 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
832 remaining_control_header_
);
833 remaining_control_header_
-= bytes_read
;
836 if (remaining_control_header_
== 0) {
837 SpdyControlFrame
control_frame(current_frame_buffer_
.get(), false);
838 switch (control_frame
.type()) {
841 SpdySynStreamControlFrame
* syn_stream_frame
=
842 reinterpret_cast<SpdySynStreamControlFrame
*>(&control_frame
);
843 // TODO(hkhalil): Check that invalid flag bits are unset?
844 visitor_
->OnSynStream(
845 syn_stream_frame
->stream_id(),
846 syn_stream_frame
->associated_stream_id(),
847 syn_stream_frame
->priority(),
848 syn_stream_frame
->credential_slot(),
849 (syn_stream_frame
->flags() & CONTROL_FLAG_FIN
) != 0,
850 (syn_stream_frame
->flags() & CONTROL_FLAG_UNIDIRECTIONAL
) != 0);
852 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
856 SpdySynReplyControlFrame
* syn_reply_frame
=
857 reinterpret_cast<SpdySynReplyControlFrame
*>(&control_frame
);
858 visitor_
->OnSynReply(
859 syn_reply_frame
->stream_id(),
860 (syn_reply_frame
->flags() & CONTROL_FLAG_FIN
) != 0);
862 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
866 SpdyHeadersControlFrame
* headers_frame
=
867 reinterpret_cast<SpdyHeadersControlFrame
*>(&control_frame
);
869 headers_frame
->stream_id(),
870 (headers_frame
->flags() & CONTROL_FLAG_FIN
) != 0);
872 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
875 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD
);
881 return original_len
- len
;
884 // Does not buffer the control payload. Instead, either passes directly to the
885 // visitor or decompresses and then passes directly to the visitor, via
886 // IncrementallyDeliverControlFrameHeaderData() or
887 // IncrementallyDecompressControlFrameHeaderData() respectively.
888 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
890 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
891 SpdyControlFrame
control_frame(current_frame_buffer_
.get(), false);
893 bool processed_successfully
= true;
894 DCHECK(control_frame
.type() == SYN_STREAM
||
895 control_frame
.type() == SYN_REPLY
||
896 control_frame
.type() == HEADERS
);
897 size_t process_bytes
= std::min(data_len
, remaining_control_payload_
);
898 if (process_bytes
> 0) {
899 if (enable_compression_
) {
900 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
901 &control_frame
, data
, process_bytes
);
903 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
904 &control_frame
, data
, process_bytes
);
907 remaining_control_payload_
-= process_bytes
;
908 remaining_data_
-= process_bytes
;
911 // Handle the case that there is no futher data in this frame.
912 if (remaining_control_payload_
== 0 && processed_successfully
) {
913 // The complete header block has been delivered. We send a zero-length
914 // OnControlFrameHeaderData() to indicate this.
915 visitor_
->OnControlFrameHeaderData(
916 GetControlFrameStreamId(&control_frame
), NULL
, 0);
918 // If this is a FIN, tell the caller.
919 if (control_frame
.flags() & CONTROL_FLAG_FIN
) {
920 visitor_
->OnStreamFrameData(GetControlFrameStreamId(&control_frame
),
921 NULL
, 0, DATA_FLAG_FIN
);
924 CHANGE_STATE(SPDY_AUTO_RESET
);
928 if (!processed_successfully
) {
932 // Return amount processed.
933 return process_bytes
;
936 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data
,
938 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD
, state_
);
939 SpdyControlFrame
control_frame(current_frame_buffer_
.get(), false);
940 DCHECK_EQ(SETTINGS
, control_frame
.type());
941 size_t unprocessed_bytes
= std::min(data_len
, remaining_control_payload_
);
942 size_t processed_bytes
= 0;
944 // Loop over our incoming data.
945 while (unprocessed_bytes
> 0) {
946 // Process up to one setting at a time.
947 size_t processing
= std::min(
949 static_cast<size_t>(8 - settings_scratch_
.setting_buf_len
));
951 // Check if we have a complete setting in our input.
952 if (processing
== 8) {
953 // Parse the setting directly out of the input without buffering.
954 if (!ProcessSetting(data
+ processed_bytes
)) {
955 set_error(SPDY_INVALID_CONTROL_FRAME
);
956 return processed_bytes
;
959 // Continue updating settings_scratch_.setting_buf.
960 memcpy(settings_scratch_
.setting_buf
+ settings_scratch_
.setting_buf_len
,
961 data
+ processed_bytes
,
963 settings_scratch_
.setting_buf_len
+= processing
;
965 // Check if we have a complete setting buffered.
966 if (settings_scratch_
.setting_buf_len
== 8) {
967 if (!ProcessSetting(settings_scratch_
.setting_buf
)) {
968 set_error(SPDY_INVALID_CONTROL_FRAME
);
969 return processed_bytes
;
971 // Reset settings_scratch_.setting_buf for our next setting.
972 settings_scratch_
.setting_buf_len
= 0;
977 unprocessed_bytes
-= processing
;
978 processed_bytes
+= processing
;
981 // Check if we're done handling this SETTINGS frame.
982 remaining_control_payload_
-= processed_bytes
;
983 if (remaining_control_payload_
== 0) {
984 CHANGE_STATE(SPDY_AUTO_RESET
);
987 return processed_bytes
;
990 bool SpdyFramer::ProcessSetting(const char* data
) {
992 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
993 const uint32 id_and_flags_wire
= *(reinterpret_cast<const uint32
*>(data
));
994 SettingsFlagsAndId id_and_flags
=
995 SettingsFlagsAndId::FromWireFormat(spdy_version_
, id_and_flags_wire
);
996 uint8 flags
= id_and_flags
.flags();
997 uint32 value
= ntohl(*(reinterpret_cast<const uint32
*>(data
+ 4)));
1000 switch (id_and_flags
.id()) {
1001 case SETTINGS_UPLOAD_BANDWIDTH
:
1002 case SETTINGS_DOWNLOAD_BANDWIDTH
:
1003 case SETTINGS_ROUND_TRIP_TIME
:
1004 case SETTINGS_MAX_CONCURRENT_STREAMS
:
1005 case SETTINGS_CURRENT_CWND
:
1006 case SETTINGS_DOWNLOAD_RETRANS_RATE
:
1007 case SETTINGS_INITIAL_WINDOW_SIZE
:
1011 DLOG(WARNING
) << "Unknown SETTINGS ID: " << id_and_flags
.id();
1014 SpdySettingsIds id
= static_cast<SpdySettingsIds
>(id_and_flags
.id());
1016 // Detect duplciates.
1017 if (static_cast<uint32
>(id
) <= settings_scratch_
.last_setting_id
) {
1018 DLOG(WARNING
) << "Duplicate entry or invalid ordering for id " << id
1019 << " in " << display_protocol_
<< " SETTINGS frame "
1020 << "(last settikng id was "
1021 << settings_scratch_
.last_setting_id
<< ").";
1024 settings_scratch_
.last_setting_id
= id
;
1027 uint8 kFlagsMask
= SETTINGS_FLAG_PLEASE_PERSIST
| SETTINGS_FLAG_PERSISTED
;
1028 if ((flags
& ~(kFlagsMask
)) != 0) {
1029 DLOG(WARNING
) << "Unknown SETTINGS flags provided for id " << id
<< ": "
1034 // Validation succeeded. Pass on to visitor.
1035 visitor_
->OnSetting(id
, flags
, value
);
1039 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
1040 size_t original_len
= len
;
1041 if (remaining_control_payload_
) {
1042 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
1043 remaining_control_payload_
);
1044 remaining_control_payload_
-= bytes_read
;
1045 remaining_data_
-= bytes_read
;
1046 if (remaining_control_payload_
== 0) {
1047 SpdyControlFrame
control_frame(current_frame_buffer_
.get(), false);
1048 DCHECK(!control_frame
.has_header_block());
1049 // Use frame-specific handlers.
1050 switch (control_frame
.type()) {
1052 SpdyPingControlFrame
* ping_frame
=
1053 reinterpret_cast<SpdyPingControlFrame
*>(&control_frame
);
1054 visitor_
->OnPing(ping_frame
->unique_id());
1057 case WINDOW_UPDATE
: {
1058 SpdyWindowUpdateControlFrame
*window_update_frame
=
1059 reinterpret_cast<SpdyWindowUpdateControlFrame
*>(&control_frame
);
1060 visitor_
->OnWindowUpdate(window_update_frame
->stream_id(),
1061 window_update_frame
->delta_window_size());
1065 SpdyRstStreamControlFrame
* rst_stream_frame
=
1066 reinterpret_cast<SpdyRstStreamControlFrame
*>(&control_frame
);
1067 visitor_
->OnRstStream(rst_stream_frame
->stream_id(),
1068 rst_stream_frame
->status());
1072 SpdyGoAwayControlFrame
* go_away_frame
=
1073 reinterpret_cast<SpdyGoAwayControlFrame
*>(&control_frame
);
1074 if (spdy_version_
< 3) {
1075 visitor_
->OnGoAway(go_away_frame
->last_accepted_stream_id(),
1078 visitor_
->OnGoAway(go_away_frame
->last_accepted_stream_id(),
1079 go_away_frame
->status());
1085 LOG(FATAL
) << "Unhandled control frame " << control_frame
.type();
1088 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
1091 return original_len
- len
;
1094 size_t SpdyFramer::ProcessCredentialFramePayload(const char* data
, size_t len
) {
1096 // Process only up to the end of this CREDENTIAL frame.
1097 len
= std::min(len
, remaining_control_payload_
);
1098 bool processed_succesfully
= visitor_
->OnCredentialFrameData(data
, len
);
1099 remaining_control_payload_
-= len
;
1100 remaining_data_
-= len
;
1101 if (!processed_succesfully
) {
1102 set_error(SPDY_CREDENTIAL_FRAME_CORRUPT
);
1103 } else if (remaining_control_payload_
== 0) {
1104 visitor_
->OnCredentialFrameData(NULL
, 0);
1105 CHANGE_STATE(SPDY_AUTO_RESET
);
1111 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
1112 size_t original_len
= len
;
1114 SpdyDataFrame
current_data_frame(current_frame_buffer_
.get(), false);
1115 if (remaining_data_
> 0) {
1116 size_t amount_to_forward
= std::min(remaining_data_
, len
);
1117 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
1118 // Only inform the visitor if there is data.
1119 if (amount_to_forward
) {
1120 visitor_
->OnStreamFrameData(current_data_frame
.stream_id(),
1121 data
, amount_to_forward
, SpdyDataFlags());
1124 data
+= amount_to_forward
;
1125 len
-= amount_to_forward
;
1126 remaining_data_
-= amount_to_forward
;
1128 // If the FIN flag is set, and there is no more data in this data
1129 // frame, inform the visitor of EOF via a 0-length data frame.
1130 if (!remaining_data_
&&
1131 current_data_frame
.flags() & DATA_FLAG_FIN
) {
1132 visitor_
->OnStreamFrameData(current_data_frame
.stream_id(),
1133 NULL
, 0, DATA_FLAG_FIN
);
1137 if (remaining_data_
== 0) {
1138 CHANGE_STATE(SPDY_AUTO_RESET
);
1140 return original_len
- len
;
1143 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
1144 size_t header_length
,
1145 SpdyHeaderBlock
* block
) const {
1146 SpdyFrameReader
reader(header_data
, header_length
);
1148 // Read number of headers.
1150 if (spdy_version_
< 3) {
1152 if (!reader
.ReadUInt16(&temp
)) {
1153 DLOG(INFO
) << "Unable to read number of headers.";
1158 if (!reader
.ReadUInt32(&num_headers
)) {
1159 DLOG(INFO
) << "Unable to read number of headers.";
1164 // Read each header.
1165 for (uint32 index
= 0; index
< num_headers
; ++index
) {
1166 base::StringPiece temp
;
1168 // Read header name.
1169 if ((spdy_version_
< 3) ? !reader
.ReadStringPiece16(&temp
)
1170 : !reader
.ReadStringPiece32(&temp
)) {
1171 DLOG(INFO
) << "Unable to read header name (" << index
+ 1 << " of "
1172 << num_headers
<< ").";
1175 std::string name
= temp
.as_string();
1177 // Read header value.
1178 if ((spdy_version_
< 3) ? !reader
.ReadStringPiece16(&temp
)
1179 : !reader
.ReadStringPiece32(&temp
)) {
1180 DLOG(INFO
) << "Unable to read header value (" << index
+ 1 << " of "
1181 << num_headers
<< ").";
1184 std::string value
= temp
.as_string();
1186 // Ensure no duplicates.
1187 if (block
->find(name
) != block
->end()) {
1188 DLOG(INFO
) << "Duplicate header '" << name
<< "' (" << index
+ 1 << " of "
1189 << num_headers
<< ").";
1194 (*block
)[name
] = value
;
1199 // TODO(hkhalil): Remove, or move to test utils kit.
1201 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame
* frame
,
1202 SettingsMap
* settings
) {
1203 DCHECK_EQ(frame
->type(), SETTINGS
);
1206 SpdyFrameReader
parser(frame
->header_block(), frame
->header_block_len());
1207 for (size_t index
= 0; index
< frame
->num_entries(); ++index
) {
1208 uint32 id_and_flags_wire
;
1210 // SettingsFlagsAndId accepts off-the-wire (network byte order) data, so we
1211 // use ReadBytes() instead of ReadUInt32() as the latter calls ntohl().
1212 if (!parser
.ReadBytes(&id_and_flags_wire
, 4)) {
1215 if (!parser
.ReadUInt32(&value
))
1217 SettingsFlagsAndId flags_and_id
=
1218 SettingsFlagsAndId::FromWireFormat(frame
->version(), id_and_flags_wire
);
1219 SpdySettingsIds id
= static_cast<SpdySettingsIds
>(flags_and_id
.id());
1220 SpdySettingsFlags flags
=
1221 static_cast<SpdySettingsFlags
>(flags_and_id
.flags());
1222 (*settings
)[id
] = SettingsFlagsAndValue(flags
, value
);
1228 bool SpdyFramer::ParseCredentialData(const char* data
, size_t len
,
1229 SpdyCredential
* credential
) {
1232 SpdyFrameReader
parser(data
, len
);
1233 base::StringPiece temp
;
1234 if (!parser
.ReadUInt16(&credential
->slot
)) {
1238 if (!parser
.ReadStringPiece32(&temp
)) {
1241 credential
->proof
= temp
.as_string();
1243 while (!parser
.IsDoneReading()) {
1244 if (!parser
.ReadStringPiece32(&temp
)) {
1247 credential
->certs
.push_back(temp
.as_string());
1252 SpdySynStreamControlFrame
* SpdyFramer::CreateSynStream(
1253 SpdyStreamId stream_id
,
1254 SpdyStreamId associated_stream_id
,
1255 SpdyPriority priority
,
1256 uint8 credential_slot
,
1257 SpdyControlFlags flags
,
1259 const SpdyHeaderBlock
* headers
) {
1260 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1261 DCHECK_EQ(0u, associated_stream_id
& ~kStreamIdMask
);
1264 size_t frame_size
= SpdySynStreamControlFrame::size() +
1265 GetSerializedLength(spdy_version_
, headers
);
1267 SpdyFrameBuilder
frame(SYN_STREAM
, flags
, spdy_version_
, frame_size
);
1268 frame
.WriteUInt32(stream_id
);
1269 frame
.WriteUInt32(associated_stream_id
);
1270 // Cap as appropriate.
1271 if (priority
> GetLowestPriority()) {
1272 DLOG(DFATAL
) << "Priority out-of-bounds.";
1273 priority
= GetLowestPriority();
1275 // Priority is 2 bits for <spdy3, 3 bits otherwise.
1276 frame
.WriteUInt8(priority
<< ((spdy_version_
< 3) ? 6 : 5));
1277 frame
.WriteUInt8((spdy_version_
< 3) ? 0 : credential_slot
);
1278 WriteHeaderBlock(&frame
, spdy_version_
, headers
);
1279 DCHECK_EQ(frame
.length(), frame_size
);
1281 scoped_ptr
<SpdySynStreamControlFrame
> syn_frame(
1282 reinterpret_cast<SpdySynStreamControlFrame
*>(frame
.take()));
1284 return reinterpret_cast<SpdySynStreamControlFrame
*>(
1285 CompressControlFrame(*syn_frame
.get(), headers
));
1287 return syn_frame
.release();
1290 SpdySynReplyControlFrame
* SpdyFramer::CreateSynReply(
1291 SpdyStreamId stream_id
,
1292 SpdyControlFlags flags
,
1294 const SpdyHeaderBlock
* headers
) {
1295 DCHECK_GT(stream_id
, 0u);
1296 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1299 size_t frame_size
= SpdySynReplyControlFrame::size() +
1300 GetSerializedLength(spdy_version_
, headers
);
1301 // In SPDY 2, there were 2 unused bytes before payload.
1302 if (spdy_version_
< 3) {
1306 SpdyFrameBuilder
frame(SYN_REPLY
, flags
, spdy_version_
, frame_size
);
1307 frame
.WriteUInt32(stream_id
);
1308 if (spdy_version_
< 3) {
1309 frame
.WriteUInt16(0); // Unused
1311 WriteHeaderBlock(&frame
, spdy_version_
, headers
);
1312 DCHECK_EQ(frame
.length(), frame_size
);
1314 scoped_ptr
<SpdySynReplyControlFrame
> reply_frame(
1315 reinterpret_cast<SpdySynReplyControlFrame
*>(frame
.take()));
1317 return reinterpret_cast<SpdySynReplyControlFrame
*>(
1318 CompressControlFrame(*reply_frame
.get(), headers
));
1320 return reply_frame
.release();
1323 SpdyRstStreamControlFrame
* SpdyFramer::CreateRstStream(
1324 SpdyStreamId stream_id
,
1325 SpdyStatusCodes status
) const {
1326 DCHECK_GT(stream_id
, 0u);
1327 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1328 DCHECK_NE(status
, INVALID
);
1329 DCHECK_LT(status
, NUM_STATUS_CODES
);
1331 size_t frame_size
= SpdyRstStreamControlFrame::size();
1332 SpdyFrameBuilder
frame(RST_STREAM
, CONTROL_FLAG_NONE
, spdy_version_
,
1334 frame
.WriteUInt32(stream_id
);
1335 frame
.WriteUInt32(status
);
1336 DCHECK_EQ(frame
.length(), frame_size
);
1337 return reinterpret_cast<SpdyRstStreamControlFrame
*>(frame
.take());
1340 SpdySettingsControlFrame
* SpdyFramer::CreateSettings(
1341 const SettingsMap
& values
) const {
1342 size_t frame_size
= SpdySettingsControlFrame::size() + 8 * values
.size();
1343 SpdyFrameBuilder
frame(SETTINGS
, CONTROL_FLAG_NONE
, spdy_version_
,
1345 frame
.WriteUInt32(values
.size());
1346 for (SettingsMap::const_iterator it
= values
.begin();
1349 SettingsFlagsAndId
flags_and_id(it
->second
.first
, it
->first
);
1350 uint32 id_and_flags_wire
= flags_and_id
.GetWireFormat(spdy_version_
);
1351 frame
.WriteBytes(&id_and_flags_wire
, 4);
1352 frame
.WriteUInt32(it
->second
.second
);
1354 DCHECK_EQ(frame
.length(), frame_size
);
1355 return reinterpret_cast<SpdySettingsControlFrame
*>(frame
.take());
1358 SpdyPingControlFrame
* SpdyFramer::CreatePingFrame(uint32 unique_id
) const {
1359 size_t frame_size
= SpdyPingControlFrame::size();
1360 SpdyFrameBuilder
frame(PING
, CONTROL_FLAG_NONE
, spdy_version_
, frame_size
);
1361 frame
.WriteUInt32(unique_id
);
1362 DCHECK_EQ(frame
.length(), frame_size
);
1363 return reinterpret_cast<SpdyPingControlFrame
*>(frame
.take());
1366 SpdyGoAwayControlFrame
* SpdyFramer::CreateGoAway(
1367 SpdyStreamId last_accepted_stream_id
,
1368 SpdyGoAwayStatus status
) const {
1369 DCHECK_EQ(0u, last_accepted_stream_id
& ~kStreamIdMask
);
1371 // SPDY 2 GOAWAY frames are 4 bytes smaller than in SPDY 3. We account for
1372 // this difference via a separate offset variable, since
1373 // SpdyGoAwayControlFrame::size() returns the SPDY 3 size.
1374 const size_t goaway_offset
= (protocol_version() < 3) ? 4 : 0;
1375 size_t frame_size
= SpdyGoAwayControlFrame::size() - goaway_offset
;
1376 SpdyFrameBuilder
frame(GOAWAY
, CONTROL_FLAG_NONE
, spdy_version_
, frame_size
);
1377 frame
.WriteUInt32(last_accepted_stream_id
);
1378 if (protocol_version() >= 3) {
1379 frame
.WriteUInt32(status
);
1381 DCHECK_EQ(frame
.length(), frame_size
);
1382 return reinterpret_cast<SpdyGoAwayControlFrame
*>(frame
.take());
1385 SpdyHeadersControlFrame
* SpdyFramer::CreateHeaders(
1386 SpdyStreamId stream_id
,
1387 SpdyControlFlags flags
,
1389 const SpdyHeaderBlock
* headers
) {
1390 // Basically the same as CreateSynReply().
1391 DCHECK_GT(stream_id
, 0u);
1392 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1395 size_t frame_size
= SpdyHeadersControlFrame::size() +
1396 GetSerializedLength(spdy_version_
, headers
);
1397 // In SPDY 2, there were 2 unused bytes before payload.
1398 if (spdy_version_
< 3) {
1402 SpdyFrameBuilder
frame(HEADERS
, flags
, spdy_version_
, frame_size
);
1403 frame
.WriteUInt32(stream_id
);
1404 if (spdy_version_
< 3) {
1405 frame
.WriteUInt16(0); // Unused
1407 WriteHeaderBlock(&frame
, spdy_version_
, headers
);
1408 DCHECK_EQ(frame
.length(), frame_size
);
1410 scoped_ptr
<SpdyHeadersControlFrame
> headers_frame(
1411 reinterpret_cast<SpdyHeadersControlFrame
*>(frame
.take()));
1413 return reinterpret_cast<SpdyHeadersControlFrame
*>(
1414 CompressControlFrame(*headers_frame
.get(), headers
));
1416 return headers_frame
.release();
1419 SpdyWindowUpdateControlFrame
* SpdyFramer::CreateWindowUpdate(
1420 SpdyStreamId stream_id
,
1421 uint32 delta_window_size
) const {
1422 DCHECK_GT(stream_id
, 0u);
1423 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1424 DCHECK_GT(delta_window_size
, 0u);
1425 DCHECK_LE(delta_window_size
,
1426 static_cast<uint32
>(kSpdyStreamMaximumWindowSize
));
1428 size_t frame_size
= SpdyWindowUpdateControlFrame::size();
1429 SpdyFrameBuilder
frame(WINDOW_UPDATE
, CONTROL_FLAG_NONE
, spdy_version_
,
1431 frame
.WriteUInt32(stream_id
);
1432 frame
.WriteUInt32(delta_window_size
);
1433 DCHECK_EQ(frame
.length(), frame_size
);
1434 return reinterpret_cast<SpdyWindowUpdateControlFrame
*>(frame
.take());
1437 SpdyCredentialControlFrame
* SpdyFramer::CreateCredentialFrame(
1438 const SpdyCredential
& credential
) const {
1439 // Calculate the size of the frame by adding the size of the
1440 // variable length data to the size of the fixed length data.
1441 size_t frame_size
= SpdyCredentialControlFrame::size() +
1442 credential
.proof
.length();
1443 DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u);
1444 for (std::vector
<std::string
>::const_iterator cert
= credential
.certs
.begin();
1445 cert
!= credential
.certs
.end();
1447 frame_size
+= sizeof(uint32
); // size of the cert_length field
1448 frame_size
+= cert
->length(); // size of the cert_data field
1451 SpdyFrameBuilder
frame(CREDENTIAL
, CONTROL_FLAG_NONE
, spdy_version_
,
1453 frame
.WriteUInt16(credential
.slot
);
1454 frame
.WriteUInt32(credential
.proof
.size());
1455 frame
.WriteBytes(credential
.proof
.c_str(), credential
.proof
.size());
1456 for (std::vector
<std::string
>::const_iterator cert
= credential
.certs
.begin();
1457 cert
!= credential
.certs
.end();
1459 frame
.WriteUInt32(cert
->length());
1460 frame
.WriteBytes(cert
->c_str(), cert
->length());
1462 DCHECK_EQ(frame
.length(), frame_size
);
1463 return reinterpret_cast<SpdyCredentialControlFrame
*>(frame
.take());
1466 SpdyDataFrame
* SpdyFramer::CreateDataFrame(
1467 SpdyStreamId stream_id
,
1469 uint32 len
, SpdyDataFlags flags
) const {
1470 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1471 size_t frame_size
= SpdyDataFrame::size() + len
;
1472 SpdyFrameBuilder
frame(stream_id
, flags
, frame_size
);
1473 frame
.WriteBytes(data
, len
);
1474 DCHECK_EQ(frame
.length(), frame_size
);
1475 return reinterpret_cast<SpdyDataFrame
*>(frame
.take());
1478 // The following compression setting are based on Brian Olson's analysis. See
1479 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
1480 // for more details.
1481 #if defined(USE_SYSTEM_ZLIB)
1482 // System zlib is not expected to have workaround for http://crbug.com/139744,
1483 // so disable compression in that case.
1484 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
1485 static const int kCompressorLevel
= 0;
1486 #else // !defined(USE_SYSTEM_ZLIB)
1487 static const int kCompressorLevel
= 9;
1488 #endif // !defined(USE_SYSTEM_ZLIB)
1489 static const int kCompressorWindowSizeInBits
= 11;
1490 static const int kCompressorMemLevel
= 1;
1492 z_stream
* SpdyFramer::GetHeaderCompressor() {
1493 if (header_compressor_
.get())
1494 return header_compressor_
.get(); // Already initialized.
1496 header_compressor_
.reset(new z_stream
);
1497 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
1499 int success
= deflateInit2(header_compressor_
.get(),
1502 kCompressorWindowSizeInBits
,
1503 kCompressorMemLevel
,
1504 Z_DEFAULT_STRATEGY
);
1505 if (success
== Z_OK
) {
1506 const char* dictionary
= (spdy_version_
< 3) ? kV2Dictionary
1508 const int dictionary_size
= (spdy_version_
< 3) ? kV2DictionarySize
1509 : kV3DictionarySize
;
1510 success
= deflateSetDictionary(header_compressor_
.get(),
1511 reinterpret_cast<const Bytef
*>(dictionary
),
1514 if (success
!= Z_OK
) {
1515 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
1516 header_compressor_
.reset(NULL
);
1519 return header_compressor_
.get();
1522 z_stream
* SpdyFramer::GetHeaderDecompressor() {
1523 if (header_decompressor_
.get())
1524 return header_decompressor_
.get(); // Already initialized.
1526 header_decompressor_
.reset(new z_stream
);
1527 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
1529 int success
= inflateInit(header_decompressor_
.get());
1530 if (success
!= Z_OK
) {
1531 LOG(WARNING
) << "inflateInit failure: " << success
;
1532 header_decompressor_
.reset(NULL
);
1535 return header_decompressor_
.get();
1538 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame
& frame
,
1539 int* payload_length
,
1541 const char** payload
) const {
1543 if (frame
.is_control_frame()) {
1544 const SpdyControlFrame
& control_frame
=
1545 reinterpret_cast<const SpdyControlFrame
&>(frame
);
1546 switch (control_frame
.type()) {
1549 const SpdySynStreamControlFrame
& syn_frame
=
1550 reinterpret_cast<const SpdySynStreamControlFrame
&>(frame
);
1551 frame_size
= SpdySynStreamControlFrame::size();
1552 *payload_length
= syn_frame
.header_block_len();
1553 *header_length
= frame_size
;
1554 *payload
= frame
.data() + *header_length
;
1559 const SpdySynReplyControlFrame
& syn_frame
=
1560 reinterpret_cast<const SpdySynReplyControlFrame
&>(frame
);
1561 frame_size
= SpdySynReplyControlFrame::size();
1562 *payload_length
= syn_frame
.header_block_len();
1563 *header_length
= frame_size
;
1564 *payload
= frame
.data() + *header_length
;
1565 // SPDY 2 had two bytes of unused space preceeding payload.
1566 if (spdy_version_
< 3) {
1567 *header_length
+= 2;
1574 const SpdyHeadersControlFrame
& headers_frame
=
1575 reinterpret_cast<const SpdyHeadersControlFrame
&>(frame
);
1576 frame_size
= SpdyHeadersControlFrame::size();
1577 *payload_length
= headers_frame
.header_block_len();
1578 *header_length
= frame_size
;
1579 *payload
= frame
.data() + *header_length
;
1580 // SPDY 2 had two bytes of unused space preceeding payload.
1581 if (spdy_version_
< 3) {
1582 *header_length
+= 2;
1588 // TODO(mbelshe): set an error?
1589 return false; // We can't compress this frame!
1592 frame_size
= SpdyFrame::kHeaderSize
;
1593 *header_length
= frame_size
;
1594 *payload_length
= frame
.length();
1595 *payload
= frame
.data() + SpdyFrame::kHeaderSize
;
1600 SpdyControlFrame
* SpdyFramer::CompressControlFrame(
1601 const SpdyControlFrame
& frame
,
1602 const SpdyHeaderBlock
* headers
) {
1603 z_stream
* compressor
= GetHeaderCompressor();
1609 const char* payload
;
1611 base::StatsCounter
compressed_frames("spdy.CompressedFrames");
1612 base::StatsCounter
pre_compress_bytes("spdy.PreCompressSize");
1613 base::StatsCounter
post_compress_bytes("spdy.PostCompressSize");
1615 if (!enable_compression_
)
1616 return reinterpret_cast<SpdyControlFrame
*>(DuplicateFrame(frame
));
1618 if (!GetFrameBoundaries(frame
, &payload_length
, &header_length
, &payload
))
1621 // Create an output frame.
1622 int compressed_max_size
= deflateBound(compressor
, payload_length
);
1623 // Since we'll be performing lots of flushes when compressing the data,
1624 // zlib's lower bounds may be insufficient.
1625 compressed_max_size
*= 2;
1627 size_t new_frame_size
= header_length
+ compressed_max_size
;
1628 if ((frame
.type() == SYN_REPLY
|| frame
.type() == HEADERS
) &&
1629 spdy_version_
< 3) {
1630 new_frame_size
+= 2;
1632 DCHECK_GE(new_frame_size
, frame
.length() + SpdyFrame::kHeaderSize
);
1633 scoped_ptr
<SpdyControlFrame
> new_frame(new SpdyControlFrame(new_frame_size
));
1634 memcpy(new_frame
->data(), frame
.data(),
1635 frame
.length() + SpdyFrame::kHeaderSize
);
1637 // TODO(phajdan.jr): Clean up after we no longer need
1638 // to workaround http://crbug.com/139744.
1639 #if defined(USE_SYSTEM_ZLIB)
1640 compressor
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(payload
));
1641 compressor
->avail_in
= payload_length
;
1642 #endif // defined(USE_SYSTEM_ZLIB)
1643 compressor
->next_out
= reinterpret_cast<Bytef
*>(new_frame
->data()) +
1645 compressor
->avail_out
= compressed_max_size
;
1646 // TODO(phajdan.jr): Clean up after we no longer need
1647 // to workaround http://crbug.com/139744.
1648 #if defined(USE_SYSTEM_ZLIB)
1649 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
1650 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
1651 // This shouldn't happen, right?
1652 LOG(WARNING
) << "deflate failure: " << rv
;
1655 #else // !defined(USE_SYSTEM_ZLIB)
1656 WriteHeaderBlockToZ(headers
, compressor
);
1657 #endif // !defined(USE_SYSTEM_ZLIB)
1658 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
1660 // We trust zlib. Also, we can't do anything about it.
1661 // See http://www.zlib.net/zlib_faq.html#faq36
1662 (void)VALGRIND_MAKE_MEM_DEFINED(new_frame
->data() + header_length
,
1665 new_frame
->set_length(
1666 header_length
+ compressed_size
- SpdyFrame::kHeaderSize
);
1668 pre_compress_bytes
.Add(payload_length
);
1669 post_compress_bytes
.Add(new_frame
->length());
1671 compressed_frames
.Increment();
1674 visitor_
->OnControlFrameCompressed(frame
, *new_frame
);
1676 return new_frame
.release();
1679 // Incrementally decompress the control frame's header block, feeding the
1680 // result to the visitor in chunks. Continue this until the visitor
1681 // indicates that it cannot process any more data, or (more commonly) we
1682 // run out of data to deliver.
1683 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
1684 const SpdyControlFrame
* control_frame
,
1687 // Get a decompressor or set error.
1688 z_stream
* decomp
= GetHeaderDecompressor();
1689 if (decomp
== NULL
) {
1690 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
1691 set_error(SPDY_DECOMPRESS_FAILURE
);
1695 bool processed_successfully
= true;
1696 char buffer
[kHeaderDataChunkMaxSize
];
1698 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
1699 decomp
->avail_in
= len
;
1700 const SpdyStreamId stream_id
= GetControlFrameStreamId(control_frame
);
1701 DCHECK_LT(0u, stream_id
);
1702 while (decomp
->avail_in
> 0 && processed_successfully
) {
1703 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
1704 decomp
->avail_out
= arraysize(buffer
);
1706 int rv
= inflate(decomp
, Z_SYNC_FLUSH
);
1707 if (rv
== Z_NEED_DICT
) {
1708 const char* dictionary
= (spdy_version_
< 3) ? kV2Dictionary
1710 const int dictionary_size
= (spdy_version_
< 3) ? kV2DictionarySize
1711 : kV3DictionarySize
;
1712 const DictionaryIds
& ids
= g_dictionary_ids
.Get();
1713 const uLong dictionary_id
= (spdy_version_
< 3) ? ids
.v2_dictionary_id
1714 : ids
.v3_dictionary_id
;
1715 // Need to try again with the right dictionary.
1716 if (decomp
->adler
== dictionary_id
) {
1717 rv
= inflateSetDictionary(decomp
,
1718 reinterpret_cast<const Bytef
*>(dictionary
),
1721 rv
= inflate(decomp
, Z_SYNC_FLUSH
);
1725 // Inflate will generate a Z_BUF_ERROR if it runs out of input
1726 // without producing any output. The input is consumed and
1727 // buffered internally by zlib so we can detect this condition by
1728 // checking if avail_in is 0 after the call to inflate.
1729 bool input_exhausted
= ((rv
== Z_BUF_ERROR
) && (decomp
->avail_in
== 0));
1730 if ((rv
== Z_OK
) || input_exhausted
) {
1731 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
1732 if (decompressed_len
> 0) {
1733 processed_successfully
= visitor_
->OnControlFrameHeaderData(
1734 stream_id
, buffer
, decompressed_len
);
1736 if (!processed_successfully
) {
1737 // Assume that the problem was the header block was too large for the
1739 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1742 DLOG(WARNING
) << "inflate failure: " << rv
<< " " << len
;
1743 set_error(SPDY_DECOMPRESS_FAILURE
);
1744 processed_successfully
= false;
1747 return processed_successfully
;
1750 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
1751 const SpdyControlFrame
* control_frame
, const char* data
, size_t len
) {
1752 bool read_successfully
= true;
1753 const SpdyStreamId stream_id
= GetControlFrameStreamId(control_frame
);
1754 while (read_successfully
&& len
> 0) {
1755 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
1756 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
1758 data
+= bytes_to_deliver
;
1759 len
-= bytes_to_deliver
;
1760 if (!read_successfully
) {
1761 // Assume that the problem was the header block was too large for the
1763 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1766 return read_successfully
;
1769 SpdyFrame
* SpdyFramer::DuplicateFrame(const SpdyFrame
& frame
) {
1770 int size
= SpdyFrame::kHeaderSize
+ frame
.length();
1771 SpdyFrame
* new_frame
= new SpdyFrame(size
);
1772 memcpy(new_frame
->data(), frame
.data(), size
);
1776 bool SpdyFramer::IsCompressible(const SpdyFrame
& frame
) const {
1777 // The important frames to compress are those which contain large
1778 // amounts of compressible data - namely the headers in the SYN_STREAM
1780 if (frame
.is_control_frame()) {
1781 const SpdyControlFrame
& control_frame
=
1782 reinterpret_cast<const SpdyControlFrame
&>(frame
);
1783 return control_frame
.type() == SYN_STREAM
||
1784 control_frame
.type() == SYN_REPLY
||
1785 control_frame
.type() == HEADERS
;
1788 // We don't compress Data frames.
1792 size_t SpdyFramer::GetMinimumControlFrameSize(int version
,
1793 SpdyControlType type
) {
1796 return SpdySynStreamControlFrame::size();
1798 return SpdySynReplyControlFrame::size();
1800 return SpdyRstStreamControlFrame::size();
1802 return SpdySettingsControlFrame::size();
1804 // Even though NOOP is no longer supported, we still correctly report its
1805 // size so that it can be handled correctly as incoming data if
1806 // implementations so desire.
1807 return SpdyFrame::kHeaderSize
;
1809 return SpdyPingControlFrame::size();
1812 // SPDY 2 GOAWAY is smaller by 32 bits. Since
1813 // SpdyGoAwayControlFrame::size() returns the size for SPDY 3, we adjust
1814 // before returning here.
1815 return SpdyGoAwayControlFrame::size() - 4;
1817 return SpdyGoAwayControlFrame::size();
1820 return SpdyHeadersControlFrame::size();
1822 return SpdyWindowUpdateControlFrame::size();
1824 return SpdyCredentialControlFrame::size();
1825 case NUM_CONTROL_FRAME_TYPES
:
1828 LOG(ERROR
) << "Unknown control frame type " << type
;
1829 return std::numeric_limits
<size_t>::max();
1833 SpdyStreamId
SpdyFramer::GetControlFrameStreamId(
1834 const SpdyControlFrame
* control_frame
) {
1835 SpdyStreamId stream_id
= kInvalidStream
;
1836 if (control_frame
!= NULL
) {
1837 switch (control_frame
->type()) {
1839 stream_id
= reinterpret_cast<const SpdySynStreamControlFrame
*>(
1840 control_frame
)->stream_id();
1843 stream_id
= reinterpret_cast<const SpdySynReplyControlFrame
*>(
1844 control_frame
)->stream_id();
1847 stream_id
= reinterpret_cast<const SpdyHeadersControlFrame
*>(
1848 control_frame
)->stream_id();
1851 stream_id
= reinterpret_cast<const SpdyRstStreamControlFrame
*>(
1852 control_frame
)->stream_id();
1855 stream_id
= reinterpret_cast<const SpdyWindowUpdateControlFrame
*>(
1856 control_frame
)->stream_id();
1858 // All of the following types are not part of a particular stream.
1859 // They all fall through to the invalid control frame type case.
1860 // (The default case isn't used so that the compile will break if a new
1861 // control frame type is added but not included here.)
1867 case NUM_CONTROL_FRAME_TYPES
: // makes compiler happy
1874 void SpdyFramer::set_enable_compression(bool value
) {
1875 enable_compression_
= value
;