Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
bloba12c3ceada035a7328bad4343eece9ec68c3fd32
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 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
171 size_t len) {
172 return true;
175 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
176 const char* rst_stream_data,
177 size_t len) {
178 return true;
181 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
182 : current_frame_buffer_(kControlFrameBufferSize),
183 expect_continuation_(0),
184 visitor_(NULL),
185 debug_visitor_(NULL),
186 display_protocol_("SPDY"),
187 protocol_version_(version),
188 enable_compression_(true),
189 syn_frame_processed_(false),
190 probable_http_response_(false),
191 end_stream_when_done_(false),
192 header_table_size_bound_(4096) {
193 DCHECK_GE(protocol_version_, SPDY_MIN_VERSION);
194 DCHECK_LE(protocol_version_, SPDY_MAX_VERSION);
195 DCHECK_LE(kMaxControlFrameSize,
196 SpdyConstants::GetFrameMaximumSize(protocol_version_) +
197 SpdyConstants::GetControlFrameHeaderSize(protocol_version_));
198 Reset();
201 SpdyFramer::~SpdyFramer() {
202 if (header_compressor_.get()) {
203 deflateEnd(header_compressor_.get());
205 if (header_decompressor_.get()) {
206 inflateEnd(header_decompressor_.get());
210 void SpdyFramer::Reset() {
211 state_ = SPDY_READY_FOR_FRAME;
212 previous_state_ = SPDY_READY_FOR_FRAME;
213 error_code_ = SPDY_NO_ERROR;
214 remaining_data_length_ = 0;
215 remaining_control_header_ = 0;
216 current_frame_buffer_.Rewind();
217 current_frame_type_ = DATA;
218 current_frame_flags_ = 0;
219 current_frame_length_ = 0;
220 current_frame_stream_id_ = kInvalidStream;
221 settings_scratch_.Reset();
222 altsvc_scratch_.reset();
223 remaining_padding_payload_length_ = 0;
226 size_t SpdyFramer::GetDataFrameMinimumSize() const {
227 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
230 // Size, in bytes, of the control frame header.
231 size_t SpdyFramer::GetControlFrameHeaderSize() const {
232 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
235 size_t SpdyFramer::GetSynStreamMinimumSize() const {
236 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
237 // header block.
238 if (protocol_version() <= SPDY3) {
239 // Calculated as:
240 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
241 // + 1 (unused, was credential slot)
242 return GetControlFrameHeaderSize() + 10;
243 } else {
244 return GetControlFrameHeaderSize() +
245 kPriorityDependencyPayloadSize +
246 kPriorityWeightPayloadSize;
250 size_t SpdyFramer::GetSynReplyMinimumSize() const {
251 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
252 // header block.
253 size_t size = GetControlFrameHeaderSize();
254 if (protocol_version() <= SPDY3) {
255 // Calculated as:
256 // control frame header + 4 (stream IDs)
257 size += 4;
260 // In SPDY 2, there were 2 unused bytes before payload.
261 if (protocol_version() < SPDY3) {
262 size += 2;
265 return size;
268 size_t SpdyFramer::GetRstStreamMinimumSize() const {
269 // Size, in bytes, of a RST_STREAM frame.
270 if (protocol_version() <= SPDY3) {
271 // Calculated as:
272 // control frame header + 4 (stream id) + 4 (status code)
273 return GetControlFrameHeaderSize() + 8;
274 } else {
275 // Calculated as:
276 // frame prefix + 4 (status code)
277 return GetControlFrameHeaderSize() + 4;
281 size_t SpdyFramer::GetSettingsMinimumSize() const {
282 // Size, in bytes, of a SETTINGS frame not including the IDs and values
283 // from the variable-length value block. Calculated as:
284 // control frame header + 4 (number of ID/value pairs)
285 if (protocol_version() <= SPDY3) {
286 return GetControlFrameHeaderSize() + 4;
287 } else {
288 return GetControlFrameHeaderSize();
292 size_t SpdyFramer::GetPingSize() const {
293 // Size, in bytes, of this PING frame.
294 if (protocol_version() <= SPDY3) {
295 // Calculated as:
296 // control frame header + 4 (id)
297 return GetControlFrameHeaderSize() + 4;
298 } else {
299 // Calculated as:
300 // control frame header + 8 (id)
301 return GetControlFrameHeaderSize() + 8;
305 size_t SpdyFramer::GetGoAwayMinimumSize() const {
306 // Size, in bytes, of this GOAWAY frame. Calculated as:
307 // 1. Control frame header size
308 size_t size = GetControlFrameHeaderSize();
310 // 2. Last good stream id (4 bytes)
311 size += 4;
313 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
314 if (protocol_version() >= SPDY3) {
315 size += 4;
318 return size;
321 size_t SpdyFramer::GetHeadersMinimumSize() const {
322 // Size, in bytes, of a HEADERS frame not including the variable-length
323 // header block.
324 size_t size = GetControlFrameHeaderSize();
325 if (protocol_version() <= SPDY3) {
326 // Calculated as:
327 // control frame header + 4 (stream IDs)
328 size += 4;
331 // In SPDY 2, there were 2 unused bytes before payload.
332 if (protocol_version() <= SPDY2) {
333 size += 2;
336 return size;
339 size_t SpdyFramer::GetWindowUpdateSize() const {
340 // Size, in bytes, of a WINDOW_UPDATE frame.
341 if (protocol_version() <= SPDY3) {
342 // Calculated as:
343 // control frame header + 4 (stream id) + 4 (delta)
344 return GetControlFrameHeaderSize() + 8;
345 } else {
346 // Calculated as:
347 // frame prefix + 4 (delta)
348 return GetControlFrameHeaderSize() + 4;
352 size_t SpdyFramer::GetBlockedSize() const {
353 DCHECK_LT(SPDY3, protocol_version());
354 // Size, in bytes, of a BLOCKED frame.
355 // The BLOCKED frame has no payload beyond the control frame header.
356 return GetControlFrameHeaderSize();
359 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
360 DCHECK_LT(SPDY3, protocol_version());
361 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
362 // Calculated as frame prefix + 4 (promised stream id).
363 return GetControlFrameHeaderSize() + 4;
366 size_t SpdyFramer::GetContinuationMinimumSize() const {
367 // Size, in bytes, of a CONTINUATION frame not including the variable-length
368 // headers fragments.
369 return GetControlFrameHeaderSize();
372 size_t SpdyFramer::GetAltSvcMinimumSize() const {
373 // Size, in bytes, of an ALTSVC frame not including the Field-Value and
374 // (optional) Origin fields, both of which can vary in length. Note that this
375 // gives a lower bound on the frame size rather than a true minimum; the
376 // actual frame should always be larger than this.
377 // Calculated as frame prefix + 2 (origin_len).
378 return GetControlFrameHeaderSize() + 2;
381 size_t SpdyFramer::GetPrioritySize() const {
382 // Size, in bytes, of a PRIORITY frame.
383 return GetControlFrameHeaderSize() +
384 kPriorityDependencyPayloadSize +
385 kPriorityWeightPayloadSize;
388 size_t SpdyFramer::GetFrameMinimumSize() const {
389 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
392 size_t SpdyFramer::GetFrameMaximumSize() const {
393 return SpdyConstants::GetFrameMaximumSize(protocol_version());
396 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
397 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
400 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
401 return SpdyConstants::GetPrefixLength(type, protocol_version());
404 const char* SpdyFramer::StateToString(int state) {
405 switch (state) {
406 case SPDY_ERROR:
407 return "ERROR";
408 case SPDY_FRAME_COMPLETE:
409 return "FRAME_COMPLETE";
410 case SPDY_READY_FOR_FRAME:
411 return "READY_FOR_FRAME";
412 case SPDY_READING_COMMON_HEADER:
413 return "READING_COMMON_HEADER";
414 case SPDY_CONTROL_FRAME_PAYLOAD:
415 return "CONTROL_FRAME_PAYLOAD";
416 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
417 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
418 case SPDY_CONSUME_PADDING:
419 return "SPDY_CONSUME_PADDING";
420 case SPDY_IGNORE_REMAINING_PAYLOAD:
421 return "IGNORE_REMAINING_PAYLOAD";
422 case SPDY_FORWARD_STREAM_FRAME:
423 return "FORWARD_STREAM_FRAME";
424 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
425 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
426 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
427 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
428 case SPDY_GOAWAY_FRAME_PAYLOAD:
429 return "SPDY_GOAWAY_FRAME_PAYLOAD";
430 case SPDY_RST_STREAM_FRAME_PAYLOAD:
431 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
432 case SPDY_SETTINGS_FRAME_PAYLOAD:
433 return "SPDY_SETTINGS_FRAME_PAYLOAD";
434 case SPDY_ALTSVC_FRAME_PAYLOAD:
435 return "SPDY_ALTSVC_FRAME_PAYLOAD";
437 return "UNKNOWN_STATE";
440 void SpdyFramer::set_error(SpdyError error) {
441 DCHECK(visitor_);
442 error_code_ = error;
443 // These values will usually get reset once we come to the end
444 // of a header block, but if we run into an error that
445 // might not happen, so reset them here.
446 expect_continuation_ = 0;
447 end_stream_when_done_ = false;
449 CHANGE_STATE(SPDY_ERROR);
450 visitor_->OnError(this);
453 const char* SpdyFramer::ErrorCodeToString(int error_code) {
454 switch (error_code) {
455 case SPDY_NO_ERROR:
456 return "NO_ERROR";
457 case SPDY_INVALID_CONTROL_FRAME:
458 return "INVALID_CONTROL_FRAME";
459 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
460 return "CONTROL_PAYLOAD_TOO_LARGE";
461 case SPDY_ZLIB_INIT_FAILURE:
462 return "ZLIB_INIT_FAILURE";
463 case SPDY_UNSUPPORTED_VERSION:
464 return "UNSUPPORTED_VERSION";
465 case SPDY_DECOMPRESS_FAILURE:
466 return "DECOMPRESS_FAILURE";
467 case SPDY_COMPRESS_FAILURE:
468 return "COMPRESS_FAILURE";
469 case SPDY_INVALID_DATA_FRAME_FLAGS:
470 return "SPDY_INVALID_DATA_FRAME_FLAGS";
471 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
472 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
473 case SPDY_UNEXPECTED_FRAME:
474 return "UNEXPECTED_FRAME";
476 return "UNKNOWN_ERROR";
479 const char* SpdyFramer::StatusCodeToString(int status_code) {
480 switch (status_code) {
481 case RST_STREAM_INVALID:
482 return "INVALID";
483 case RST_STREAM_PROTOCOL_ERROR:
484 return "PROTOCOL_ERROR";
485 case RST_STREAM_INVALID_STREAM:
486 return "INVALID_STREAM";
487 case RST_STREAM_REFUSED_STREAM:
488 return "REFUSED_STREAM";
489 case RST_STREAM_UNSUPPORTED_VERSION:
490 return "UNSUPPORTED_VERSION";
491 case RST_STREAM_CANCEL:
492 return "CANCEL";
493 case RST_STREAM_INTERNAL_ERROR:
494 return "INTERNAL_ERROR";
495 case RST_STREAM_FLOW_CONTROL_ERROR:
496 return "FLOW_CONTROL_ERROR";
497 case RST_STREAM_STREAM_IN_USE:
498 return "STREAM_IN_USE";
499 case RST_STREAM_STREAM_ALREADY_CLOSED:
500 return "STREAM_ALREADY_CLOSED";
501 case RST_STREAM_INVALID_CREDENTIALS:
502 return "INVALID_CREDENTIALS";
503 case RST_STREAM_FRAME_TOO_LARGE:
504 return "FRAME_TOO_LARGE";
505 case RST_STREAM_CONNECT_ERROR:
506 return "CONNECT_ERROR";
507 case RST_STREAM_ENHANCE_YOUR_CALM:
508 return "ENHANCE_YOUR_CALM";
509 case RST_STREAM_INADEQUATE_SECURITY:
510 return "INADEQUATE_SECURITY";
511 case RST_STREAM_HTTP_1_1_REQUIRED:
512 return "HTTP_1_1_REQUIRED";
514 return "UNKNOWN_STATUS";
517 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
518 switch (type) {
519 case DATA:
520 return "DATA";
521 case SYN_STREAM:
522 return "SYN_STREAM";
523 case SYN_REPLY:
524 return "SYN_REPLY";
525 case RST_STREAM:
526 return "RST_STREAM";
527 case SETTINGS:
528 return "SETTINGS";
529 case PING:
530 return "PING";
531 case GOAWAY:
532 return "GOAWAY";
533 case HEADERS:
534 return "HEADERS";
535 case WINDOW_UPDATE:
536 return "WINDOW_UPDATE";
537 case CREDENTIAL:
538 return "CREDENTIAL";
539 case PUSH_PROMISE:
540 return "PUSH_PROMISE";
541 case CONTINUATION:
542 return "CONTINUATION";
543 case PRIORITY:
544 return "PRIORITY";
545 case ALTSVC:
546 return "ALTSVC";
547 case BLOCKED:
548 return "BLOCKED";
550 return "UNKNOWN_CONTROL_TYPE";
553 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
554 DCHECK(visitor_);
555 DCHECK(data);
557 const size_t original_len = len;
558 do {
559 previous_state_ = state_;
560 switch (state_) {
561 case SPDY_ERROR:
562 goto bottom;
564 case SPDY_FRAME_COMPLETE:
565 // Should not enter in this state.
566 DCHECK_LT(len, original_len);
567 Reset();
568 if (len > 0 && !process_single_input_frame_) {
569 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
571 break;
573 case SPDY_READY_FOR_FRAME:
574 if (len > 0) {
575 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
577 break;
579 case SPDY_READING_COMMON_HEADER: {
580 size_t bytes_read = ProcessCommonHeader(data, len);
581 len -= bytes_read;
582 data += bytes_read;
583 break;
586 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
587 // Control frames that contain header blocks
588 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
589 // take a different path through the state machine - they
590 // will go:
591 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
592 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
594 // SETTINGS frames take a slightly modified route:
595 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
596 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
598 // All other control frames will use the alternate route directly to
599 // SPDY_CONTROL_FRAME_PAYLOAD
600 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
601 len -= bytes_read;
602 data += bytes_read;
603 break;
606 case SPDY_SETTINGS_FRAME_PAYLOAD: {
607 int bytes_read = ProcessSettingsFramePayload(data, len);
608 len -= bytes_read;
609 data += bytes_read;
610 break;
613 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
614 int bytes_read = ProcessControlFrameHeaderBlock(
615 data, len, protocol_version() > SPDY3);
616 len -= bytes_read;
617 data += bytes_read;
618 break;
621 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
622 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
623 len -= bytes_read;
624 data += bytes_read;
625 break;
628 case SPDY_GOAWAY_FRAME_PAYLOAD: {
629 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
630 len -= bytes_read;
631 data += bytes_read;
632 break;
635 case SPDY_ALTSVC_FRAME_PAYLOAD: {
636 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
637 len -= bytes_read;
638 data += bytes_read;
639 break;
642 case SPDY_CONTROL_FRAME_PAYLOAD: {
643 size_t bytes_read = ProcessControlFramePayload(data, len);
644 len -= bytes_read;
645 data += bytes_read;
646 break;
649 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: {
650 size_t bytes_read = ProcessDataFramePaddingLength(data, len);
651 len -= bytes_read;
652 data += bytes_read;
653 break;
656 case SPDY_CONSUME_PADDING: {
657 size_t bytes_read = ProcessFramePadding(data, len);
658 len -= bytes_read;
659 data += bytes_read;
660 break;
663 case SPDY_IGNORE_REMAINING_PAYLOAD: {
664 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
665 len -= bytes_read;
666 data += bytes_read;
667 break;
670 case SPDY_FORWARD_STREAM_FRAME: {
671 size_t bytes_read = ProcessDataFramePayload(data, len);
672 len -= bytes_read;
673 data += bytes_read;
674 break;
677 default:
678 LOG(DFATAL) << "Invalid value for " << display_protocol_
679 << " framer state: " << state_;
680 // This ensures that we don't infinite-loop if state_ gets an
681 // invalid value somehow, such as due to a SpdyFramer getting deleted
682 // from a callback it calls.
683 goto bottom;
685 } while (state_ != previous_state_);
686 bottom:
687 DCHECK(len == 0 || state_ == SPDY_ERROR || process_single_input_frame_);
688 if (current_frame_buffer_.len() == 0 && remaining_data_length_ == 0 &&
689 remaining_control_header_ == 0) {
690 DCHECK(state_ == SPDY_READY_FOR_FRAME || state_ == SPDY_ERROR)
691 << "State: " << StateToString(state_);
694 return original_len - len;
697 SpdyFramer::CharBuffer::CharBuffer(size_t capacity)
698 : buffer_(new char[capacity]), capacity_(capacity), len_(0) {}
699 SpdyFramer::CharBuffer::~CharBuffer() {}
701 void SpdyFramer::CharBuffer::CopyFrom(const char* data, size_t size) {
702 DCHECK_GE(capacity_, len_ + size);
703 memcpy(buffer_.get() + len_, data, size);
704 len_ += size;
707 void SpdyFramer::CharBuffer::Rewind() {
708 len_ = 0;
711 SpdyFramer::SpdySettingsScratch::SpdySettingsScratch()
712 : buffer(8), last_setting_id(-1) {}
714 void SpdyFramer::SpdySettingsScratch::Reset() {
715 buffer.Rewind();
716 last_setting_id = -1;
719 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
720 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
721 // state.
722 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
724 size_t original_len = len;
726 // Update current frame buffer as needed.
727 if (current_frame_buffer_.len() < GetControlFrameHeaderSize()) {
728 size_t bytes_desired =
729 GetControlFrameHeaderSize() - current_frame_buffer_.len();
730 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
733 if (current_frame_buffer_.len() < GetControlFrameHeaderSize()) {
734 // Not enough information to do anything meaningful.
735 return original_len - len;
738 SpdyFrameReader reader(current_frame_buffer_.data(),
739 current_frame_buffer_.len());
740 bool is_control_frame = false;
742 int control_frame_type_field =
743 SpdyConstants::DataFrameType(protocol_version());
744 // ProcessControlFrameHeader() will set current_frame_type_ to the
745 // correct value if this is a valid control frame.
746 current_frame_type_ = DATA;
747 if (protocol_version() <= SPDY3) {
748 uint16 version = 0;
749 bool successful_read = reader.ReadUInt16(&version);
750 DCHECK(successful_read);
751 is_control_frame = (version & kControlFlagMask) != 0;
752 version &= ~kControlFlagMask; // Only valid for control frames.
753 if (is_control_frame) {
754 // We check version before we check validity: version can never be
755 // 'invalid', it can only be unsupported.
756 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
757 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
758 SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
759 // Version does not match the version the framer was initialized with.
760 DVLOG(1) << "Unsupported SPDY version "
761 << version
762 << " (expected " << protocol_version() << ")";
763 set_error(SPDY_UNSUPPORTED_VERSION);
764 return 0;
766 // We check control_frame_type_field's validity in
767 // ProcessControlFrameHeader().
768 uint16 control_frame_type_field_uint16;
769 successful_read = reader.ReadUInt16(&control_frame_type_field_uint16);
770 control_frame_type_field = control_frame_type_field_uint16;
771 } else {
772 reader.Rewind();
773 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
775 DCHECK(successful_read);
777 successful_read = reader.ReadUInt8(&current_frame_flags_);
778 DCHECK(successful_read);
780 uint32 length_field = 0;
781 successful_read = reader.ReadUInt24(&length_field);
782 DCHECK(successful_read);
783 remaining_data_length_ = length_field;
784 current_frame_length_ = remaining_data_length_ + reader.GetBytesConsumed();
785 } else {
786 uint32 length_field = 0;
787 bool successful_read = reader.ReadUInt24(&length_field);
788 DCHECK(successful_read);
790 uint8 control_frame_type_field_uint8;
791 successful_read = reader.ReadUInt8(&control_frame_type_field_uint8);
792 DCHECK(successful_read);
793 // We check control_frame_type_field's validity in
794 // ProcessControlFrameHeader().
795 control_frame_type_field = control_frame_type_field_uint8;
796 is_control_frame = control_frame_type_field !=
797 SpdyConstants::SerializeFrameType(protocol_version(), DATA);
799 if (is_control_frame) {
800 current_frame_length_ = length_field + GetControlFrameHeaderSize();
801 } else {
802 current_frame_length_ = length_field + GetDataFrameMinimumSize();
805 successful_read = reader.ReadUInt8(&current_frame_flags_);
806 DCHECK(successful_read);
808 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
809 DCHECK(successful_read);
811 remaining_data_length_ = current_frame_length_ - reader.GetBytesConsumed();
813 // Before we accept a DATA frame, we need to make sure we're not in the
814 // middle of processing a header block.
815 const bool is_continuation_frame = (control_frame_type_field ==
816 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
817 if ((expect_continuation_ != 0) != is_continuation_frame) {
818 if (expect_continuation_ != 0) {
819 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
820 << "frame, but instead received frame type "
821 << control_frame_type_field;
822 } else {
823 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
825 set_error(SPDY_UNEXPECTED_FRAME);
826 return original_len - len;
829 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
830 : GetDataFrameMinimumSize(),
831 reader.GetBytesConsumed());
832 DCHECK_EQ(current_frame_length_,
833 remaining_data_length_ + reader.GetBytesConsumed());
835 // This is just a sanity check for help debugging early frame errors.
836 if (remaining_data_length_ > 1000000u) {
837 // The strncmp for 5 is safe because we only hit this point if we
838 // have kMinCommonHeader (8) bytes
839 if (!syn_frame_processed_ &&
840 strncmp(current_frame_buffer_.data(), "HTTP/", 5) == 0) {
841 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
842 << " request";
843 probable_http_response_ = true;
844 } else {
845 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
846 << " session is likely corrupt.";
850 // if we're here, then we have the common header all received.
851 if (!is_control_frame) {
852 if (protocol_version() > SPDY3) {
853 // Catch bogus tests sending oversized DATA frames.
854 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
855 << "DATA frame too large for SPDY >= 4.";
858 uint8 valid_data_flags = 0;
859 if (protocol_version() > SPDY3) {
860 valid_data_flags =
861 DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
862 } else {
863 valid_data_flags = DATA_FLAG_FIN;
866 if (current_frame_flags_ & ~valid_data_flags) {
867 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
868 } else {
869 visitor_->OnDataFrameHeader(current_frame_stream_id_,
870 remaining_data_length_,
871 current_frame_flags_ & DATA_FLAG_FIN);
872 if (remaining_data_length_ > 0) {
873 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH);
874 } else {
875 // Empty data frame.
876 if (current_frame_flags_ & DATA_FLAG_FIN) {
877 visitor_->OnStreamFrameData(
878 current_frame_stream_id_, NULL, 0, true);
880 CHANGE_STATE(SPDY_FRAME_COMPLETE);
883 } else {
884 ProcessControlFrameHeader(control_frame_type_field);
887 return original_len - len;
890 void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
891 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
892 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_.len());
894 // TODO(mlavan): Either remove credential frames from the code entirely,
895 // or add them to parsing + serialization methods for SPDY3.
896 // Early detection of deprecated frames that we ignore.
897 if (protocol_version() <= SPDY3) {
898 if (control_frame_type_field == CREDENTIAL) {
899 current_frame_type_ = CREDENTIAL;
900 DCHECK_EQ(SPDY3, protocol_version());
901 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
902 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
903 return;
907 if (!SpdyConstants::IsValidFrameType(protocol_version(),
908 control_frame_type_field)) {
909 if (protocol_version() <= SPDY3) {
910 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
911 << " (protocol version: " << protocol_version() << ")";
912 set_error(SPDY_INVALID_CONTROL_FRAME);
913 return;
914 } else {
915 // In HTTP2 we ignore unknown frame types for extensibility, as long as
916 // the rest of the control frame header is valid.
917 // We rely on the visitor to check validity of current_frame_stream_id_.
918 bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_,
919 control_frame_type_field);
920 if (valid_stream) {
921 DVLOG(1) << "Ignoring unknown frame type.";
922 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
923 } else {
924 // Report an invalid frame error and close the stream if the
925 // stream_id is not valid.
926 DLOG(WARNING) << "Unknown control frame type "
927 << control_frame_type_field
928 << " received on invalid stream "
929 << current_frame_stream_id_;
930 set_error(SPDY_INVALID_CONTROL_FRAME);
932 return;
936 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
937 control_frame_type_field);
939 // Do some sanity checking on the control frame sizes and flags.
940 switch (current_frame_type_) {
941 case SYN_STREAM:
942 if (current_frame_length_ < GetSynStreamMinimumSize()) {
943 set_error(SPDY_INVALID_CONTROL_FRAME);
944 } else if (current_frame_flags_ &
945 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
946 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
948 break;
949 case SYN_REPLY:
950 if (current_frame_length_ < GetSynReplyMinimumSize()) {
951 set_error(SPDY_INVALID_CONTROL_FRAME);
952 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
953 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
955 break;
956 case RST_STREAM:
957 // For SPDY versions < 4, the header has a fixed length.
958 // For SPDY version 4 and up, the RST_STREAM frame may include optional
959 // opaque data, so we only have a lower limit on the frame size.
960 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
961 protocol_version() <= SPDY3) ||
962 (current_frame_length_ < GetRstStreamMinimumSize() &&
963 protocol_version() > SPDY3)) {
964 set_error(SPDY_INVALID_CONTROL_FRAME);
965 } else if (current_frame_flags_ != 0) {
966 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
968 break;
969 case SETTINGS:
971 // Make sure that we have an integral number of 8-byte key/value pairs,
972 // plus a 4-byte length field in SPDY3 and below.
973 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
974 // Size of each key/value pair in bytes.
975 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
976 if (current_frame_length_ < GetSettingsMinimumSize() ||
977 (current_frame_length_ - GetControlFrameHeaderSize())
978 % setting_size != values_prefix_size) {
979 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
980 << current_frame_length_;
981 set_error(SPDY_INVALID_CONTROL_FRAME);
982 } else if (protocol_version() <= SPDY3 &&
983 current_frame_flags_ &
984 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
985 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
986 } else if (protocol_version() > SPDY3 &&
987 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
988 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
989 } else if (protocol_version() > SPDY3 &&
990 current_frame_flags_ & SETTINGS_FLAG_ACK &&
991 current_frame_length_ > GetSettingsMinimumSize()) {
992 set_error(SPDY_INVALID_CONTROL_FRAME);
994 break;
996 case PING:
997 if (current_frame_length_ != GetPingSize()) {
998 set_error(SPDY_INVALID_CONTROL_FRAME);
999 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
1000 (current_frame_flags_ & ~PING_FLAG_ACK)) {
1001 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1003 break;
1004 case GOAWAY:
1006 // For SPDY version < 4, there are only mandatory fields and the header
1007 // has a fixed length. For SPDY version >= 4, optional opaque data may
1008 // be appended to the GOAWAY frame, thus there is only a minimal length
1009 // restriction.
1010 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
1011 protocol_version() <= SPDY3) ||
1012 (current_frame_length_ < GetGoAwayMinimumSize() &&
1013 protocol_version() > SPDY3)) {
1014 set_error(SPDY_INVALID_CONTROL_FRAME);
1015 } else if (current_frame_flags_ != 0) {
1016 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1018 break;
1020 case HEADERS:
1022 size_t min_size = GetHeadersMinimumSize();
1023 if (protocol_version() > SPDY3 &&
1024 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
1025 min_size += 4;
1027 if (current_frame_length_ < min_size) {
1028 // TODO(mlavan): check here for HEADERS with no payload?
1029 // (not allowed in HTTP2)
1030 set_error(SPDY_INVALID_CONTROL_FRAME);
1031 } else if (protocol_version() <= SPDY3 &&
1032 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
1033 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1034 } else if (protocol_version() > SPDY3 &&
1035 current_frame_flags_ &
1036 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
1037 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
1038 HEADERS_FLAG_PADDED)) {
1039 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1042 break;
1043 case WINDOW_UPDATE:
1044 if (current_frame_length_ != GetWindowUpdateSize()) {
1045 set_error(SPDY_INVALID_CONTROL_FRAME);
1046 } else if (current_frame_flags_ != 0) {
1047 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1049 break;
1050 case BLOCKED:
1051 if (current_frame_length_ != GetBlockedSize() ||
1052 protocol_version() <= SPDY3) {
1053 set_error(SPDY_INVALID_CONTROL_FRAME);
1054 } else if (current_frame_flags_ != 0) {
1055 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1057 break;
1058 case PUSH_PROMISE:
1059 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
1060 set_error(SPDY_INVALID_CONTROL_FRAME);
1061 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
1062 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1063 } else if (protocol_version() > SPDY3 &&
1064 current_frame_flags_ &
1065 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
1066 HEADERS_FLAG_PADDED)) {
1067 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1069 break;
1070 case CONTINUATION:
1071 if (current_frame_length_ < GetContinuationMinimumSize() ||
1072 protocol_version() <= SPDY3) {
1073 set_error(SPDY_INVALID_CONTROL_FRAME);
1074 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
1075 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1077 break;
1078 case ALTSVC:
1079 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
1080 set_error(SPDY_INVALID_CONTROL_FRAME);
1081 } else if (current_frame_flags_ != 0) {
1082 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1084 break;
1085 case PRIORITY:
1086 if (current_frame_length_ != GetPrioritySize() ||
1087 protocol_version() <= SPDY3) {
1088 set_error(SPDY_INVALID_CONTROL_FRAME);
1089 } else if (current_frame_flags_ != 0) {
1090 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1092 break;
1093 default:
1094 LOG(WARNING) << "Valid " << display_protocol_
1095 << " control frame with unhandled type: "
1096 << current_frame_type_;
1097 // This branch should be unreachable because of the frame type bounds
1098 // check above. However, we DLOG(FATAL) here in an effort to painfully
1099 // club the head of the developer who failed to keep this file in sync
1100 // with spdy_protocol.h.
1101 set_error(SPDY_INVALID_CONTROL_FRAME);
1102 DLOG(FATAL);
1103 break;
1106 if (state_ == SPDY_ERROR) {
1107 return;
1110 if (current_frame_length_ >
1111 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1112 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1113 DLOG(WARNING) << "Received control frame of type " << current_frame_type_
1114 << " with way too big of a payload: "
1115 << current_frame_length_;
1116 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1117 return;
1120 if (current_frame_type_ == GOAWAY) {
1121 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1122 return;
1125 if (current_frame_type_ == RST_STREAM) {
1126 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1127 return;
1130 if (current_frame_type_ == ALTSVC) {
1131 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1132 return;
1134 // Determine the frame size without variable-length data.
1135 int32 frame_size_without_variable_data;
1136 switch (current_frame_type_) {
1137 case SYN_STREAM:
1138 syn_frame_processed_ = true;
1139 frame_size_without_variable_data = GetSynStreamMinimumSize();
1140 break;
1141 case SYN_REPLY:
1142 syn_frame_processed_ = true;
1143 frame_size_without_variable_data = GetSynReplyMinimumSize();
1144 break;
1145 case SETTINGS:
1146 frame_size_without_variable_data = GetSettingsMinimumSize();
1147 break;
1148 case HEADERS:
1149 frame_size_without_variable_data = GetHeadersMinimumSize();
1150 if (protocol_version() > SPDY3) {
1151 if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
1152 frame_size_without_variable_data += kPadLengthFieldSize;
1154 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1155 frame_size_without_variable_data +=
1156 kPriorityDependencyPayloadSize +
1157 kPriorityWeightPayloadSize;
1160 break;
1161 case PUSH_PROMISE:
1162 frame_size_without_variable_data = GetPushPromiseMinimumSize();
1163 if (protocol_version() > SPDY3 &&
1164 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1165 frame_size_without_variable_data += kPadLengthFieldSize;
1167 break;
1168 case CONTINUATION:
1169 frame_size_without_variable_data = GetContinuationMinimumSize();
1170 break;
1171 default:
1172 frame_size_without_variable_data = -1;
1173 break;
1176 if ((frame_size_without_variable_data == -1) &&
1177 (current_frame_length_ > kControlFrameBufferSize)) {
1178 // We should already be in an error state. Double-check.
1179 DCHECK_EQ(SPDY_ERROR, state_);
1180 if (state_ != SPDY_ERROR) {
1181 LOG(DFATAL) << display_protocol_
1182 << " control frame buffer too small for fixed-length frame.";
1183 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1185 return;
1188 if (frame_size_without_variable_data > 0) {
1189 // We have a control frame with a header block. We need to parse the
1190 // remainder of the control frame's header before we can parse the header
1191 // block. The start of the header block varies with the control type.
1192 DCHECK_GE(frame_size_without_variable_data,
1193 static_cast<int32>(current_frame_buffer_.len()));
1194 remaining_control_header_ =
1195 frame_size_without_variable_data - current_frame_buffer_.len();
1197 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1198 return;
1201 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1204 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1205 size_t max_bytes) {
1206 size_t bytes_to_read = std::min(*len, max_bytes);
1207 if (bytes_to_read > 0) {
1208 current_frame_buffer_.CopyFrom(*data, bytes_to_read);
1209 *data += bytes_to_read;
1210 *len -= bytes_to_read;
1212 return bytes_to_read;
1215 size_t SpdyFramer::GetSerializedLength(
1216 const SpdyMajorVersion spdy_version,
1217 const SpdyHeaderBlock* headers) {
1218 const size_t num_name_value_pairs_size
1219 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1220 const size_t length_of_name_size = num_name_value_pairs_size;
1221 const size_t length_of_value_size = num_name_value_pairs_size;
1223 size_t total_length = num_name_value_pairs_size;
1224 for (const auto& header : *headers) {
1225 // We add space for the length of the name and the length of the value as
1226 // well as the length of the name and the length of the value.
1227 total_length += length_of_name_size + header.first.size() +
1228 length_of_value_size + header.second.size();
1230 return total_length;
1233 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1234 const SpdyMajorVersion spdy_version,
1235 const SpdyHeaderBlock* headers) {
1236 if (spdy_version < SPDY3) {
1237 frame->WriteUInt16(static_cast<uint16>(headers->size()));
1238 } else {
1239 frame->WriteUInt32(headers->size());
1241 SpdyHeaderBlock::const_iterator it;
1242 for (it = headers->begin(); it != headers->end(); ++it) {
1243 if (spdy_version < SPDY3) {
1244 frame->WriteStringPiece16(it->first);
1245 frame->WriteStringPiece16(it->second);
1246 } else {
1247 frame->WriteStringPiece32(it->first);
1248 frame->WriteStringPiece32(it->second);
1253 // TODO(phajdan.jr): Clean up after we no longer need
1254 // to workaround http://crbug.com/139744.
1255 #if !defined(USE_SYSTEM_ZLIB)
1257 // These constants are used by zlib to differentiate between normal data and
1258 // cookie data. Cookie data is handled specially by zlib when compressing.
1259 enum ZDataClass {
1260 // kZStandardData is compressed normally, save that it will never match
1261 // against any other class of data in the window.
1262 kZStandardData = Z_CLASS_STANDARD,
1263 // kZCookieData is compressed in its own Huffman blocks and only matches in
1264 // its entirety and only against other kZCookieData blocks. Any matches must
1265 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1266 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1267 // prefix matches.
1268 kZCookieData = Z_CLASS_COOKIE,
1269 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1270 // against the window.
1271 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1274 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1275 // needed when switching between classes of data.
1276 static void WriteZ(const base::StringPiece& data,
1277 ZDataClass clas,
1278 z_stream* out) {
1279 int rv;
1281 // If we are switching from standard to non-standard data then we need to end
1282 // the current Huffman context to avoid it leaking between them.
1283 if (out->clas == kZStandardData &&
1284 clas != kZStandardData) {
1285 out->avail_in = 0;
1286 rv = deflate(out, Z_PARTIAL_FLUSH);
1287 DCHECK_EQ(Z_OK, rv);
1288 DCHECK_EQ(0u, out->avail_in);
1289 DCHECK_LT(0u, out->avail_out);
1292 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1293 out->avail_in = data.size();
1294 out->clas = clas;
1295 if (clas == kZStandardData) {
1296 rv = deflate(out, Z_NO_FLUSH);
1297 } else {
1298 rv = deflate(out, Z_PARTIAL_FLUSH);
1300 if (!data.empty()) {
1301 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1302 DCHECK_EQ(Z_OK, rv);
1304 DCHECK_EQ(0u, out->avail_in);
1305 DCHECK_LT(0u, out->avail_out);
1308 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1309 static void WriteLengthZ(size_t n,
1310 unsigned length,
1311 ZDataClass clas,
1312 z_stream* out) {
1313 char buf[4];
1314 DCHECK_LE(length, sizeof(buf));
1315 for (unsigned i = 1; i <= length; i++) {
1316 buf[length - i] = static_cast<char>(n);
1317 n >>= 8;
1319 WriteZ(base::StringPiece(buf, length), clas, out);
1322 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1323 // manner that resists the length of the compressed data from compromising
1324 // cookie data.
1325 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1326 z_stream* z) const {
1327 unsigned length_length = 4;
1328 if (protocol_version() < 3)
1329 length_length = 2;
1331 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1333 std::map<std::string, std::string>::const_iterator it;
1334 for (it = headers->begin(); it != headers->end(); ++it) {
1335 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1336 WriteZ(it->first, kZStandardData, z);
1338 if (it->first == "cookie") {
1339 // We require the cookie values (save for the last) to end with a
1340 // semicolon and (save for the first) to start with a space. This is
1341 // typically the format that we are given them in but we reserialize them
1342 // to be sure.
1344 std::vector<base::StringPiece> cookie_values;
1345 size_t cookie_length = 0;
1346 base::StringPiece cookie_data(it->second);
1348 for (;;) {
1349 while (!cookie_data.empty() &&
1350 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1351 cookie_data.remove_prefix(1);
1353 if (cookie_data.empty())
1354 break;
1356 size_t i;
1357 for (i = 0; i < cookie_data.size(); i++) {
1358 if (cookie_data[i] == ';')
1359 break;
1361 if (i < cookie_data.size()) {
1362 if (!IsCookieEmpty(cookie_data.substr(0, i))) {
1363 cookie_values.push_back(cookie_data.substr(0, i));
1364 cookie_length += i + 2 /* semicolon and space */;
1366 cookie_data.remove_prefix(i + 1);
1367 } else {
1368 if (!IsCookieEmpty(cookie_data)) {
1369 cookie_values.push_back(cookie_data);
1370 cookie_length += cookie_data.size();
1371 } else if (cookie_length > 2) {
1372 cookie_length -= 2 /* compensate for previously added length */;
1374 cookie_data.remove_prefix(i);
1378 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1379 for (size_t i = 0; i < cookie_values.size(); i++) {
1380 std::string cookie;
1381 // Since zlib will only back-reference complete cookies, a cookie that
1382 // is currently last (and so doesn't have a trailing semicolon) won't
1383 // match if it's later in a non-final position. The same is true of
1384 // the first cookie.
1385 if (i == 0 && cookie_values.size() == 1) {
1386 cookie = cookie_values[i].as_string();
1387 } else if (i == 0) {
1388 cookie = cookie_values[i].as_string() + ";";
1389 } else if (i < cookie_values.size() - 1) {
1390 cookie = " " + cookie_values[i].as_string() + ";";
1391 } else {
1392 cookie = " " + cookie_values[i].as_string();
1394 WriteZ(cookie, kZCookieData, z);
1396 } else if (it->first == "accept" ||
1397 it->first == "accept-charset" ||
1398 it->first == "accept-encoding" ||
1399 it->first == "accept-language" ||
1400 it->first == "host" ||
1401 it->first == "version" ||
1402 it->first == "method" ||
1403 it->first == "scheme" ||
1404 it->first == ":host" ||
1405 it->first == ":version" ||
1406 it->first == ":method" ||
1407 it->first == ":scheme" ||
1408 it->first == "user-agent") {
1409 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1410 WriteZ(it->second, kZStandardData, z);
1411 } else {
1412 // Non-whitelisted headers are Huffman compressed in their own block, but
1413 // don't match against the window.
1414 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1415 WriteZ(it->second, kZHuffmanOnlyData, z);
1419 z->avail_in = 0;
1420 int rv = deflate(z, Z_SYNC_FLUSH);
1421 DCHECK_EQ(Z_OK, rv);
1422 z->clas = kZStandardData;
1425 #endif // !defined(USE_SYSTEM_ZLIB)
1427 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1428 size_t len) {
1429 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1430 const size_t original_len = len;
1432 if (remaining_control_header_ > 0) {
1433 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1434 remaining_control_header_);
1435 remaining_control_header_ -= bytes_read;
1436 remaining_data_length_ -= bytes_read;
1439 if (remaining_control_header_ == 0) {
1440 SpdyFrameReader reader(current_frame_buffer_.data(),
1441 current_frame_buffer_.len());
1442 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1444 switch (current_frame_type_) {
1445 case SYN_STREAM:
1447 DCHECK_GE(SPDY3, protocol_version());
1448 bool successful_read = true;
1449 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1450 DCHECK(successful_read);
1451 if (current_frame_stream_id_ == 0) {
1452 set_error(SPDY_INVALID_CONTROL_FRAME);
1453 break;
1456 SpdyStreamId associated_to_stream_id = kInvalidStream;
1457 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1458 DCHECK(successful_read);
1460 SpdyPriority priority = 0;
1461 successful_read = reader.ReadUInt8(&priority);
1462 DCHECK(successful_read);
1463 if (protocol_version() <= SPDY2) {
1464 priority = priority >> 6;
1465 } else {
1466 priority = priority >> 5;
1469 // Seek past unused byte; used to be credential slot in SPDY 3.
1470 reader.Seek(1);
1472 DCHECK(reader.IsDoneReading());
1473 if (debug_visitor_) {
1474 debug_visitor_->OnReceiveCompressedFrame(
1475 current_frame_stream_id_,
1476 current_frame_type_,
1477 current_frame_length_);
1479 visitor_->OnSynStream(
1480 current_frame_stream_id_,
1481 associated_to_stream_id,
1482 priority,
1483 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1484 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1486 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1487 break;
1488 case SETTINGS:
1489 if (protocol_version() > SPDY3 &&
1490 current_frame_flags_ & SETTINGS_FLAG_ACK) {
1491 visitor_->OnSettingsAck();
1492 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1493 } else {
1494 visitor_->OnSettings(current_frame_flags_ &
1495 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1496 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1498 break;
1499 case SYN_REPLY:
1500 case HEADERS:
1501 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1503 if (protocol_version() > SPDY3) {
1504 DCHECK_EQ(HEADERS, current_frame_type_);
1506 bool successful_read = true;
1507 if (protocol_version() <= SPDY3) {
1508 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1509 DCHECK(successful_read);
1511 if (current_frame_stream_id_ == 0) {
1512 set_error(SPDY_INVALID_CONTROL_FRAME);
1513 break;
1515 if (protocol_version() <= SPDY2) {
1516 // SPDY 2 had two unused bytes here. Seek past them.
1517 reader.Seek(2);
1519 if (protocol_version() > SPDY3 &&
1520 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1521 current_frame_type_ == HEADERS) {
1522 expect_continuation_ = current_frame_stream_id_;
1523 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1525 if (protocol_version() > SPDY3 &&
1526 current_frame_flags_ & HEADERS_FLAG_PADDED) {
1527 uint8 pad_payload_len = 0;
1528 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1529 successful_read = reader.ReadUInt8(&pad_payload_len);
1530 DCHECK(successful_read);
1531 remaining_padding_payload_length_ = pad_payload_len;
1533 const bool has_priority =
1534 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1535 SpdyPriority priority = 0;
1536 uint32 parent_stream_id = 0;
1537 bool exclusive = false;
1538 if (protocol_version() > SPDY3 && has_priority) {
1539 uint32 stream_dependency;
1540 successful_read = reader.ReadUInt32(&stream_dependency);
1541 DCHECK(successful_read);
1542 UnpackStreamDependencyValues(stream_dependency, &exclusive,
1543 &parent_stream_id);
1545 uint8 weight = 0;
1546 successful_read = reader.ReadUInt8(&weight);
1547 if (successful_read) {
1548 priority = MapWeightToPriority(weight);
1551 DCHECK(reader.IsDoneReading());
1552 if (debug_visitor_) {
1553 debug_visitor_->OnReceiveCompressedFrame(
1554 current_frame_stream_id_,
1555 current_frame_type_,
1556 current_frame_length_);
1558 if (current_frame_type_ == SYN_REPLY) {
1559 visitor_->OnSynReply(
1560 current_frame_stream_id_,
1561 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1562 } else {
1563 visitor_->OnHeaders(
1564 current_frame_stream_id_,
1565 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, priority,
1566 parent_stream_id, exclusive,
1567 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1568 expect_continuation_ == 0);
1571 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1572 break;
1573 case PUSH_PROMISE:
1575 DCHECK_LT(SPDY3, protocol_version());
1576 if (current_frame_stream_id_ == 0) {
1577 set_error(SPDY_INVALID_CONTROL_FRAME);
1578 break;
1580 bool successful_read = true;
1581 if (protocol_version() > SPDY3 &&
1582 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1583 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1584 uint8 pad_payload_len = 0;
1585 successful_read = reader.ReadUInt8(&pad_payload_len);
1586 DCHECK(successful_read);
1587 remaining_padding_payload_length_ = pad_payload_len;
1591 SpdyStreamId promised_stream_id = kInvalidStream;
1592 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1593 DCHECK(successful_read);
1594 DCHECK(reader.IsDoneReading());
1595 if (promised_stream_id == 0) {
1596 set_error(SPDY_INVALID_CONTROL_FRAME);
1597 break;
1599 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1600 expect_continuation_ = current_frame_stream_id_;
1602 if (debug_visitor_) {
1603 debug_visitor_->OnReceiveCompressedFrame(
1604 current_frame_stream_id_,
1605 current_frame_type_,
1606 current_frame_length_);
1608 visitor_->OnPushPromise(current_frame_stream_id_,
1609 promised_stream_id,
1610 (current_frame_flags_ &
1611 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1613 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1614 break;
1615 case CONTINUATION:
1617 // Check to make sure the stream id of the current frame is
1618 // the same as that of the preceding frame.
1619 // If we're at this point we should already know that
1620 // expect_continuation_ != 0, so this doubles as a check
1621 // that current_frame_stream_id != 0.
1622 if (current_frame_stream_id_ != expect_continuation_) {
1623 set_error(SPDY_INVALID_CONTROL_FRAME);
1624 break;
1626 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1627 expect_continuation_ = 0;
1629 if (debug_visitor_) {
1630 debug_visitor_->OnReceiveCompressedFrame(
1631 current_frame_stream_id_,
1632 current_frame_type_,
1633 current_frame_length_);
1635 visitor_->OnContinuation(current_frame_stream_id_,
1636 (current_frame_flags_ &
1637 HEADERS_FLAG_END_HEADERS) != 0);
1639 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1640 break;
1641 default:
1642 DCHECK(false);
1645 return original_len - len;
1648 // Does not buffer the control payload. Instead, either passes directly to the
1649 // visitor or decompresses and then passes directly to the visitor, via
1650 // IncrementallyDeliverControlFrameHeaderData() or
1651 // IncrementallyDecompressControlFrameHeaderData() respectively.
1652 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1653 size_t data_len,
1654 bool is_hpack_header_block) {
1655 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1657 bool processed_successfully = true;
1658 if (current_frame_type_ != SYN_STREAM &&
1659 current_frame_type_ != SYN_REPLY &&
1660 current_frame_type_ != HEADERS &&
1661 current_frame_type_ != PUSH_PROMISE &&
1662 current_frame_type_ != CONTINUATION) {
1663 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1665 size_t process_bytes = std::min(
1666 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1667 if (is_hpack_header_block) {
1668 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1669 current_frame_stream_id_, data, process_bytes)) {
1670 // TODO(jgraettinger): Finer-grained HPACK error codes.
1671 set_error(SPDY_DECOMPRESS_FAILURE);
1672 processed_successfully = false;
1674 } else if (process_bytes > 0) {
1675 if (enable_compression_ && protocol_version() <= SPDY3) {
1676 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1677 current_frame_stream_id_, data, process_bytes);
1678 } else {
1679 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1680 current_frame_stream_id_, data, process_bytes);
1683 remaining_data_length_ -= process_bytes;
1685 // Handle the case that there is no futher data in this frame.
1686 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1687 processed_successfully) {
1688 if (expect_continuation_ == 0) {
1689 if (is_hpack_header_block) {
1690 size_t compressed_len = 0;
1691 if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
1692 current_frame_stream_id_, &compressed_len)) {
1693 // TODO(jgraettinger): To be removed with migration to
1694 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1695 // block, delivered via reentrant call to
1696 // ProcessControlFrameHeaderBlock().
1697 DeliverHpackBlockAsSpdy3Block(compressed_len);
1698 return process_bytes;
1700 set_error(SPDY_DECOMPRESS_FAILURE);
1701 processed_successfully = false;
1702 } else {
1703 // The complete header block has been delivered. We send a zero-length
1704 // OnControlFrameHeaderData() to indicate this.
1705 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1708 if (processed_successfully) {
1709 CHANGE_STATE(SPDY_CONSUME_PADDING);
1713 // Handle error.
1714 if (!processed_successfully) {
1715 return data_len;
1718 // Return amount processed.
1719 return process_bytes;
1722 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1723 size_t data_len) {
1724 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1725 DCHECK_EQ(SETTINGS, current_frame_type_);
1726 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1727 size_t processed_bytes = 0;
1729 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
1731 // Loop over our incoming data.
1732 while (unprocessed_bytes > 0) {
1733 // Process up to one setting at a time.
1734 size_t processing = std::min(unprocessed_bytes,
1735 setting_size - settings_scratch_.buffer.len());
1737 // Check if we have a complete setting in our input.
1738 if (processing == setting_size) {
1739 // Parse the setting directly out of the input without buffering.
1740 if (!ProcessSetting(data + processed_bytes)) {
1741 set_error(SPDY_INVALID_CONTROL_FRAME);
1742 return processed_bytes;
1744 } else {
1745 // Continue updating settings_scratch_.setting_buf.
1746 settings_scratch_.buffer.CopyFrom(data + processed_bytes, processing);
1748 // Check if we have a complete setting buffered.
1749 if (settings_scratch_.buffer.len() == setting_size) {
1750 if (!ProcessSetting(settings_scratch_.buffer.data())) {
1751 set_error(SPDY_INVALID_CONTROL_FRAME);
1752 return processed_bytes;
1754 // Rewind settings buffer for our next setting.
1755 settings_scratch_.buffer.Rewind();
1759 // Iterate.
1760 unprocessed_bytes -= processing;
1761 processed_bytes += processing;
1764 // Check if we're done handling this SETTINGS frame.
1765 remaining_data_length_ -= processed_bytes;
1766 if (remaining_data_length_ == 0) {
1767 visitor_->OnSettingsEnd();
1768 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1771 return processed_bytes;
1774 void SpdyFramer::DeliverHpackBlockAsSpdy3Block(size_t compressed_len) {
1775 DCHECK_LT(SPDY3, protocol_version());
1776 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1778 const SpdyHeaderBlock& block = GetHpackDecoder()->decoded_block();
1779 if (block.empty()) {
1780 // Special-case this to make tests happy.
1781 ProcessControlFrameHeaderBlock(NULL, 0, false);
1782 return;
1784 size_t payload_len = GetSerializedLength(protocol_version(), &block);
1785 SpdyFrameBuilder builder(payload_len, SPDY3);
1787 SerializeHeaderBlockWithoutCompression(&builder, block);
1788 scoped_ptr<SpdyFrame> frame(builder.take());
1790 // Preserve padding length, and reset it after the re-entrant call.
1791 size_t remaining_padding = remaining_padding_payload_length_;
1793 remaining_padding_payload_length_ = 0;
1794 remaining_data_length_ = frame->size();
1796 if (payload_len != 0) {
1797 int compression_pct = 100 - (100 * compressed_len) / payload_len;
1798 DVLOG(1) << "Net.SpdyHpackDecompressionPercentage: " << compression_pct;
1799 UMA_HISTOGRAM_PERCENTAGE("Net.SpdyHpackDecompressionPercentage",
1800 compression_pct);
1803 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1805 remaining_padding_payload_length_ = remaining_padding;
1806 remaining_data_length_ = remaining_padding;
1809 bool SpdyFramer::ProcessSetting(const char* data) {
1810 int id_field;
1811 SpdySettingsIds id;
1812 uint8 flags = 0;
1813 uint32 value;
1815 // Extract fields.
1816 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1817 if (protocol_version() <= SPDY3) {
1818 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1819 SettingsFlagsAndId id_and_flags =
1820 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1821 id_field = id_and_flags.id();
1822 flags = id_and_flags.flags();
1823 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1824 } else {
1825 id_field = ntohs(*(reinterpret_cast<const uint16*>(data)));
1826 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2)));
1829 // Validate id.
1830 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1831 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1832 if (protocol_version() <= SPDY3) {
1833 return false;
1834 } else {
1835 // In HTTP2 we ignore unknown settings for extensibility.
1836 return true;
1839 id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1841 if (protocol_version() <= SPDY3) {
1842 // Detect duplicates.
1843 if (id <= settings_scratch_.last_setting_id) {
1844 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1845 << " in " << display_protocol_ << " SETTINGS frame "
1846 << "(last setting id was "
1847 << settings_scratch_.last_setting_id << ").";
1848 return false;
1850 settings_scratch_.last_setting_id = id;
1852 // Validate flags.
1853 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1854 if ((flags & ~(kFlagsMask)) != 0) {
1855 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1856 << flags;
1857 return false;
1861 // Validation succeeded. Pass on to visitor.
1862 visitor_->OnSetting(id, flags, value);
1863 return true;
1866 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1867 size_t original_len = len;
1868 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1869 remaining_data_length_);
1870 remaining_data_length_ -= bytes_read;
1871 if (remaining_data_length_ == 0) {
1872 SpdyFrameReader reader(current_frame_buffer_.data(),
1873 current_frame_buffer_.len());
1874 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1876 // Use frame-specific handlers.
1877 switch (current_frame_type_) {
1878 case PING: {
1879 SpdyPingId id = 0;
1880 bool is_ack = protocol_version() > SPDY3 &&
1881 (current_frame_flags_ & PING_FLAG_ACK);
1882 bool successful_read = true;
1883 if (protocol_version() <= SPDY3) {
1884 uint32 id32 = 0;
1885 successful_read = reader.ReadUInt32(&id32);
1886 id = id32;
1887 } else {
1888 successful_read = reader.ReadUInt64(&id);
1890 DCHECK(successful_read);
1891 DCHECK(reader.IsDoneReading());
1892 visitor_->OnPing(id, is_ack);
1894 break;
1895 case WINDOW_UPDATE: {
1896 uint32 delta_window_size = 0;
1897 bool successful_read = true;
1898 if (protocol_version() <= SPDY3) {
1899 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1900 DCHECK(successful_read);
1902 successful_read = reader.ReadUInt32(&delta_window_size);
1903 DCHECK(successful_read);
1904 DCHECK(reader.IsDoneReading());
1905 visitor_->OnWindowUpdate(current_frame_stream_id_,
1906 delta_window_size);
1908 break;
1909 case BLOCKED: {
1910 DCHECK_LT(SPDY3, protocol_version());
1911 DCHECK(reader.IsDoneReading());
1912 visitor_->OnBlocked(current_frame_stream_id_);
1914 break;
1915 case PRIORITY: {
1916 DCHECK_LT(SPDY3, protocol_version());
1917 uint32 stream_dependency;
1918 uint32 parent_stream_id;
1919 bool exclusive;
1920 uint8 weight;
1921 bool successful_read = reader.ReadUInt32(&stream_dependency);
1922 DCHECK(successful_read);
1923 UnpackStreamDependencyValues(stream_dependency, &exclusive,
1924 &parent_stream_id);
1926 successful_read = reader.ReadUInt8(&weight);
1927 DCHECK(successful_read);
1928 DCHECK(reader.IsDoneReading());
1929 visitor_->OnPriority(
1930 current_frame_stream_id_, parent_stream_id, weight, exclusive);
1932 break;
1933 default:
1934 // Unreachable.
1935 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1938 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1940 return original_len - len;
1943 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1944 if (len == 0) {
1945 return 0;
1947 // Clamp to the actual remaining payload.
1948 if (len > remaining_data_length_) {
1949 len = remaining_data_length_;
1951 size_t original_len = len;
1953 // Check if we had already read enough bytes to parse the GOAWAY header.
1954 const size_t header_size = GetGoAwayMinimumSize();
1955 size_t unread_header_bytes = header_size - current_frame_buffer_.len();
1956 bool already_parsed_header = (unread_header_bytes == 0);
1957 if (!already_parsed_header) {
1958 // Buffer the new GOAWAY header bytes we got.
1959 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1961 // Do we have enough to parse the constant size GOAWAY header?
1962 if (current_frame_buffer_.len() == header_size) {
1963 // Parse out the last good stream id.
1964 SpdyFrameReader reader(current_frame_buffer_.data(),
1965 current_frame_buffer_.len());
1966 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1967 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1968 DCHECK(successful_read);
1970 // In SPDYv3 and up, frames also specify a status code - parse it out.
1971 SpdyGoAwayStatus status = GOAWAY_OK;
1972 if (protocol_version() >= SPDY3) {
1973 uint32 status_raw = GOAWAY_OK;
1974 successful_read = reader.ReadUInt32(&status_raw);
1975 DCHECK(successful_read);
1976 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1977 status_raw)) {
1978 status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1979 status_raw);
1980 } else {
1981 if (protocol_version() > SPDY3) {
1982 // Treat unrecognized status codes as INTERNAL_ERROR as
1983 // recommended by the HTTP/2 spec.
1984 status = GOAWAY_INTERNAL_ERROR;
1988 // Finished parsing the GOAWAY header, call frame handler.
1989 visitor_->OnGoAway(current_frame_stream_id_, status);
1993 // Handle remaining data as opaque.
1994 bool processed_successfully = true;
1995 if (len > 0) {
1996 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1998 remaining_data_length_ -= original_len;
1999 if (!processed_successfully) {
2000 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
2001 } else if (remaining_data_length_ == 0) {
2002 // Signal that there is not more opaque data.
2003 visitor_->OnGoAwayFrameData(NULL, 0);
2004 CHANGE_STATE(SPDY_FRAME_COMPLETE);
2006 return original_len;
2009 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
2010 if (len == 0) {
2011 return 0;
2013 // Clamp to the actual remaining payload.
2014 if (len > remaining_data_length_) {
2015 len = remaining_data_length_;
2017 size_t original_len = len;
2019 // Check if we had already read enough bytes to parse the fixed-length portion
2020 // of the RST_STREAM frame.
2021 const size_t header_size = GetRstStreamMinimumSize();
2022 size_t unread_header_bytes = header_size - current_frame_buffer_.len();
2023 bool already_parsed_header = (unread_header_bytes == 0);
2024 if (!already_parsed_header) {
2025 // Buffer the new RST_STREAM header bytes we got.
2026 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
2028 // Do we have enough to parse the constant size RST_STREAM header?
2029 if (current_frame_buffer_.len() == header_size) {
2030 // Parse out the last good stream id.
2031 SpdyFrameReader reader(current_frame_buffer_.data(),
2032 current_frame_buffer_.len());
2033 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2034 if (protocol_version() <= SPDY3) {
2035 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
2036 DCHECK(successful_read);
2039 SpdyRstStreamStatus status = RST_STREAM_INVALID;
2040 uint32 status_raw = status;
2041 bool successful_read = reader.ReadUInt32(&status_raw);
2042 DCHECK(successful_read);
2043 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
2044 status_raw)) {
2045 status =
2046 SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw);
2047 } else {
2048 if (protocol_version() > SPDY3) {
2049 // Treat unrecognized status codes as INTERNAL_ERROR as
2050 // recommended by the HTTP/2 spec.
2051 status = RST_STREAM_INTERNAL_ERROR;
2054 // Finished parsing the RST_STREAM header, call frame handler.
2055 visitor_->OnRstStream(current_frame_stream_id_, status);
2059 // Handle remaining data as opaque.
2060 bool processed_successfully = true;
2061 if (len > 0) {
2062 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
2064 remaining_data_length_ -= original_len;
2065 if (!processed_successfully) {
2066 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
2067 } else if (remaining_data_length_ == 0) {
2068 // Signal that there is not more opaque data.
2069 visitor_->OnRstStreamFrameData(NULL, 0);
2070 CHANGE_STATE(SPDY_FRAME_COMPLETE);
2072 return original_len;
2075 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
2076 if (len == 0) {
2077 return 0;
2080 // Clamp to the actual remaining payload.
2081 len = std::min(len, remaining_data_length_);
2083 if (altsvc_scratch_ == nullptr) {
2084 size_t capacity = current_frame_length_ - GetControlFrameHeaderSize();
2085 altsvc_scratch_.reset(new CharBuffer(capacity));
2087 altsvc_scratch_->CopyFrom(data, len);
2088 remaining_data_length_ -= len;
2089 if (remaining_data_length_ > 0) {
2090 return len;
2093 SpdyFrameReader reader(altsvc_scratch_->data(), altsvc_scratch_->len());
2094 StringPiece origin;
2095 bool successful_read = reader.ReadStringPiece16(&origin);
2096 if (!successful_read) {
2097 set_error(SPDY_INVALID_CONTROL_FRAME);
2098 return 0;
2100 StringPiece value(altsvc_scratch_->data() + reader.GetBytesConsumed(),
2101 altsvc_scratch_->len() - reader.GetBytesConsumed());
2103 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
2104 bool success =
2105 SpdyAltSvcWireFormat::ParseHeaderFieldValue(value, &altsvc_vector);
2106 if (!success) {
2107 set_error(SPDY_INVALID_CONTROL_FRAME);
2108 return 0;
2111 visitor_->OnAltSvc(current_frame_stream_id_, origin, altsvc_vector);
2112 CHANGE_STATE(SPDY_FRAME_COMPLETE);
2113 return len;
2116 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
2117 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_);
2118 DCHECK_EQ(0u, remaining_padding_payload_length_);
2119 DCHECK_EQ(DATA, current_frame_type_);
2121 size_t original_len = len;
2122 if (current_frame_flags_ & DATA_FLAG_PADDED) {
2123 if (len != 0) {
2124 if (remaining_data_length_ < kPadLengthFieldSize) {
2125 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2126 return 0;
2129 static_assert(kPadLengthFieldSize == 1,
2130 "Unexpected pad length field size.");
2131 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data);
2132 ++data;
2133 --len;
2134 --remaining_data_length_;
2135 visitor_->OnStreamPadding(current_frame_stream_id_, kPadLengthFieldSize);
2136 } else {
2137 // We don't have the data available for parsing the pad length field. Keep
2138 // waiting.
2139 return 0;
2143 if (remaining_padding_payload_length_ > remaining_data_length_) {
2144 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2145 return 0;
2147 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2148 return original_len - len;
2151 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2152 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2154 size_t original_len = len;
2155 if (remaining_padding_payload_length_ > 0) {
2156 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2157 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2158 if (current_frame_type_ == DATA && amount_to_discard > 0) {
2159 DCHECK_LE(HTTP2, protocol_version());
2160 visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
2162 data += amount_to_discard;
2163 len -= amount_to_discard;
2164 remaining_padding_payload_length_ -= amount_to_discard;
2165 remaining_data_length_ -= amount_to_discard;
2168 if (remaining_data_length_ == 0) {
2169 // If the FIN flag is set, or this ends a header block which set FIN,
2170 // inform the visitor of EOF via a 0-length data frame.
2171 if (expect_continuation_ == 0 &&
2172 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2173 end_stream_when_done_)) {
2174 end_stream_when_done_ = false;
2175 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2177 CHANGE_STATE(SPDY_FRAME_COMPLETE);
2179 return original_len - len;
2182 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2183 size_t original_len = len;
2184 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2185 size_t amount_to_forward = std::min(
2186 remaining_data_length_ - remaining_padding_payload_length_, len);
2187 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2188 // Only inform the visitor if there is data.
2189 if (amount_to_forward) {
2190 visitor_->OnStreamFrameData(
2191 current_frame_stream_id_, data, amount_to_forward, false);
2194 data += amount_to_forward;
2195 len -= amount_to_forward;
2196 remaining_data_length_ -= amount_to_forward;
2199 if (remaining_data_length_ == remaining_padding_payload_length_) {
2200 CHANGE_STATE(SPDY_CONSUME_PADDING);
2202 return original_len - len;
2205 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2206 size_t len) {
2207 size_t original_len = len;
2208 if (remaining_data_length_ > 0) {
2209 size_t amount_to_ignore = std::min(remaining_data_length_, len);
2210 len -= amount_to_ignore;
2211 remaining_data_length_ -= amount_to_ignore;
2214 if (remaining_data_length_ == 0) {
2215 CHANGE_STATE(SPDY_FRAME_COMPLETE);
2217 return original_len - len;
2220 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2221 size_t header_length,
2222 SpdyHeaderBlock* block) const {
2223 SpdyFrameReader reader(header_data, header_length);
2225 // Read number of headers.
2226 uint32 num_headers;
2227 if (protocol_version() <= SPDY2) {
2228 uint16 temp;
2229 if (!reader.ReadUInt16(&temp)) {
2230 DVLOG(1) << "Unable to read number of headers.";
2231 return 0;
2233 num_headers = temp;
2234 } else {
2235 if (!reader.ReadUInt32(&num_headers)) {
2236 DVLOG(1) << "Unable to read number of headers.";
2237 return 0;
2241 // Read each header.
2242 for (uint32 index = 0; index < num_headers; ++index) {
2243 base::StringPiece temp;
2245 // Read header name.
2246 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2247 : !reader.ReadStringPiece32(&temp)) {
2248 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2249 << num_headers << ").";
2250 return 0;
2252 std::string name = temp.as_string();
2254 // Read header value.
2255 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2256 : !reader.ReadStringPiece32(&temp)) {
2257 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2258 << num_headers << ").";
2259 return 0;
2261 std::string value = temp.as_string();
2263 // Ensure no duplicates.
2264 if (block->find(name) != block->end()) {
2265 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2266 << num_headers << ").";
2267 return 0;
2270 // Store header.
2271 (*block)[name] = value;
2273 return reader.GetBytesConsumed();
2276 SpdySerializedFrame* SpdyFramer::SerializeData(
2277 const SpdyDataIR& data_ir) const {
2278 uint8 flags = DATA_FLAG_NONE;
2279 if (data_ir.fin()) {
2280 flags = DATA_FLAG_FIN;
2283 if (protocol_version() > SPDY3) {
2284 int num_padding_fields = 0;
2285 if (data_ir.padded()) {
2286 flags |= DATA_FLAG_PADDED;
2287 ++num_padding_fields;
2290 const size_t size_with_padding = num_padding_fields +
2291 data_ir.data().length() + data_ir.padding_payload_len() +
2292 GetDataFrameMinimumSize();
2293 SpdyFrameBuilder builder(size_with_padding, protocol_version());
2294 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2295 if (data_ir.padded()) {
2296 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2298 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2299 if (data_ir.padding_payload_len() > 0) {
2300 string padding(data_ir.padding_payload_len(), 0);
2301 builder.WriteBytes(padding.data(), padding.length());
2303 DCHECK_EQ(size_with_padding, builder.length());
2304 return builder.take();
2305 } else {
2306 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2307 SpdyFrameBuilder builder(size, protocol_version());
2308 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2309 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2310 DCHECK_EQ(size, builder.length());
2311 return builder.take();
2315 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2316 const SpdyDataIR& data_ir) const {
2317 uint8 flags = DATA_FLAG_NONE;
2318 if (data_ir.fin()) {
2319 flags = DATA_FLAG_FIN;
2322 size_t frame_size = GetDataFrameMinimumSize();
2323 size_t num_padding_fields = 0;
2324 if (protocol_version() > SPDY3) {
2325 if (data_ir.padded()) {
2326 flags |= DATA_FLAG_PADDED;
2327 ++num_padding_fields;
2329 frame_size += num_padding_fields;
2332 SpdyFrameBuilder builder(frame_size, protocol_version());
2333 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2334 if (protocol_version() > SPDY3) {
2335 if (data_ir.padded()) {
2336 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2338 builder.OverwriteLength(*this, num_padding_fields +
2339 data_ir.data().length() + data_ir.padding_payload_len());
2340 } else {
2341 builder.OverwriteLength(*this, data_ir.data().length());
2343 DCHECK_EQ(frame_size, builder.length());
2344 return builder.take();
2347 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2348 const SpdySynStreamIR& syn_stream) {
2349 DCHECK_GE(SPDY3, protocol_version());
2350 uint8 flags = 0;
2351 if (syn_stream.fin()) {
2352 flags |= CONTROL_FLAG_FIN;
2354 if (syn_stream.unidirectional()) {
2355 // TODO(hkhalil): invalid for HTTP2.
2356 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2359 // Sanitize priority.
2360 uint8 priority = syn_stream.priority();
2361 if (priority > GetLowestPriority()) {
2362 DLOG(DFATAL) << "Priority out-of-bounds.";
2363 priority = GetLowestPriority();
2366 // The size of this frame, including variable-length header block.
2367 size_t size = GetSynStreamMinimumSize() +
2368 GetSerializedLength(syn_stream.header_block());
2370 SpdyFrameBuilder builder(size, protocol_version());
2371 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2372 builder.WriteUInt32(syn_stream.stream_id());
2373 builder.WriteUInt32(syn_stream.associated_to_stream_id());
2374 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2375 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
2376 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2377 SerializeHeaderBlock(&builder, syn_stream);
2379 if (debug_visitor_) {
2380 const size_t payload_len =
2381 GetSerializedLength(protocol_version(), &(syn_stream.header_block()));
2382 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2383 SYN_STREAM,
2384 payload_len,
2385 builder.length());
2388 return builder.take();
2391 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2392 const SpdySynReplyIR& syn_reply) {
2393 DCHECK_GE(SPDY3, protocol_version());
2394 uint8 flags = 0;
2395 if (syn_reply.fin()) {
2396 flags |= CONTROL_FLAG_FIN;
2399 // The size of this frame, including variable-length header block.
2400 const size_t size =
2401 GetSynReplyMinimumSize() + GetSerializedLength(syn_reply.header_block());
2403 SpdyFrameBuilder builder(size, protocol_version());
2404 if (protocol_version() <= SPDY3) {
2405 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2406 builder.WriteUInt32(syn_reply.stream_id());
2407 } else {
2408 builder.BeginNewFrame(*this,
2409 HEADERS,
2410 flags,
2411 syn_reply.stream_id());
2413 if (protocol_version() < SPDY3) {
2414 builder.WriteUInt16(0); // Unused.
2416 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2417 SerializeHeaderBlock(&builder, syn_reply);
2419 if (debug_visitor_) {
2420 const size_t payload_len =
2421 GetSerializedLength(protocol_version(), &(syn_reply.header_block()));
2422 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2423 SYN_REPLY,
2424 payload_len,
2425 builder.length());
2428 return builder.take();
2431 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2432 const SpdyRstStreamIR& rst_stream) const {
2433 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2434 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2435 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2436 // commented but left in place to simplify future patching.
2437 // Compute the output buffer size, taking opaque data into account.
2438 size_t expected_length = GetRstStreamMinimumSize();
2439 if (protocol_version() > SPDY3) {
2440 expected_length += rst_stream.description().size();
2442 SpdyFrameBuilder builder(expected_length, protocol_version());
2444 // Serialize the RST_STREAM frame.
2445 if (protocol_version() <= SPDY3) {
2446 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2447 builder.WriteUInt32(rst_stream.stream_id());
2448 } else {
2449 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2452 builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
2453 protocol_version(), rst_stream.status()));
2455 // In HTTP2 and up, RST_STREAM frames may also specify opaque data.
2456 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2457 builder.WriteBytes(rst_stream.description().data(),
2458 rst_stream.description().size());
2461 DCHECK_EQ(expected_length, builder.length());
2462 return builder.take();
2465 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2466 const SpdySettingsIR& settings) const {
2467 uint8 flags = 0;
2469 if (protocol_version() <= SPDY3) {
2470 if (settings.clear_settings()) {
2471 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2473 } else {
2474 if (settings.is_ack()) {
2475 flags |= SETTINGS_FLAG_ACK;
2478 const SpdySettingsIR::ValueMap* values = &(settings.values());
2480 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
2481 // Size, in bytes, of this SETTINGS frame.
2482 const size_t size = GetSettingsMinimumSize() +
2483 (values->size() * setting_size);
2484 SpdyFrameBuilder builder(size, protocol_version());
2485 if (protocol_version() <= SPDY3) {
2486 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2487 } else {
2488 builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2491 // If this is an ACK, payload should be empty.
2492 if (protocol_version() > SPDY3 && settings.is_ack()) {
2493 return builder.take();
2496 if (protocol_version() <= SPDY3) {
2497 builder.WriteUInt32(values->size());
2499 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2500 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2501 it != values->end();
2502 ++it) {
2503 int setting_id =
2504 SpdyConstants::SerializeSettingId(protocol_version(), it->first);
2505 DCHECK_GE(setting_id, 0);
2506 if (protocol_version() <= SPDY3) {
2507 uint8 setting_flags = 0;
2508 if (it->second.persist_value) {
2509 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2511 if (it->second.persisted) {
2512 setting_flags |= SETTINGS_FLAG_PERSISTED;
2514 SettingsFlagsAndId flags_and_id(setting_flags, setting_id);
2515 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2516 builder.WriteBytes(&id_and_flags_wire, 4);
2517 } else {
2518 builder.WriteUInt16(static_cast<uint16>(setting_id));
2520 builder.WriteUInt32(it->second.value);
2522 DCHECK_EQ(size, builder.length());
2523 return builder.take();
2526 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2527 SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2528 if (protocol_version() <= SPDY3) {
2529 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2530 builder.WriteUInt32(static_cast<uint32>(ping.id()));
2531 } else {
2532 uint8 flags = 0;
2533 if (ping.is_ack()) {
2534 flags |= PING_FLAG_ACK;
2536 builder.BeginNewFrame(*this, PING, flags, 0);
2537 builder.WriteUInt64(ping.id());
2539 DCHECK_EQ(GetPingSize(), builder.length());
2540 return builder.take();
2543 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2544 const SpdyGoAwayIR& goaway) const {
2546 // Compute the output buffer size, take opaque data into account.
2547 size_t expected_length = GetGoAwayMinimumSize();
2548 if (protocol_version() > SPDY3) {
2549 expected_length += goaway.description().size();
2551 SpdyFrameBuilder builder(expected_length, protocol_version());
2553 // Serialize the GOAWAY frame.
2554 if (protocol_version() <= SPDY3) {
2555 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2556 } else {
2557 builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2560 // GOAWAY frames specify the last good stream id for all SPDY versions.
2561 builder.WriteUInt32(goaway.last_good_stream_id());
2563 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2564 if (protocol_version() >= SPDY3) {
2565 // TODO(jgraettinger): Merge back to server-side.
2566 builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2567 goaway.status()));
2570 // In HTTP2 and up, GOAWAY frames may also specify opaque data.
2571 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2572 builder.WriteBytes(goaway.description().data(),
2573 goaway.description().size());
2576 DCHECK_EQ(expected_length, builder.length());
2577 return builder.take();
2580 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2581 const SpdyHeadersIR& headers) {
2582 uint8 flags = 0;
2583 if (headers.fin()) {
2584 flags |= CONTROL_FLAG_FIN;
2586 if (protocol_version() > SPDY3) {
2587 // This will get overwritten if we overflow into a CONTINUATION frame.
2588 flags |= HEADERS_FLAG_END_HEADERS;
2589 if (headers.has_priority()) {
2590 flags |= HEADERS_FLAG_PRIORITY;
2592 if (headers.padded()) {
2593 flags |= HEADERS_FLAG_PADDED;
2597 // The size of this frame, including padding (if there is any) and
2598 // variable-length header block.
2599 size_t size = GetHeadersMinimumSize();
2601 if (protocol_version() > SPDY3 && headers.padded()) {
2602 size += kPadLengthFieldSize;
2603 size += headers.padding_payload_len();
2606 SpdyPriority priority = static_cast<SpdyPriority>(headers.priority());
2607 if (headers.has_priority()) {
2608 if (headers.priority() > GetLowestPriority()) {
2609 DLOG(DFATAL) << "Priority out-of-bounds.";
2610 priority = GetLowestPriority();
2612 size += 5;
2615 string hpack_encoding;
2616 if (protocol_version() > SPDY3) {
2617 if (enable_compression_) {
2618 GetHpackEncoder()->EncodeHeaderSet(headers.header_block(),
2619 &hpack_encoding);
2620 } else {
2621 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2622 headers.header_block(), &hpack_encoding);
2624 size += hpack_encoding.size();
2625 if (size > kMaxControlFrameSize) {
2626 size += GetNumberRequiredContinuationFrames(size) *
2627 GetContinuationMinimumSize();
2628 flags &= ~HEADERS_FLAG_END_HEADERS;
2630 } else {
2631 size += GetSerializedLength(headers.header_block());
2634 SpdyFrameBuilder builder(size, protocol_version());
2635 if (protocol_version() <= SPDY3) {
2636 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2637 builder.WriteUInt32(headers.stream_id());
2638 } else {
2639 builder.BeginNewFrame(*this,
2640 HEADERS,
2641 flags,
2642 headers.stream_id());
2644 if (protocol_version() <= SPDY2) {
2645 builder.WriteUInt16(0); // Unused.
2647 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2649 if (protocol_version() > SPDY3) {
2650 int padding_payload_len = 0;
2651 if (headers.padded()) {
2652 builder.WriteUInt8(headers.padding_payload_len());
2653 padding_payload_len = headers.padding_payload_len();
2655 if (headers.has_priority()) {
2656 builder.WriteUInt32(PackStreamDependencyValues(
2657 headers.exclusive(), headers.parent_stream_id()));
2658 builder.WriteUInt8(MapPriorityToWeight(priority));
2660 WritePayloadWithContinuation(&builder,
2661 hpack_encoding,
2662 headers.stream_id(),
2663 HEADERS,
2664 padding_payload_len);
2665 } else {
2666 SerializeHeaderBlock(&builder, headers);
2669 if (debug_visitor_) {
2670 // HTTP2 uses HPACK for header compression. However, continue to
2671 // use GetSerializedLength() for an apples-to-apples comparision of
2672 // compression performance between HPACK and SPDY w/ deflate.
2673 const size_t payload_len =
2674 GetSerializedLength(protocol_version(), &(headers.header_block()));
2675 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2676 HEADERS,
2677 payload_len,
2678 builder.length());
2681 return builder.take();
2684 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2685 const SpdyWindowUpdateIR& window_update) const {
2686 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2687 if (protocol_version() <= SPDY3) {
2688 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2689 builder.WriteUInt32(window_update.stream_id());
2690 } else {
2691 builder.BeginNewFrame(*this,
2692 WINDOW_UPDATE,
2693 kNoFlags,
2694 window_update.stream_id());
2696 builder.WriteUInt32(window_update.delta());
2697 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2698 return builder.take();
2701 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2702 DCHECK_LT(SPDY3, protocol_version());
2703 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2704 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2705 return builder.take();
2708 SpdyFrame* SpdyFramer::SerializePushPromise(
2709 const SpdyPushPromiseIR& push_promise) {
2710 DCHECK_LT(SPDY3, protocol_version());
2711 uint8 flags = 0;
2712 // This will get overwritten if we overflow into a CONTINUATION frame.
2713 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2714 // The size of this frame, including variable-length name-value block.
2715 size_t size = GetPushPromiseMinimumSize();
2717 if (push_promise.padded()) {
2718 flags |= PUSH_PROMISE_FLAG_PADDED;
2719 size += kPadLengthFieldSize;
2720 size += push_promise.padding_payload_len();
2723 string hpack_encoding;
2724 if (enable_compression_) {
2725 GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(),
2726 &hpack_encoding);
2727 } else {
2728 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2729 push_promise.header_block(), &hpack_encoding);
2731 size += hpack_encoding.size();
2732 if (size > kMaxControlFrameSize) {
2733 size += GetNumberRequiredContinuationFrames(size) *
2734 GetContinuationMinimumSize();
2735 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2738 SpdyFrameBuilder builder(size, protocol_version());
2739 builder.BeginNewFrame(*this,
2740 PUSH_PROMISE,
2741 flags,
2742 push_promise.stream_id());
2743 int padding_payload_len = 0;
2744 if (push_promise.padded()) {
2745 builder.WriteUInt8(push_promise.padding_payload_len());
2746 builder.WriteUInt32(push_promise.promised_stream_id());
2747 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
2748 builder.length());
2750 padding_payload_len = push_promise.padding_payload_len();
2751 } else {
2752 builder.WriteUInt32(push_promise.promised_stream_id());
2753 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2756 WritePayloadWithContinuation(&builder,
2757 hpack_encoding,
2758 push_promise.stream_id(),
2759 PUSH_PROMISE,
2760 padding_payload_len);
2762 if (debug_visitor_) {
2763 // HTTP2 uses HPACK for header compression. However, continue to
2764 // use GetSerializedLength() for an apples-to-apples comparision of
2765 // compression performance between HPACK and SPDY w/ deflate.
2766 const size_t payload_len =
2767 GetSerializedLength(protocol_version(), &(push_promise.header_block()));
2768 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2769 PUSH_PROMISE,
2770 payload_len,
2771 builder.length());
2774 return builder.take();
2777 // TODO(jgraettinger): This implementation is incorrect. The continuation
2778 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2779 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2780 SpdyFrame* SpdyFramer::SerializeContinuation(
2781 const SpdyContinuationIR& continuation) {
2782 CHECK_LT(SPDY3, protocol_version());
2783 uint8 flags = 0;
2784 if (continuation.end_headers()) {
2785 flags |= HEADERS_FLAG_END_HEADERS;
2788 // The size of this frame, including variable-length name-value block.
2789 size_t size = GetContinuationMinimumSize();
2790 string hpack_encoding;
2791 if (enable_compression_) {
2792 GetHpackEncoder()->EncodeHeaderSet(continuation.header_block(),
2793 &hpack_encoding);
2794 } else {
2795 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2796 continuation.header_block(), &hpack_encoding);
2798 size += hpack_encoding.size();
2800 SpdyFrameBuilder builder(size, protocol_version());
2801 builder.BeginNewFrame(*this, CONTINUATION, flags,
2802 continuation.stream_id());
2803 DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2805 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2806 return builder.take();
2809 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
2810 DCHECK_LT(SPDY3, protocol_version());
2812 size_t size = GetAltSvcMinimumSize();
2813 size += altsvc_ir.origin().length();
2814 string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
2815 altsvc_ir.altsvc_vector());
2816 size += value.length();
2818 SpdyFrameBuilder builder(size, protocol_version());
2819 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id());
2821 builder.WriteUInt16(altsvc_ir.origin().length());
2822 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length());
2823 builder.WriteBytes(value.data(), value.length());
2824 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2825 return builder.take();
2828 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const {
2829 DCHECK_LT(SPDY3, protocol_version());
2830 size_t size = GetPrioritySize();
2832 SpdyFrameBuilder builder(size, protocol_version());
2833 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
2835 builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(),
2836 priority.parent_stream_id()));
2837 builder.WriteUInt8(priority.weight());
2838 DCHECK_EQ(GetPrioritySize(), builder.length());
2839 return builder.take();
2842 namespace {
2844 class FrameSerializationVisitor : public SpdyFrameVisitor {
2845 public:
2846 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2847 ~FrameSerializationVisitor() override {}
2849 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2851 void VisitData(const SpdyDataIR& data) override {
2852 frame_.reset(framer_->SerializeData(data));
2854 void VisitSynStream(const SpdySynStreamIR& syn_stream) override {
2855 frame_.reset(framer_->SerializeSynStream(syn_stream));
2857 void VisitSynReply(const SpdySynReplyIR& syn_reply) override {
2858 frame_.reset(framer_->SerializeSynReply(syn_reply));
2860 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2861 frame_.reset(framer_->SerializeRstStream(rst_stream));
2863 void VisitSettings(const SpdySettingsIR& settings) override {
2864 frame_.reset(framer_->SerializeSettings(settings));
2866 void VisitPing(const SpdyPingIR& ping) override {
2867 frame_.reset(framer_->SerializePing(ping));
2869 void VisitGoAway(const SpdyGoAwayIR& goaway) override {
2870 frame_.reset(framer_->SerializeGoAway(goaway));
2872 void VisitHeaders(const SpdyHeadersIR& headers) override {
2873 frame_.reset(framer_->SerializeHeaders(headers));
2875 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2876 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2878 void VisitBlocked(const SpdyBlockedIR& blocked) override {
2879 frame_.reset(framer_->SerializeBlocked(blocked));
2881 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2882 frame_.reset(framer_->SerializePushPromise(push_promise));
2884 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2885 frame_.reset(framer_->SerializeContinuation(continuation));
2887 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
2888 frame_.reset(framer_->SerializeAltSvc(altsvc));
2890 void VisitPriority(const SpdyPriorityIR& priority) override {
2891 frame_.reset(framer_->SerializePriority(priority));
2894 private:
2895 SpdyFramer* framer_;
2896 scoped_ptr<SpdySerializedFrame> frame_;
2899 } // namespace
2901 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2902 FrameSerializationVisitor visitor(this);
2903 frame.Visit(&visitor);
2904 return visitor.ReleaseSerializedFrame();
2907 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2908 CHECK_GE(SPDY3, protocol_version());
2909 const size_t uncompressed_length =
2910 GetSerializedLength(protocol_version(), &headers);
2911 if (!enable_compression_) {
2912 return uncompressed_length;
2914 z_stream* compressor = GetHeaderCompressor();
2915 // Since we'll be performing lots of flushes when compressing the data,
2916 // zlib's lower bounds may be insufficient.
2917 return 2 * deflateBound(compressor, uncompressed_length);
2920 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2921 DCHECK_GT(protocol_version(), SPDY3);
2922 DCHECK_GT(size, kMaxControlFrameSize);
2923 size_t overflow = size - kMaxControlFrameSize;
2924 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
2925 // This is ceiling(overflow/payload_size) using integer arithmetics.
2926 return (overflow - 1) / payload_size + 1;
2929 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2930 const string& hpack_encoding,
2931 SpdyStreamId stream_id,
2932 SpdyFrameType type,
2933 int padding_payload_len) {
2934 uint8 end_flag = 0;
2935 uint8 flags = 0;
2936 if (type == HEADERS) {
2937 end_flag = HEADERS_FLAG_END_HEADERS;
2938 } else if (type == PUSH_PROMISE) {
2939 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2940 } else {
2941 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2942 << FrameTypeToString(type);
2945 // Write all the padding payload and as much of the data payload as possible
2946 // into the initial frame.
2947 size_t bytes_remaining = 0;
2948 bytes_remaining =
2949 hpack_encoding.size() -
2950 std::min(hpack_encoding.size(),
2951 kMaxControlFrameSize - builder->length() - padding_payload_len);
2952 builder->WriteBytes(&hpack_encoding[0],
2953 hpack_encoding.size() - bytes_remaining);
2954 if (padding_payload_len > 0) {
2955 string padding = string(padding_payload_len, 0);
2956 builder->WriteBytes(padding.data(), padding.length());
2958 if (bytes_remaining > 0) {
2959 builder->OverwriteLength(
2960 *this, kMaxControlFrameSize - GetControlFrameHeaderSize());
2963 // Tack on CONTINUATION frames for the overflow.
2964 while (bytes_remaining > 0) {
2965 size_t bytes_to_write = std::min(
2966 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize());
2967 // Write CONTINUATION frame prefix.
2968 if (bytes_remaining == bytes_to_write) {
2969 flags |= end_flag;
2971 builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
2972 // Write payload fragment.
2973 builder->WriteBytes(
2974 &hpack_encoding[hpack_encoding.size() - bytes_remaining],
2975 bytes_to_write);
2976 bytes_remaining -= bytes_to_write;
2980 // The following compression setting are based on Brian Olson's analysis. See
2981 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2982 // for more details.
2983 #if defined(USE_SYSTEM_ZLIB)
2984 // System zlib is not expected to have workaround for http://crbug.com/139744,
2985 // so disable compression in that case.
2986 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2987 static const int kCompressorLevel = 0;
2988 #else // !defined(USE_SYSTEM_ZLIB)
2989 static const int kCompressorLevel = 9;
2990 #endif // !defined(USE_SYSTEM_ZLIB)
2991 static const int kCompressorWindowSizeInBits = 11;
2992 static const int kCompressorMemLevel = 1;
2994 z_stream* SpdyFramer::GetHeaderCompressor() {
2995 if (header_compressor_.get()) {
2996 return header_compressor_.get(); // Already initialized.
2999 header_compressor_.reset(new z_stream);
3000 memset(header_compressor_.get(), 0, sizeof(z_stream));
3002 int success = deflateInit2(header_compressor_.get(),
3003 kCompressorLevel,
3004 Z_DEFLATED,
3005 kCompressorWindowSizeInBits,
3006 kCompressorMemLevel,
3007 Z_DEFAULT_STRATEGY);
3008 if (success == Z_OK) {
3009 const char* dictionary = (protocol_version() <= SPDY2) ?
3010 kV2Dictionary : kV3Dictionary;
3011 const int dictionary_size = (protocol_version() <= SPDY2) ?
3012 kV2DictionarySize : kV3DictionarySize;
3013 success = deflateSetDictionary(header_compressor_.get(),
3014 reinterpret_cast<const Bytef*>(dictionary),
3015 dictionary_size);
3017 if (success != Z_OK) {
3018 LOG(WARNING) << "deflateSetDictionary failure: " << success;
3019 header_compressor_.reset(NULL);
3020 return NULL;
3022 return header_compressor_.get();
3025 z_stream* SpdyFramer::GetHeaderDecompressor() {
3026 if (header_decompressor_.get()) {
3027 return header_decompressor_.get(); // Already initialized.
3030 header_decompressor_.reset(new z_stream);
3031 memset(header_decompressor_.get(), 0, sizeof(z_stream));
3033 int success = inflateInit(header_decompressor_.get());
3034 if (success != Z_OK) {
3035 LOG(WARNING) << "inflateInit failure: " << success;
3036 header_decompressor_.reset(NULL);
3037 return NULL;
3039 return header_decompressor_.get();
3042 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3043 DCHECK_LT(SPDY3, protocol_version());
3044 if (hpack_encoder_.get() == nullptr) {
3045 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3047 return hpack_encoder_.get();
3050 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3051 DCHECK_LT(SPDY3, protocol_version());
3052 if (hpack_decoder_.get() == nullptr) {
3053 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3055 return hpack_decoder_.get();
3058 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3059 const float kSteps = 255.9f / 7.f;
3060 return static_cast<uint8>(kSteps * (7.f - priority));
3063 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3064 const float kSteps = 255.9f / 7.f;
3065 return static_cast<SpdyPriority>(7.f - weight / kSteps);
3068 // Incrementally decompress the control frame's header block, feeding the
3069 // result to the visitor in chunks. Continue this until the visitor
3070 // indicates that it cannot process any more data, or (more commonly) we
3071 // run out of data to deliver.
3072 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3073 SpdyStreamId stream_id,
3074 const char* data,
3075 size_t len) {
3076 // Get a decompressor or set error.
3077 z_stream* decomp = GetHeaderDecompressor();
3078 if (decomp == NULL) {
3079 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3080 set_error(SPDY_DECOMPRESS_FAILURE);
3081 return false;
3084 bool processed_successfully = true;
3085 char buffer[kHeaderDataChunkMaxSize];
3087 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3088 decomp->avail_in = len;
3089 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3090 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3091 // reached this method successfully, stream_id should be nonzero.
3092 DCHECK_LT(0u, stream_id);
3093 while (decomp->avail_in > 0 && processed_successfully) {
3094 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3095 decomp->avail_out = arraysize(buffer);
3097 int rv = inflate(decomp, Z_SYNC_FLUSH);
3098 if (rv == Z_NEED_DICT) {
3099 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3100 : kV3Dictionary;
3101 const int dictionary_size = (protocol_version() <= SPDY2) ?
3102 kV2DictionarySize : kV3DictionarySize;
3103 const DictionaryIds& ids = g_dictionary_ids.Get();
3104 const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3105 ids.v2_dictionary_id : ids.v3_dictionary_id;
3106 // Need to try again with the right dictionary.
3107 if (decomp->adler == dictionary_id) {
3108 rv = inflateSetDictionary(decomp,
3109 reinterpret_cast<const Bytef*>(dictionary),
3110 dictionary_size);
3111 if (rv == Z_OK) {
3112 rv = inflate(decomp, Z_SYNC_FLUSH);
3117 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3118 // without producing any output. The input is consumed and
3119 // buffered internally by zlib so we can detect this condition by
3120 // checking if avail_in is 0 after the call to inflate.
3121 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3122 if ((rv == Z_OK) || input_exhausted) {
3123 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3124 if (decompressed_len > 0) {
3125 processed_successfully = visitor_->OnControlFrameHeaderData(
3126 stream_id, buffer, decompressed_len);
3128 if (!processed_successfully) {
3129 // Assume that the problem was the header block was too large for the
3130 // visitor.
3131 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3133 } else {
3134 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3135 set_error(SPDY_DECOMPRESS_FAILURE);
3136 processed_successfully = false;
3139 return processed_successfully;
3142 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3143 SpdyStreamId stream_id, const char* data, size_t len) {
3144 bool read_successfully = true;
3145 while (read_successfully && len > 0) {
3146 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3147 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3148 bytes_to_deliver);
3149 data += bytes_to_deliver;
3150 len -= bytes_to_deliver;
3151 if (!read_successfully) {
3152 // Assume that the problem was the header block was too large for the
3153 // visitor.
3154 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3157 return read_successfully;
3160 void SpdyFramer::UpdateHeaderTableSizeSetting(uint32 value) {
3161 header_table_size_bound_ = value;
3162 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value);
3163 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value);
3166 // Return size bound of the header compression table.
3167 size_t SpdyFramer::header_table_size_bound() const {
3168 return header_table_size_bound_;
3171 void SpdyFramer::SerializeHeaderBlockWithoutCompression(
3172 SpdyFrameBuilder* builder,
3173 const SpdyHeaderBlock& header_block) const {
3174 // Serialize number of headers.
3175 if (protocol_version() <= SPDY2) {
3176 builder->WriteUInt16(static_cast<uint16>(header_block.size()));
3177 } else {
3178 builder->WriteUInt32(header_block.size());
3181 // Serialize each header.
3182 for (const auto& header : header_block) {
3183 if (protocol_version() <= SPDY2) {
3184 builder->WriteStringPiece16(header.first);
3185 builder->WriteStringPiece16(header.second);
3186 } else {
3187 builder->WriteStringPiece32(header.first);
3188 builder->WriteStringPiece32(header.second);
3193 void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder,
3194 const SpdyFrameWithHeaderBlockIR& frame) {
3195 CHECK_GE(SPDY3, protocol_version());
3196 if (!enable_compression_) {
3197 return SerializeHeaderBlockWithoutCompression(builder,
3198 frame.header_block());
3201 // First build an uncompressed version to be fed into the compressor.
3202 const size_t uncompressed_len =
3203 GetSerializedLength(protocol_version(), &(frame.header_block()));
3204 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3205 SerializeHeaderBlockWithoutCompression(&uncompressed_builder,
3206 frame.header_block());
3207 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3209 z_stream* compressor = GetHeaderCompressor();
3210 if (!compressor) {
3211 LOG(DFATAL) << "Could not obtain compressor.";
3212 return;
3214 // Create an output frame.
3215 // Since we'll be performing lots of flushes when compressing the data,
3216 // zlib's lower bounds may be insufficient.
3218 // TODO(akalin): Avoid the duplicate calculation with
3219 // GetSerializedLength(const SpdyHeaderBlock&).
3220 const int compressed_max_size =
3221 2 * deflateBound(compressor, uncompressed_len);
3223 // TODO(phajdan.jr): Clean up after we no longer need
3224 // to workaround http://crbug.com/139744.
3225 #if defined(USE_SYSTEM_ZLIB)
3226 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3227 compressor->avail_in = uncompressed_len;
3228 #endif // defined(USE_SYSTEM_ZLIB)
3229 compressor->next_out = reinterpret_cast<Bytef*>(
3230 builder->GetWritableBuffer(compressed_max_size));
3231 compressor->avail_out = compressed_max_size;
3233 // TODO(phajdan.jr): Clean up after we no longer need
3234 // to workaround http://crbug.com/139744.
3235 #if defined(USE_SYSTEM_ZLIB)
3236 int rv = deflate(compressor, Z_SYNC_FLUSH);
3237 if (rv != Z_OK) { // How can we know that it compressed everything?
3238 // This shouldn't happen, right?
3239 LOG(WARNING) << "deflate failure: " << rv;
3240 // TODO(akalin): Upstream this return.
3241 return;
3243 #else
3244 WriteHeaderBlockToZ(&frame.header_block(), compressor);
3245 #endif // defined(USE_SYSTEM_ZLIB)
3247 int compressed_size = compressed_max_size - compressor->avail_out;
3248 builder->Seek(compressed_size);
3249 builder->RewriteLength(*this);
3252 } // namespace net