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