Move StartsWith[ASCII] to base namespace.
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blob44e919746acd91668ccbe8024db1a2b42288083c
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 <algorithm>
8 #include <limits>
9 #include <string>
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/third_party/valgrind/memcheck.h"
14 #include "net/spdy/spdy_frame_builder.h"
15 #include "net/spdy/spdy_frame_reader.h"
16 #include "net/spdy/spdy_bitmasks.h"
17 #include "third_party/zlib/zlib.h"
19 using base::StringPiece;
20 using std::string;
21 using std::vector;
23 namespace net {
25 namespace {
27 // Compute the id of our dictionary so that we know we're using the
28 // right one when asked for it.
29 uLong CalculateDictionaryId(const char* dictionary,
30 const size_t dictionary_size) {
31 uLong initial_value = adler32(0L, Z_NULL, 0);
32 return adler32(initial_value,
33 reinterpret_cast<const Bytef*>(dictionary),
34 dictionary_size);
37 // Check to see if the name and value of a cookie are both empty.
38 bool IsCookieEmpty(const base::StringPiece& cookie) {
39 if (cookie.size() == 0) {
40 return true;
42 size_t pos = cookie.find('=');
43 if (pos == base::StringPiece::npos) {
44 return false;
46 // Ignore leading whitespaces of cookie value.
47 size_t value_start = pos + 1;
48 for (; value_start < cookie.size(); value_start++) {
49 if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) {
50 break;
53 return (pos == 0) && ((cookie.size() - value_start) == 0);
56 struct DictionaryIds {
57 DictionaryIds()
58 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
59 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
61 const uLong v2_dictionary_id;
62 const uLong v3_dictionary_id;
65 // Adler ID for the SPDY header compressor dictionaries. Note that they are
66 // initialized lazily to avoid static initializers.
67 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
69 // Used to indicate no flags in a SPDY flags field.
70 const uint8 kNoFlags = 0;
72 // Wire sizes of priority payloads.
73 const size_t kPriorityDependencyPayloadSize = 4;
74 const size_t kPriorityWeightPayloadSize = 1;
76 // Wire size of pad length field.
77 const size_t kPadLengthFieldSize = 1;
79 } // namespace
81 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
82 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
83 // We fragment sent control frames at smaller payload boundaries.
84 const size_t SpdyFramer::kMaxControlFrameSize = 1024;
85 // The size of the control frame buffer. Must be >= the minimum size of the
86 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
87 // calculation details.
88 const size_t SpdyFramer::kControlFrameBufferSize = 19;
90 #ifdef DEBUG_SPDY_STATE_CHANGES
91 #define CHANGE_STATE(newstate) \
92 do { \
93 DVLOG(1) << "Changing state from: " \
94 << StateToString(state_) \
95 << " to " << StateToString(newstate) << "\n"; \
96 DCHECK(state_ != SPDY_ERROR); \
97 DCHECK_EQ(previous_state_, state_); \
98 previous_state_ = state_; \
99 state_ = newstate; \
100 } while (false)
101 #else
102 #define CHANGE_STATE(newstate) \
103 do { \
104 DCHECK(state_ != SPDY_ERROR); \
105 DCHECK_EQ(previous_state_, state_); \
106 previous_state_ = state_; \
107 state_ = newstate; \
108 } while (false)
109 #endif
111 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
112 SpdyMajorVersion version, uint32 wire) {
113 if (version < SPDY3) {
114 ConvertFlagsAndIdForSpdy2(&wire);
116 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
119 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
120 : flags_(flags), id_(id & 0x00ffffff) {
121 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
124 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
125 const {
126 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
127 if (version < SPDY3) {
128 ConvertFlagsAndIdForSpdy2(&wire);
130 return wire;
133 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
134 // This method is used to preserve buggy behavior and works on both
135 // little-endian and big-endian hosts.
136 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
137 // as well as vice versa).
138 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
139 uint8* wire_array = reinterpret_cast<uint8*>(val);
140 std::swap(wire_array[0], wire_array[3]);
141 std::swap(wire_array[1], wire_array[2]);
144 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
145 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
147 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
148 size_t len) {
149 return true;
152 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
153 const char* rst_stream_data,
154 size_t len) {
155 return true;
158 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
159 : current_frame_buffer_(new char[kControlFrameBufferSize]),
160 expect_continuation_(0),
161 visitor_(NULL),
162 debug_visitor_(NULL),
163 display_protocol_("SPDY"),
164 protocol_version_(version),
165 enable_compression_(true),
166 syn_frame_processed_(false),
167 probable_http_response_(false),
168 end_stream_when_done_(false),
169 header_table_size_bound_(4096) {
170 DCHECK_GE(protocol_version_, SPDY_MIN_VERSION);
171 DCHECK_LE(protocol_version_, SPDY_MAX_VERSION);
172 DCHECK_LE(kMaxControlFrameSize,
173 SpdyConstants::GetFrameMaximumSize(protocol_version_) +
174 SpdyConstants::GetControlFrameHeaderSize(protocol_version_));
175 Reset();
178 SpdyFramer::~SpdyFramer() {
179 if (header_compressor_.get()) {
180 deflateEnd(header_compressor_.get());
182 if (header_decompressor_.get()) {
183 inflateEnd(header_decompressor_.get());
187 void SpdyFramer::Reset() {
188 state_ = SPDY_RESET;
189 previous_state_ = SPDY_RESET;
190 error_code_ = SPDY_NO_ERROR;
191 remaining_data_length_ = 0;
192 remaining_control_header_ = 0;
193 current_frame_buffer_length_ = 0;
194 current_frame_type_ = DATA;
195 current_frame_flags_ = 0;
196 current_frame_length_ = 0;
197 current_frame_stream_id_ = kInvalidStream;
198 settings_scratch_.Reset();
199 altsvc_scratch_.Reset();
200 remaining_padding_payload_length_ = 0;
203 size_t SpdyFramer::GetDataFrameMinimumSize() const {
204 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
207 // Size, in bytes, of the control frame header.
208 size_t SpdyFramer::GetControlFrameHeaderSize() const {
209 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
212 size_t SpdyFramer::GetSynStreamMinimumSize() const {
213 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
214 // name-value block.
215 if (protocol_version() <= SPDY3) {
216 // Calculated as:
217 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
218 // + 1 (unused, was credential slot)
219 return GetControlFrameHeaderSize() + 10;
220 } else {
221 return GetControlFrameHeaderSize() +
222 kPriorityDependencyPayloadSize +
223 kPriorityWeightPayloadSize;
227 size_t SpdyFramer::GetSynReplyMinimumSize() const {
228 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
229 // name-value block.
230 size_t size = GetControlFrameHeaderSize();
231 if (protocol_version() <= SPDY3) {
232 // Calculated as:
233 // control frame header + 4 (stream IDs)
234 size += 4;
237 // In SPDY 2, there were 2 unused bytes before payload.
238 if (protocol_version() < SPDY3) {
239 size += 2;
242 return size;
245 size_t SpdyFramer::GetRstStreamMinimumSize() const {
246 // Size, in bytes, of a RST_STREAM frame.
247 if (protocol_version() <= SPDY3) {
248 // Calculated as:
249 // control frame header + 4 (stream id) + 4 (status code)
250 return GetControlFrameHeaderSize() + 8;
251 } else {
252 // Calculated as:
253 // frame prefix + 4 (status code)
254 return GetControlFrameHeaderSize() + 4;
258 size_t SpdyFramer::GetSettingsMinimumSize() const {
259 // Size, in bytes, of a SETTINGS frame not including the IDs and values
260 // from the variable-length value block. Calculated as:
261 // control frame header + 4 (number of ID/value pairs)
262 if (protocol_version() <= SPDY3) {
263 return GetControlFrameHeaderSize() + 4;
264 } else {
265 return GetControlFrameHeaderSize();
269 size_t SpdyFramer::GetPingSize() const {
270 // Size, in bytes, of this PING frame.
271 if (protocol_version() <= SPDY3) {
272 // Calculated as:
273 // control frame header + 4 (id)
274 return GetControlFrameHeaderSize() + 4;
275 } else {
276 // Calculated as:
277 // control frame header + 8 (id)
278 return GetControlFrameHeaderSize() + 8;
282 size_t SpdyFramer::GetGoAwayMinimumSize() const {
283 // Size, in bytes, of this GOAWAY frame. Calculated as:
284 // 1. Control frame header size
285 size_t size = GetControlFrameHeaderSize();
287 // 2. Last good stream id (4 bytes)
288 size += 4;
290 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
291 if (protocol_version() >= SPDY3) {
292 size += 4;
295 return size;
298 size_t SpdyFramer::GetHeadersMinimumSize() const {
299 // Size, in bytes, of a HEADERS frame not including the variable-length
300 // name-value block.
301 size_t size = GetControlFrameHeaderSize();
302 if (protocol_version() <= SPDY3) {
303 // Calculated as:
304 // control frame header + 4 (stream IDs)
305 size += 4;
308 // In SPDY 2, there were 2 unused bytes before payload.
309 if (protocol_version() <= SPDY2) {
310 size += 2;
313 return size;
316 size_t SpdyFramer::GetWindowUpdateSize() const {
317 // Size, in bytes, of a WINDOW_UPDATE frame.
318 if (protocol_version() <= SPDY3) {
319 // Calculated as:
320 // control frame header + 4 (stream id) + 4 (delta)
321 return GetControlFrameHeaderSize() + 8;
322 } else {
323 // Calculated as:
324 // frame prefix + 4 (delta)
325 return GetControlFrameHeaderSize() + 4;
329 size_t SpdyFramer::GetBlockedSize() const {
330 DCHECK_LT(SPDY3, protocol_version());
331 // Size, in bytes, of a BLOCKED frame.
332 // The BLOCKED frame has no payload beyond the control frame header.
333 return GetControlFrameHeaderSize();
336 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
337 DCHECK_LT(SPDY3, protocol_version());
338 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
339 // Calculated as frame prefix + 4 (promised stream id).
340 return GetControlFrameHeaderSize() + 4;
343 size_t SpdyFramer::GetContinuationMinimumSize() const {
344 // Size, in bytes, of a CONTINUATION frame not including the variable-length
345 // headers fragments.
346 return GetControlFrameHeaderSize();
349 size_t SpdyFramer::GetAltSvcMinimumSize() const {
350 // Size, in bytes, of an ALTSVC frame not including the Field-Value and
351 // (optional) Origin fields, both of which can vary in length. Note that this
352 // gives a lower bound on the frame size rather than a true minimum; the
353 // actual frame should always be larger than this.
354 // Calculated as frame prefix + 2 (origin_len).
355 return GetControlFrameHeaderSize() + 2;
358 size_t SpdyFramer::GetPrioritySize() const {
359 // Size, in bytes, of a PRIORITY frame.
360 return GetControlFrameHeaderSize() +
361 kPriorityDependencyPayloadSize +
362 kPriorityWeightPayloadSize;
365 size_t SpdyFramer::GetFrameMinimumSize() const {
366 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
369 size_t SpdyFramer::GetFrameMaximumSize() const {
370 return SpdyConstants::GetFrameMaximumSize(protocol_version());
373 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
374 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
377 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
378 return SpdyConstants::GetPrefixLength(type, protocol_version());
381 const char* SpdyFramer::StateToString(int state) {
382 switch (state) {
383 case SPDY_ERROR:
384 return "ERROR";
385 case SPDY_AUTO_RESET:
386 return "AUTO_RESET";
387 case SPDY_RESET:
388 return "RESET";
389 case SPDY_READING_COMMON_HEADER:
390 return "READING_COMMON_HEADER";
391 case SPDY_CONTROL_FRAME_PAYLOAD:
392 return "CONTROL_FRAME_PAYLOAD";
393 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
394 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
395 case SPDY_CONSUME_PADDING:
396 return "SPDY_CONSUME_PADDING";
397 case SPDY_IGNORE_REMAINING_PAYLOAD:
398 return "IGNORE_REMAINING_PAYLOAD";
399 case SPDY_FORWARD_STREAM_FRAME:
400 return "FORWARD_STREAM_FRAME";
401 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
402 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
403 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
404 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
405 case SPDY_GOAWAY_FRAME_PAYLOAD:
406 return "SPDY_GOAWAY_FRAME_PAYLOAD";
407 case SPDY_RST_STREAM_FRAME_PAYLOAD:
408 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
409 case SPDY_SETTINGS_FRAME_PAYLOAD:
410 return "SPDY_SETTINGS_FRAME_PAYLOAD";
411 case SPDY_ALTSVC_FRAME_PAYLOAD:
412 return "SPDY_ALTSVC_FRAME_PAYLOAD";
414 return "UNKNOWN_STATE";
417 void SpdyFramer::set_error(SpdyError error) {
418 DCHECK(visitor_);
419 error_code_ = error;
420 // These values will usually get reset once we come to the end
421 // of a header block, but if we run into an error that
422 // might not happen, so reset them here.
423 expect_continuation_ = 0;
424 end_stream_when_done_ = false;
426 CHANGE_STATE(SPDY_ERROR);
427 visitor_->OnError(this);
430 const char* SpdyFramer::ErrorCodeToString(int error_code) {
431 switch (error_code) {
432 case SPDY_NO_ERROR:
433 return "NO_ERROR";
434 case SPDY_INVALID_CONTROL_FRAME:
435 return "INVALID_CONTROL_FRAME";
436 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
437 return "CONTROL_PAYLOAD_TOO_LARGE";
438 case SPDY_ZLIB_INIT_FAILURE:
439 return "ZLIB_INIT_FAILURE";
440 case SPDY_UNSUPPORTED_VERSION:
441 return "UNSUPPORTED_VERSION";
442 case SPDY_DECOMPRESS_FAILURE:
443 return "DECOMPRESS_FAILURE";
444 case SPDY_COMPRESS_FAILURE:
445 return "COMPRESS_FAILURE";
446 case SPDY_INVALID_DATA_FRAME_FLAGS:
447 return "SPDY_INVALID_DATA_FRAME_FLAGS";
448 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
449 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
450 case SPDY_UNEXPECTED_FRAME:
451 return "UNEXPECTED_FRAME";
453 return "UNKNOWN_ERROR";
456 const char* SpdyFramer::StatusCodeToString(int status_code) {
457 switch (status_code) {
458 case RST_STREAM_INVALID:
459 return "INVALID";
460 case RST_STREAM_PROTOCOL_ERROR:
461 return "PROTOCOL_ERROR";
462 case RST_STREAM_INVALID_STREAM:
463 return "INVALID_STREAM";
464 case RST_STREAM_REFUSED_STREAM:
465 return "REFUSED_STREAM";
466 case RST_STREAM_UNSUPPORTED_VERSION:
467 return "UNSUPPORTED_VERSION";
468 case RST_STREAM_CANCEL:
469 return "CANCEL";
470 case RST_STREAM_INTERNAL_ERROR:
471 return "INTERNAL_ERROR";
472 case RST_STREAM_FLOW_CONTROL_ERROR:
473 return "FLOW_CONTROL_ERROR";
474 case RST_STREAM_STREAM_IN_USE:
475 return "STREAM_IN_USE";
476 case RST_STREAM_STREAM_ALREADY_CLOSED:
477 return "STREAM_ALREADY_CLOSED";
478 case RST_STREAM_INVALID_CREDENTIALS:
479 return "INVALID_CREDENTIALS";
480 case RST_STREAM_FRAME_TOO_LARGE:
481 return "FRAME_TOO_LARGE";
482 case RST_STREAM_CONNECT_ERROR:
483 return "CONNECT_ERROR";
484 case RST_STREAM_ENHANCE_YOUR_CALM:
485 return "ENHANCE_YOUR_CALM";
486 case RST_STREAM_INADEQUATE_SECURITY:
487 return "INADEQUATE_SECURITY";
488 case RST_STREAM_HTTP_1_1_REQUIRED:
489 return "HTTP_1_1_REQUIRED";
491 return "UNKNOWN_STATUS";
494 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
495 switch (type) {
496 case DATA:
497 return "DATA";
498 case SYN_STREAM:
499 return "SYN_STREAM";
500 case SYN_REPLY:
501 return "SYN_REPLY";
502 case RST_STREAM:
503 return "RST_STREAM";
504 case SETTINGS:
505 return "SETTINGS";
506 case PING:
507 return "PING";
508 case GOAWAY:
509 return "GOAWAY";
510 case HEADERS:
511 return "HEADERS";
512 case WINDOW_UPDATE:
513 return "WINDOW_UPDATE";
514 case CREDENTIAL:
515 return "CREDENTIAL";
516 case PUSH_PROMISE:
517 return "PUSH_PROMISE";
518 case CONTINUATION:
519 return "CONTINUATION";
520 case PRIORITY:
521 return "PRIORITY";
522 case ALTSVC:
523 return "ALTSVC";
524 case BLOCKED:
525 return "BLOCKED";
527 return "UNKNOWN_CONTROL_TYPE";
530 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
531 DCHECK(visitor_);
532 DCHECK(data);
534 size_t original_len = len;
535 do {
536 previous_state_ = state_;
537 switch (state_) {
538 case SPDY_ERROR:
539 goto bottom;
541 case SPDY_AUTO_RESET:
542 case SPDY_RESET:
543 Reset();
544 if (len > 0) {
545 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
547 break;
549 case SPDY_READING_COMMON_HEADER: {
550 size_t bytes_read = ProcessCommonHeader(data, len);
551 len -= bytes_read;
552 data += bytes_read;
553 break;
556 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
557 // Control frames that contain header blocks
558 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
559 // take a different path through the state machine - they
560 // will go:
561 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
562 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
564 // SETTINGS frames take a slightly modified route:
565 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
566 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
568 // All other control frames will use the alternate route directly to
569 // SPDY_CONTROL_FRAME_PAYLOAD
570 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
571 len -= bytes_read;
572 data += bytes_read;
573 break;
576 case SPDY_SETTINGS_FRAME_PAYLOAD: {
577 int bytes_read = ProcessSettingsFramePayload(data, len);
578 len -= bytes_read;
579 data += bytes_read;
580 break;
583 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
584 int bytes_read = ProcessControlFrameHeaderBlock(
585 data, len, protocol_version() > SPDY3);
586 len -= bytes_read;
587 data += bytes_read;
588 break;
591 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
592 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
593 len -= bytes_read;
594 data += bytes_read;
595 break;
598 case SPDY_GOAWAY_FRAME_PAYLOAD: {
599 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
600 len -= bytes_read;
601 data += bytes_read;
602 break;
605 case SPDY_ALTSVC_FRAME_PAYLOAD: {
606 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
607 len -= bytes_read;
608 data += bytes_read;
609 break;
612 case SPDY_CONTROL_FRAME_PAYLOAD: {
613 size_t bytes_read = ProcessControlFramePayload(data, len);
614 len -= bytes_read;
615 data += bytes_read;
616 break;
619 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: {
620 size_t bytes_read = ProcessDataFramePaddingLength(data, len);
621 len -= bytes_read;
622 data += bytes_read;
623 break;
626 case SPDY_CONSUME_PADDING: {
627 size_t bytes_read = ProcessFramePadding(data, len);
628 len -= bytes_read;
629 data += bytes_read;
630 break;
633 case SPDY_IGNORE_REMAINING_PAYLOAD: {
634 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
635 len -= bytes_read;
636 data += bytes_read;
637 break;
640 case SPDY_FORWARD_STREAM_FRAME: {
641 size_t bytes_read = ProcessDataFramePayload(data, len);
642 len -= bytes_read;
643 data += bytes_read;
644 break;
647 default:
648 LOG(DFATAL) << "Invalid value for " << display_protocol_
649 << " framer state: " << state_;
650 // This ensures that we don't infinite-loop if state_ gets an
651 // invalid value somehow, such as due to a SpdyFramer getting deleted
652 // from a callback it calls.
653 goto bottom;
655 } while (state_ != previous_state_);
656 bottom:
657 DCHECK(len == 0 || state_ == SPDY_ERROR);
658 if (current_frame_buffer_length_ == 0 &&
659 remaining_data_length_ == 0 &&
660 remaining_control_header_ == 0) {
661 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
662 << "State: " << StateToString(state_);
665 return original_len - len;
668 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
669 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
670 // state.
671 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
673 size_t original_len = len;
675 // Update current frame buffer as needed.
676 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
677 size_t bytes_desired =
678 GetControlFrameHeaderSize() - current_frame_buffer_length_;
679 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
682 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
683 // Not enough information to do anything meaningful.
684 return original_len - len;
687 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
688 // when processing DATA frames below.
689 scoped_ptr<SpdyFrameReader> reader(
690 new SpdyFrameReader(current_frame_buffer_.get(),
691 current_frame_buffer_length_));
693 bool is_control_frame = false;
695 int control_frame_type_field =
696 SpdyConstants::DataFrameType(protocol_version());
697 // ProcessControlFrameHeader() will set current_frame_type_ to the
698 // correct value if this is a valid control frame.
699 current_frame_type_ = DATA;
700 if (protocol_version() <= SPDY3) {
701 uint16 version = 0;
702 bool successful_read = reader->ReadUInt16(&version);
703 DCHECK(successful_read);
704 is_control_frame = (version & kControlFlagMask) != 0;
705 version &= ~kControlFlagMask; // Only valid for control frames.
706 if (is_control_frame) {
707 // We check version before we check validity: version can never be
708 // 'invalid', it can only be unsupported.
709 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
710 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
711 SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
712 // Version does not match the version the framer was initialized with.
713 DVLOG(1) << "Unsupported SPDY version "
714 << version
715 << " (expected " << protocol_version() << ")";
716 set_error(SPDY_UNSUPPORTED_VERSION);
717 return 0;
719 // We check control_frame_type_field's validity in
720 // ProcessControlFrameHeader().
721 uint16 control_frame_type_field_uint16;
722 successful_read = reader->ReadUInt16(&control_frame_type_field_uint16);
723 control_frame_type_field = control_frame_type_field_uint16;
724 } else {
725 reader->Rewind();
726 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
728 DCHECK(successful_read);
730 successful_read = reader->ReadUInt8(&current_frame_flags_);
731 DCHECK(successful_read);
733 uint32 length_field = 0;
734 successful_read = reader->ReadUInt24(&length_field);
735 DCHECK(successful_read);
736 remaining_data_length_ = length_field;
737 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
738 } else {
739 uint32 length_field = 0;
740 bool successful_read = reader->ReadUInt24(&length_field);
741 DCHECK(successful_read);
743 uint8 control_frame_type_field_uint8;
744 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
745 DCHECK(successful_read);
746 // We check control_frame_type_field's validity in
747 // ProcessControlFrameHeader().
748 control_frame_type_field = control_frame_type_field_uint8;
749 is_control_frame = control_frame_type_field !=
750 SpdyConstants::SerializeFrameType(protocol_version(), DATA);
752 if (is_control_frame) {
753 current_frame_length_ = length_field + GetControlFrameHeaderSize();
754 } else {
755 current_frame_length_ = length_field + GetDataFrameMinimumSize();
758 successful_read = reader->ReadUInt8(&current_frame_flags_);
759 DCHECK(successful_read);
761 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
762 DCHECK(successful_read);
764 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
766 // Before we accept a DATA frame, we need to make sure we're not in the
767 // middle of processing a header block.
768 const bool is_continuation_frame = (control_frame_type_field ==
769 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
770 if ((expect_continuation_ != 0) != is_continuation_frame) {
771 if (expect_continuation_ != 0) {
772 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
773 << "frame, but instead received frame type "
774 << control_frame_type_field;
775 } else {
776 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
778 set_error(SPDY_UNEXPECTED_FRAME);
779 return original_len - len;
782 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
783 : GetDataFrameMinimumSize(),
784 reader->GetBytesConsumed());
785 DCHECK_EQ(current_frame_length_,
786 remaining_data_length_ + reader->GetBytesConsumed());
788 // This is just a sanity check for help debugging early frame errors.
789 if (remaining_data_length_ > 1000000u) {
790 // The strncmp for 5 is safe because we only hit this point if we
791 // have kMinCommonHeader (8) bytes
792 if (!syn_frame_processed_ &&
793 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
794 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
795 << " request";
796 probable_http_response_ = true;
797 } else {
798 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
799 << " session is likely corrupt.";
803 // if we're here, then we have the common header all received.
804 if (!is_control_frame) {
805 if (protocol_version() > SPDY3) {
806 // Catch bogus tests sending oversized DATA frames.
807 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
808 << "DATA frame too large for SPDY >= 4.";
811 uint8 valid_data_flags = 0;
812 if (protocol_version() > SPDY3) {
813 valid_data_flags =
814 DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
815 } else {
816 valid_data_flags = DATA_FLAG_FIN;
819 if (current_frame_flags_ & ~valid_data_flags) {
820 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
821 } else {
822 visitor_->OnDataFrameHeader(current_frame_stream_id_,
823 remaining_data_length_,
824 current_frame_flags_ & DATA_FLAG_FIN);
825 if (remaining_data_length_ > 0) {
826 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH);
827 } else {
828 // Empty data frame.
829 if (current_frame_flags_ & DATA_FLAG_FIN) {
830 visitor_->OnStreamFrameData(
831 current_frame_stream_id_, NULL, 0, true);
833 CHANGE_STATE(SPDY_AUTO_RESET);
836 } else {
837 ProcessControlFrameHeader(control_frame_type_field);
840 return original_len - len;
843 void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
844 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
845 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
847 // TODO(mlavan): Either remove credential frames from the code entirely,
848 // or add them to parsing + serialization methods for SPDY3.
849 // Early detection of deprecated frames that we ignore.
850 if (protocol_version() <= SPDY3) {
851 if (control_frame_type_field == CREDENTIAL) {
852 current_frame_type_ = CREDENTIAL;
853 DCHECK_EQ(SPDY3, protocol_version());
854 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
855 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
856 return;
860 if (!SpdyConstants::IsValidFrameType(protocol_version(),
861 control_frame_type_field)) {
862 if (protocol_version() <= SPDY3) {
863 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
864 << " (protocol version: " << protocol_version() << ")";
865 set_error(SPDY_INVALID_CONTROL_FRAME);
866 return;
867 } else {
868 // In HTTP2 we ignore unknown frame types for extensibility, as long as
869 // the rest of the control frame header is valid.
870 // We rely on the visitor to check validity of current_frame_stream_id_.
871 bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_,
872 control_frame_type_field);
873 if (valid_stream) {
874 DVLOG(1) << "Ignoring unknown frame type.";
875 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
876 } else {
877 // Report an invalid frame error and close the stream if the
878 // stream_id is not valid.
879 DLOG(WARNING) << "Unknown control frame type "
880 << control_frame_type_field
881 << " received on invalid stream "
882 << current_frame_stream_id_;
883 set_error(SPDY_INVALID_CONTROL_FRAME);
885 return;
889 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
890 control_frame_type_field);
892 // Do some sanity checking on the control frame sizes and flags.
893 switch (current_frame_type_) {
894 case SYN_STREAM:
895 if (current_frame_length_ < GetSynStreamMinimumSize()) {
896 set_error(SPDY_INVALID_CONTROL_FRAME);
897 } else if (current_frame_flags_ &
898 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
899 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
901 break;
902 case SYN_REPLY:
903 if (current_frame_length_ < GetSynReplyMinimumSize()) {
904 set_error(SPDY_INVALID_CONTROL_FRAME);
905 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
906 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
908 break;
909 case RST_STREAM:
910 // For SPDY versions < 4, the header has a fixed length.
911 // For SPDY version 4 and up, the RST_STREAM frame may include optional
912 // opaque data, so we only have a lower limit on the frame size.
913 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
914 protocol_version() <= SPDY3) ||
915 (current_frame_length_ < GetRstStreamMinimumSize() &&
916 protocol_version() > SPDY3)) {
917 set_error(SPDY_INVALID_CONTROL_FRAME);
918 } else if (current_frame_flags_ != 0) {
919 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
921 break;
922 case SETTINGS:
924 // Make sure that we have an integral number of 8-byte key/value pairs,
925 // plus a 4-byte length field in SPDY3 and below.
926 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
927 // Size of each key/value pair in bytes.
928 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
929 if (current_frame_length_ < GetSettingsMinimumSize() ||
930 (current_frame_length_ - GetControlFrameHeaderSize())
931 % setting_size != values_prefix_size) {
932 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
933 << current_frame_length_;
934 set_error(SPDY_INVALID_CONTROL_FRAME);
935 } else if (protocol_version() <= SPDY3 &&
936 current_frame_flags_ &
937 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
938 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
939 } else if (protocol_version() > SPDY3 &&
940 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
941 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
942 } else if (protocol_version() > SPDY3 &&
943 current_frame_flags_ & SETTINGS_FLAG_ACK &&
944 current_frame_length_ > GetSettingsMinimumSize()) {
945 set_error(SPDY_INVALID_CONTROL_FRAME);
947 break;
949 case PING:
950 if (current_frame_length_ != GetPingSize()) {
951 set_error(SPDY_INVALID_CONTROL_FRAME);
952 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
953 (current_frame_flags_ & ~PING_FLAG_ACK)) {
954 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
956 break;
957 case GOAWAY:
959 // For SPDY version < 4, there are only mandatory fields and the header
960 // has a fixed length. For SPDY version >= 4, optional opaque data may
961 // be appended to the GOAWAY frame, thus there is only a minimal length
962 // restriction.
963 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
964 protocol_version() <= SPDY3) ||
965 (current_frame_length_ < GetGoAwayMinimumSize() &&
966 protocol_version() > SPDY3)) {
967 set_error(SPDY_INVALID_CONTROL_FRAME);
968 } else if (current_frame_flags_ != 0) {
969 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
971 break;
973 case HEADERS:
975 size_t min_size = GetHeadersMinimumSize();
976 if (protocol_version() > SPDY3 &&
977 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
978 min_size += 4;
980 if (current_frame_length_ < min_size) {
981 // TODO(mlavan): check here for HEADERS with no payload?
982 // (not allowed in SPDY4)
983 set_error(SPDY_INVALID_CONTROL_FRAME);
984 } else if (protocol_version() <= SPDY3 &&
985 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
986 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
987 } else if (protocol_version() > SPDY3 &&
988 current_frame_flags_ &
989 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
990 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
991 HEADERS_FLAG_PADDED)) {
992 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
995 break;
996 case WINDOW_UPDATE:
997 if (current_frame_length_ != GetWindowUpdateSize()) {
998 set_error(SPDY_INVALID_CONTROL_FRAME);
999 } else if (current_frame_flags_ != 0) {
1000 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1002 break;
1003 case BLOCKED:
1004 if (current_frame_length_ != GetBlockedSize() ||
1005 protocol_version() <= SPDY3) {
1006 set_error(SPDY_INVALID_CONTROL_FRAME);
1007 } else if (current_frame_flags_ != 0) {
1008 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1010 break;
1011 case PUSH_PROMISE:
1012 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
1013 set_error(SPDY_INVALID_CONTROL_FRAME);
1014 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
1015 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1016 } else if (protocol_version() > SPDY3 &&
1017 current_frame_flags_ &
1018 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
1019 HEADERS_FLAG_PADDED)) {
1020 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1022 break;
1023 case CONTINUATION:
1024 if (current_frame_length_ < GetContinuationMinimumSize() ||
1025 protocol_version() <= SPDY3) {
1026 set_error(SPDY_INVALID_CONTROL_FRAME);
1027 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
1028 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1030 break;
1031 case ALTSVC:
1032 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
1033 set_error(SPDY_INVALID_CONTROL_FRAME);
1034 } else if (current_frame_flags_ != 0) {
1035 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1037 break;
1038 case PRIORITY:
1039 if (current_frame_length_ != GetPrioritySize() ||
1040 protocol_version() <= SPDY3) {
1041 set_error(SPDY_INVALID_CONTROL_FRAME);
1042 } else if (current_frame_flags_ != 0) {
1043 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1045 break;
1046 default:
1047 LOG(WARNING) << "Valid " << display_protocol_
1048 << " control frame with unhandled type: "
1049 << current_frame_type_;
1050 // This branch should be unreachable because of the frame type bounds
1051 // check above. However, we DLOG(FATAL) here in an effort to painfully
1052 // club the head of the developer who failed to keep this file in sync
1053 // with spdy_protocol.h.
1054 DLOG(FATAL);
1055 set_error(SPDY_INVALID_CONTROL_FRAME);
1056 break;
1059 if (state_ == SPDY_ERROR) {
1060 return;
1063 if (current_frame_length_ >
1064 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1065 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1066 DLOG(WARNING) << "Received control frame of type " << current_frame_type_
1067 << " with way too big of a payload: "
1068 << current_frame_length_;
1069 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1070 return;
1073 if (current_frame_type_ == GOAWAY) {
1074 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1075 return;
1078 if (current_frame_type_ == RST_STREAM) {
1079 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1080 return;
1083 if (current_frame_type_ == ALTSVC) {
1084 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1085 return;
1087 // Determine the frame size without variable-length data.
1088 int32 frame_size_without_variable_data;
1089 switch (current_frame_type_) {
1090 case SYN_STREAM:
1091 syn_frame_processed_ = true;
1092 frame_size_without_variable_data = GetSynStreamMinimumSize();
1093 break;
1094 case SYN_REPLY:
1095 syn_frame_processed_ = true;
1096 frame_size_without_variable_data = GetSynReplyMinimumSize();
1097 break;
1098 case SETTINGS:
1099 frame_size_without_variable_data = GetSettingsMinimumSize();
1100 break;
1101 case HEADERS:
1102 frame_size_without_variable_data = GetHeadersMinimumSize();
1103 if (protocol_version() > SPDY3) {
1104 if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
1105 frame_size_without_variable_data += kPadLengthFieldSize;
1107 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1108 frame_size_without_variable_data +=
1109 kPriorityDependencyPayloadSize +
1110 kPriorityWeightPayloadSize;
1113 break;
1114 case PUSH_PROMISE:
1115 frame_size_without_variable_data = GetPushPromiseMinimumSize();
1116 if (protocol_version() > SPDY3 &&
1117 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1118 frame_size_without_variable_data += kPadLengthFieldSize;
1120 break;
1121 case CONTINUATION:
1122 frame_size_without_variable_data = GetContinuationMinimumSize();
1123 break;
1124 default:
1125 frame_size_without_variable_data = -1;
1126 break;
1129 if ((frame_size_without_variable_data == -1) &&
1130 (current_frame_length_ > kControlFrameBufferSize)) {
1131 // We should already be in an error state. Double-check.
1132 DCHECK_EQ(SPDY_ERROR, state_);
1133 if (state_ != SPDY_ERROR) {
1134 LOG(DFATAL) << display_protocol_
1135 << " control frame buffer too small for fixed-length frame.";
1136 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1138 return;
1141 if (frame_size_without_variable_data > 0) {
1142 // We have a control frame with a header block. We need to parse the
1143 // remainder of the control frame's header before we can parse the header
1144 // block. The start of the header block varies with the control type.
1145 DCHECK_GE(frame_size_without_variable_data,
1146 static_cast<int32>(current_frame_buffer_length_));
1147 remaining_control_header_ = frame_size_without_variable_data -
1148 current_frame_buffer_length_;
1150 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1151 return;
1154 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1157 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1158 size_t max_bytes) {
1159 size_t bytes_to_read = std::min(*len, max_bytes);
1160 if (bytes_to_read > 0) {
1161 DCHECK_GE(kControlFrameBufferSize,
1162 current_frame_buffer_length_ + bytes_to_read);
1163 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1164 *data,
1165 bytes_to_read);
1166 current_frame_buffer_length_ += bytes_to_read;
1167 *data += bytes_to_read;
1168 *len -= bytes_to_read;
1170 return bytes_to_read;
1173 size_t SpdyFramer::GetSerializedLength(
1174 const SpdyMajorVersion spdy_version,
1175 const SpdyHeaderBlock* headers) {
1176 const size_t num_name_value_pairs_size
1177 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1178 const size_t length_of_name_size = num_name_value_pairs_size;
1179 const size_t length_of_value_size = num_name_value_pairs_size;
1181 size_t total_length = num_name_value_pairs_size;
1182 for (SpdyHeaderBlock::const_iterator it = headers->begin();
1183 it != headers->end();
1184 ++it) {
1185 // We add space for the length of the name and the length of the value as
1186 // well as the length of the name and the length of the value.
1187 total_length += length_of_name_size + it->first.size() +
1188 length_of_value_size + it->second.size();
1190 return total_length;
1193 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1194 const SpdyMajorVersion spdy_version,
1195 const SpdyHeaderBlock* headers) {
1196 if (spdy_version < SPDY3) {
1197 frame->WriteUInt16(static_cast<uint16>(headers->size()));
1198 } else {
1199 frame->WriteUInt32(headers->size());
1201 SpdyHeaderBlock::const_iterator it;
1202 for (it = headers->begin(); it != headers->end(); ++it) {
1203 if (spdy_version < SPDY3) {
1204 frame->WriteStringPiece16(it->first);
1205 frame->WriteStringPiece16(it->second);
1206 } else {
1207 frame->WriteStringPiece32(it->first);
1208 frame->WriteStringPiece32(it->second);
1213 // TODO(phajdan.jr): Clean up after we no longer need
1214 // to workaround http://crbug.com/139744.
1215 #if !defined(USE_SYSTEM_ZLIB)
1217 // These constants are used by zlib to differentiate between normal data and
1218 // cookie data. Cookie data is handled specially by zlib when compressing.
1219 enum ZDataClass {
1220 // kZStandardData is compressed normally, save that it will never match
1221 // against any other class of data in the window.
1222 kZStandardData = Z_CLASS_STANDARD,
1223 // kZCookieData is compressed in its own Huffman blocks and only matches in
1224 // its entirety and only against other kZCookieData blocks. Any matches must
1225 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1226 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1227 // prefix matches.
1228 kZCookieData = Z_CLASS_COOKIE,
1229 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1230 // against the window.
1231 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1234 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1235 // needed when switching between classes of data.
1236 static void WriteZ(const base::StringPiece& data,
1237 ZDataClass clas,
1238 z_stream* out) {
1239 int rv;
1241 // If we are switching from standard to non-standard data then we need to end
1242 // the current Huffman context to avoid it leaking between them.
1243 if (out->clas == kZStandardData &&
1244 clas != kZStandardData) {
1245 out->avail_in = 0;
1246 rv = deflate(out, Z_PARTIAL_FLUSH);
1247 DCHECK_EQ(Z_OK, rv);
1248 DCHECK_EQ(0u, out->avail_in);
1249 DCHECK_LT(0u, out->avail_out);
1252 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1253 out->avail_in = data.size();
1254 out->clas = clas;
1255 if (clas == kZStandardData) {
1256 rv = deflate(out, Z_NO_FLUSH);
1257 } else {
1258 rv = deflate(out, Z_PARTIAL_FLUSH);
1260 if (!data.empty()) {
1261 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1262 DCHECK_EQ(Z_OK, rv);
1264 DCHECK_EQ(0u, out->avail_in);
1265 DCHECK_LT(0u, out->avail_out);
1268 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1269 static void WriteLengthZ(size_t n,
1270 unsigned length,
1271 ZDataClass clas,
1272 z_stream* out) {
1273 char buf[4];
1274 DCHECK_LE(length, sizeof(buf));
1275 for (unsigned i = 1; i <= length; i++) {
1276 buf[length - i] = static_cast<char>(n);
1277 n >>= 8;
1279 WriteZ(base::StringPiece(buf, length), clas, out);
1282 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1283 // manner that resists the length of the compressed data from compromising
1284 // cookie data.
1285 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1286 z_stream* z) const {
1287 unsigned length_length = 4;
1288 if (protocol_version() < 3)
1289 length_length = 2;
1291 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1293 std::map<std::string, std::string>::const_iterator it;
1294 for (it = headers->begin(); it != headers->end(); ++it) {
1295 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1296 WriteZ(it->first, kZStandardData, z);
1298 if (it->first == "cookie") {
1299 // We require the cookie values (save for the last) to end with a
1300 // semicolon and (save for the first) to start with a space. This is
1301 // typically the format that we are given them in but we reserialize them
1302 // to be sure.
1304 std::vector<base::StringPiece> cookie_values;
1305 size_t cookie_length = 0;
1306 base::StringPiece cookie_data(it->second);
1308 for (;;) {
1309 while (!cookie_data.empty() &&
1310 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1311 cookie_data.remove_prefix(1);
1313 if (cookie_data.empty())
1314 break;
1316 size_t i;
1317 for (i = 0; i < cookie_data.size(); i++) {
1318 if (cookie_data[i] == ';')
1319 break;
1321 if (i < cookie_data.size()) {
1322 if (!IsCookieEmpty(cookie_data.substr(0, i))) {
1323 cookie_values.push_back(cookie_data.substr(0, i));
1324 cookie_length += i + 2 /* semicolon and space */;
1326 cookie_data.remove_prefix(i + 1);
1327 } else {
1328 if (!IsCookieEmpty(cookie_data)) {
1329 cookie_values.push_back(cookie_data);
1330 cookie_length += cookie_data.size();
1331 } else if (cookie_length > 2) {
1332 cookie_length -= 2 /* compensate for previously added length */;
1334 cookie_data.remove_prefix(i);
1338 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1339 for (size_t i = 0; i < cookie_values.size(); i++) {
1340 std::string cookie;
1341 // Since zlib will only back-reference complete cookies, a cookie that
1342 // is currently last (and so doesn't have a trailing semicolon) won't
1343 // match if it's later in a non-final position. The same is true of
1344 // the first cookie.
1345 if (i == 0 && cookie_values.size() == 1) {
1346 cookie = cookie_values[i].as_string();
1347 } else if (i == 0) {
1348 cookie = cookie_values[i].as_string() + ";";
1349 } else if (i < cookie_values.size() - 1) {
1350 cookie = " " + cookie_values[i].as_string() + ";";
1351 } else {
1352 cookie = " " + cookie_values[i].as_string();
1354 WriteZ(cookie, kZCookieData, z);
1356 } else if (it->first == "accept" ||
1357 it->first == "accept-charset" ||
1358 it->first == "accept-encoding" ||
1359 it->first == "accept-language" ||
1360 it->first == "host" ||
1361 it->first == "version" ||
1362 it->first == "method" ||
1363 it->first == "scheme" ||
1364 it->first == ":host" ||
1365 it->first == ":version" ||
1366 it->first == ":method" ||
1367 it->first == ":scheme" ||
1368 it->first == "user-agent") {
1369 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1370 WriteZ(it->second, kZStandardData, z);
1371 } else {
1372 // Non-whitelisted headers are Huffman compressed in their own block, but
1373 // don't match against the window.
1374 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1375 WriteZ(it->second, kZHuffmanOnlyData, z);
1379 z->avail_in = 0;
1380 int rv = deflate(z, Z_SYNC_FLUSH);
1381 DCHECK_EQ(Z_OK, rv);
1382 z->clas = kZStandardData;
1385 #endif // !defined(USE_SYSTEM_ZLIB)
1387 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1388 size_t len) {
1389 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1390 const size_t original_len = len;
1392 if (remaining_control_header_ > 0) {
1393 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1394 remaining_control_header_);
1395 remaining_control_header_ -= bytes_read;
1396 remaining_data_length_ -= bytes_read;
1399 if (remaining_control_header_ == 0) {
1400 SpdyFrameReader reader(current_frame_buffer_.get(),
1401 current_frame_buffer_length_);
1402 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1404 switch (current_frame_type_) {
1405 case SYN_STREAM:
1407 DCHECK_GE(SPDY3, protocol_version());
1408 bool successful_read = true;
1409 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1410 DCHECK(successful_read);
1411 if (current_frame_stream_id_ == 0) {
1412 set_error(SPDY_INVALID_CONTROL_FRAME);
1413 break;
1416 SpdyStreamId associated_to_stream_id = kInvalidStream;
1417 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1418 DCHECK(successful_read);
1420 SpdyPriority priority = 0;
1421 successful_read = reader.ReadUInt8(&priority);
1422 DCHECK(successful_read);
1423 if (protocol_version() <= SPDY2) {
1424 priority = priority >> 6;
1425 } else {
1426 priority = priority >> 5;
1429 // Seek past unused byte; used to be credential slot in SPDY 3.
1430 reader.Seek(1);
1432 DCHECK(reader.IsDoneReading());
1433 if (debug_visitor_) {
1434 debug_visitor_->OnReceiveCompressedFrame(
1435 current_frame_stream_id_,
1436 current_frame_type_,
1437 current_frame_length_);
1439 visitor_->OnSynStream(
1440 current_frame_stream_id_,
1441 associated_to_stream_id,
1442 priority,
1443 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1444 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1446 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1447 break;
1448 case SETTINGS:
1449 if (protocol_version() > SPDY3 &&
1450 current_frame_flags_ & SETTINGS_FLAG_ACK) {
1451 visitor_->OnSettingsAck();
1452 CHANGE_STATE(SPDY_AUTO_RESET);
1453 } else {
1454 visitor_->OnSettings(current_frame_flags_ &
1455 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1456 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1458 break;
1459 case SYN_REPLY:
1460 case HEADERS:
1461 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1463 if (protocol_version() > SPDY3) {
1464 DCHECK_EQ(HEADERS, current_frame_type_);
1466 bool successful_read = true;
1467 if (protocol_version() <= SPDY3) {
1468 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1469 DCHECK(successful_read);
1471 if (current_frame_stream_id_ == 0) {
1472 set_error(SPDY_INVALID_CONTROL_FRAME);
1473 break;
1475 if (protocol_version() <= SPDY2) {
1476 // SPDY 2 had two unused bytes here. Seek past them.
1477 reader.Seek(2);
1479 if (protocol_version() > SPDY3 &&
1480 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1481 current_frame_type_ == HEADERS) {
1482 expect_continuation_ = current_frame_stream_id_;
1483 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1485 if (protocol_version() > SPDY3 &&
1486 current_frame_flags_ & HEADERS_FLAG_PADDED) {
1487 uint8 pad_payload_len = 0;
1488 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1489 successful_read = reader.ReadUInt8(&pad_payload_len);
1490 DCHECK(successful_read);
1491 remaining_padding_payload_length_ = pad_payload_len;
1493 const bool has_priority =
1494 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1495 SpdyPriority priority = 0;
1496 if (protocol_version() > SPDY3 && has_priority) {
1497 // TODO(jgraettinger): Process dependency rather than ignoring it.
1498 reader.Seek(kPriorityDependencyPayloadSize);
1499 uint8 weight = 0;
1500 successful_read = reader.ReadUInt8(&weight);
1501 if (successful_read) {
1502 priority = MapWeightToPriority(weight);
1505 DCHECK(reader.IsDoneReading());
1506 if (debug_visitor_) {
1507 debug_visitor_->OnReceiveCompressedFrame(
1508 current_frame_stream_id_,
1509 current_frame_type_,
1510 current_frame_length_);
1512 if (current_frame_type_ == SYN_REPLY) {
1513 visitor_->OnSynReply(
1514 current_frame_stream_id_,
1515 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1516 } else {
1517 visitor_->OnHeaders(
1518 current_frame_stream_id_,
1519 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, priority,
1520 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1521 expect_continuation_ == 0);
1524 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1525 break;
1526 case PUSH_PROMISE:
1528 DCHECK_LT(SPDY3, protocol_version());
1529 if (current_frame_stream_id_ == 0) {
1530 set_error(SPDY_INVALID_CONTROL_FRAME);
1531 break;
1533 bool successful_read = true;
1534 if (protocol_version() > SPDY3 &&
1535 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1536 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1537 uint8 pad_payload_len = 0;
1538 successful_read = reader.ReadUInt8(&pad_payload_len);
1539 DCHECK(successful_read);
1540 remaining_padding_payload_length_ = pad_payload_len;
1544 SpdyStreamId promised_stream_id = kInvalidStream;
1545 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1546 DCHECK(successful_read);
1547 DCHECK(reader.IsDoneReading());
1548 if (promised_stream_id == 0) {
1549 set_error(SPDY_INVALID_CONTROL_FRAME);
1550 break;
1552 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1553 expect_continuation_ = current_frame_stream_id_;
1555 if (debug_visitor_) {
1556 debug_visitor_->OnReceiveCompressedFrame(
1557 current_frame_stream_id_,
1558 current_frame_type_,
1559 current_frame_length_);
1561 visitor_->OnPushPromise(current_frame_stream_id_,
1562 promised_stream_id,
1563 (current_frame_flags_ &
1564 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1566 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1567 break;
1568 case CONTINUATION:
1570 // Check to make sure the stream id of the current frame is
1571 // the same as that of the preceding frame.
1572 // If we're at this point we should already know that
1573 // expect_continuation_ != 0, so this doubles as a check
1574 // that current_frame_stream_id != 0.
1575 if (current_frame_stream_id_ != expect_continuation_) {
1576 set_error(SPDY_INVALID_CONTROL_FRAME);
1577 break;
1579 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1580 expect_continuation_ = 0;
1582 if (debug_visitor_) {
1583 debug_visitor_->OnReceiveCompressedFrame(
1584 current_frame_stream_id_,
1585 current_frame_type_,
1586 current_frame_length_);
1588 visitor_->OnContinuation(current_frame_stream_id_,
1589 (current_frame_flags_ &
1590 HEADERS_FLAG_END_HEADERS) != 0);
1592 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1593 break;
1594 default:
1595 DCHECK(false);
1598 return original_len - len;
1601 // Does not buffer the control payload. Instead, either passes directly to the
1602 // visitor or decompresses and then passes directly to the visitor, via
1603 // IncrementallyDeliverControlFrameHeaderData() or
1604 // IncrementallyDecompressControlFrameHeaderData() respectively.
1605 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1606 size_t data_len,
1607 bool is_hpack_header_block) {
1608 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1610 bool processed_successfully = true;
1611 if (current_frame_type_ != SYN_STREAM &&
1612 current_frame_type_ != SYN_REPLY &&
1613 current_frame_type_ != HEADERS &&
1614 current_frame_type_ != PUSH_PROMISE &&
1615 current_frame_type_ != CONTINUATION) {
1616 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1618 size_t process_bytes = std::min(
1619 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1620 if (is_hpack_header_block) {
1621 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1622 current_frame_stream_id_, data, process_bytes)) {
1623 // TODO(jgraettinger): Finer-grained HPACK error codes.
1624 set_error(SPDY_DECOMPRESS_FAILURE);
1625 processed_successfully = false;
1627 } else if (process_bytes > 0) {
1628 if (enable_compression_ && protocol_version() <= SPDY3) {
1629 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1630 current_frame_stream_id_, data, process_bytes);
1631 } else {
1632 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1633 current_frame_stream_id_, data, process_bytes);
1636 remaining_data_length_ -= process_bytes;
1638 // Handle the case that there is no futher data in this frame.
1639 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1640 processed_successfully) {
1641 if (expect_continuation_ == 0) {
1642 if (is_hpack_header_block) {
1643 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1644 current_frame_stream_id_)) {
1645 set_error(SPDY_DECOMPRESS_FAILURE);
1646 processed_successfully = false;
1647 } else {
1648 // TODO(jgraettinger): To be removed with migration to
1649 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1650 // block, delivered via reentrant call to
1651 // ProcessControlFrameHeaderBlock().
1652 DeliverHpackBlockAsSpdy3Block();
1653 return process_bytes;
1655 } else {
1656 // The complete header block has been delivered. We send a zero-length
1657 // OnControlFrameHeaderData() to indicate this.
1658 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1661 if (processed_successfully) {
1662 CHANGE_STATE(SPDY_CONSUME_PADDING);
1666 // Handle error.
1667 if (!processed_successfully) {
1668 return data_len;
1671 // Return amount processed.
1672 return process_bytes;
1675 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1676 size_t data_len) {
1677 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1678 DCHECK_EQ(SETTINGS, current_frame_type_);
1679 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1680 size_t processed_bytes = 0;
1682 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
1684 // Loop over our incoming data.
1685 while (unprocessed_bytes > 0) {
1686 // Process up to one setting at a time.
1687 size_t processing = std::min(
1688 unprocessed_bytes,
1689 static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
1691 // Check if we have a complete setting in our input.
1692 if (processing == setting_size) {
1693 // Parse the setting directly out of the input without buffering.
1694 if (!ProcessSetting(data + processed_bytes)) {
1695 set_error(SPDY_INVALID_CONTROL_FRAME);
1696 return processed_bytes;
1698 } else {
1699 // Continue updating settings_scratch_.setting_buf.
1700 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1701 data + processed_bytes,
1702 processing);
1703 settings_scratch_.setting_buf_len += processing;
1705 // Check if we have a complete setting buffered.
1706 if (settings_scratch_.setting_buf_len == setting_size) {
1707 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1708 set_error(SPDY_INVALID_CONTROL_FRAME);
1709 return processed_bytes;
1711 // Reset settings_scratch_.setting_buf for our next setting.
1712 settings_scratch_.setting_buf_len = 0;
1716 // Iterate.
1717 unprocessed_bytes -= processing;
1718 processed_bytes += processing;
1721 // Check if we're done handling this SETTINGS frame.
1722 remaining_data_length_ -= processed_bytes;
1723 if (remaining_data_length_ == 0) {
1724 visitor_->OnSettingsEnd();
1725 CHANGE_STATE(SPDY_AUTO_RESET);
1728 return processed_bytes;
1731 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1732 DCHECK_LT(SPDY3, protocol_version());
1733 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1735 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
1736 if (block.empty()) {
1737 // Special-case this to make tests happy.
1738 ProcessControlFrameHeaderBlock(NULL, 0, false);
1739 return;
1741 SpdyFrameBuilder builder(
1742 GetSerializedLength(protocol_version(), &block),
1743 SPDY3);
1745 SerializeNameValueBlockWithoutCompression(&builder, block);
1746 scoped_ptr<SpdyFrame> frame(builder.take());
1748 // Preserve padding length, and reset it after the re-entrant call.
1749 size_t remaining_padding = remaining_padding_payload_length_;
1751 remaining_padding_payload_length_ = 0;
1752 remaining_data_length_ = frame->size();
1754 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1756 remaining_padding_payload_length_ = remaining_padding;
1757 remaining_data_length_ = remaining_padding;
1760 bool SpdyFramer::ProcessSetting(const char* data) {
1761 int id_field;
1762 SpdySettingsIds id;
1763 uint8 flags = 0;
1764 uint32 value;
1766 // Extract fields.
1767 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1768 if (protocol_version() <= SPDY3) {
1769 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1770 SettingsFlagsAndId id_and_flags =
1771 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1772 id_field = id_and_flags.id();
1773 flags = id_and_flags.flags();
1774 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1775 } else {
1776 id_field = ntohs(*(reinterpret_cast<const uint16*>(data)));
1777 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2)));
1780 // Validate id.
1781 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1782 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1783 if (protocol_version() <= SPDY3) {
1784 return false;
1785 } else {
1786 // In HTTP2 we ignore unknown settings for extensibility.
1787 return true;
1790 id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1792 if (protocol_version() <= SPDY3) {
1793 // Detect duplicates.
1794 if (id <= settings_scratch_.last_setting_id) {
1795 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1796 << " in " << display_protocol_ << " SETTINGS frame "
1797 << "(last setting id was "
1798 << settings_scratch_.last_setting_id << ").";
1799 return false;
1801 settings_scratch_.last_setting_id = id;
1803 // Validate flags.
1804 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1805 if ((flags & ~(kFlagsMask)) != 0) {
1806 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1807 << flags;
1808 return false;
1812 // Validation succeeded. Pass on to visitor.
1813 visitor_->OnSetting(id, flags, value);
1814 return true;
1817 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1818 size_t original_len = len;
1819 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1820 remaining_data_length_);
1821 remaining_data_length_ -= bytes_read;
1822 if (remaining_data_length_ == 0) {
1823 SpdyFrameReader reader(current_frame_buffer_.get(),
1824 current_frame_buffer_length_);
1825 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1827 // Use frame-specific handlers.
1828 switch (current_frame_type_) {
1829 case PING: {
1830 SpdyPingId id = 0;
1831 bool is_ack = protocol_version() > SPDY3 &&
1832 (current_frame_flags_ & PING_FLAG_ACK);
1833 bool successful_read = true;
1834 if (protocol_version() <= SPDY3) {
1835 uint32 id32 = 0;
1836 successful_read = reader.ReadUInt32(&id32);
1837 id = id32;
1838 } else {
1839 successful_read = reader.ReadUInt64(&id);
1841 DCHECK(successful_read);
1842 DCHECK(reader.IsDoneReading());
1843 visitor_->OnPing(id, is_ack);
1845 break;
1846 case WINDOW_UPDATE: {
1847 uint32 delta_window_size = 0;
1848 bool successful_read = true;
1849 if (protocol_version() <= SPDY3) {
1850 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1851 DCHECK(successful_read);
1853 successful_read = reader.ReadUInt32(&delta_window_size);
1854 DCHECK(successful_read);
1855 DCHECK(reader.IsDoneReading());
1856 visitor_->OnWindowUpdate(current_frame_stream_id_,
1857 delta_window_size);
1859 break;
1860 case BLOCKED: {
1861 DCHECK_LT(SPDY3, protocol_version());
1862 DCHECK(reader.IsDoneReading());
1863 visitor_->OnBlocked(current_frame_stream_id_);
1865 break;
1866 case PRIORITY: {
1867 DCHECK_LT(SPDY3, protocol_version());
1868 uint32 parent_stream_id;
1869 uint8 weight;
1870 bool exclusive;
1871 bool successful_read = true;
1872 successful_read = reader.ReadUInt32(&parent_stream_id);
1873 DCHECK(successful_read);
1874 // Exclusivity is indicated by a single bit flag.
1875 exclusive = (parent_stream_id >> 31) != 0;
1876 // Zero out the highest-order bit to get the parent stream id.
1877 parent_stream_id &= 0x7fffffff;
1878 successful_read = reader.ReadUInt8(&weight);
1879 DCHECK(successful_read);
1880 DCHECK(reader.IsDoneReading());
1881 visitor_->OnPriority(
1882 current_frame_stream_id_, parent_stream_id, weight, exclusive);
1884 break;
1885 default:
1886 // Unreachable.
1887 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1890 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1892 return original_len - len;
1895 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1896 if (len == 0) {
1897 return 0;
1899 // Clamp to the actual remaining payload.
1900 if (len > remaining_data_length_) {
1901 len = remaining_data_length_;
1903 size_t original_len = len;
1905 // Check if we had already read enough bytes to parse the GOAWAY header.
1906 const size_t header_size = GetGoAwayMinimumSize();
1907 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1908 bool already_parsed_header = (unread_header_bytes == 0);
1909 if (!already_parsed_header) {
1910 // Buffer the new GOAWAY header bytes we got.
1911 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1913 // Do we have enough to parse the constant size GOAWAY header?
1914 if (current_frame_buffer_length_ == header_size) {
1915 // Parse out the last good stream id.
1916 SpdyFrameReader reader(current_frame_buffer_.get(),
1917 current_frame_buffer_length_);
1918 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1919 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1920 DCHECK(successful_read);
1922 // In SPDYv3 and up, frames also specify a status code - parse it out.
1923 SpdyGoAwayStatus status = GOAWAY_OK;
1924 if (protocol_version() >= SPDY3) {
1925 uint32 status_raw = GOAWAY_OK;
1926 successful_read = reader.ReadUInt32(&status_raw);
1927 DCHECK(successful_read);
1928 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1929 status_raw)) {
1930 status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1931 status_raw);
1932 } else {
1933 if (protocol_version() > SPDY3) {
1934 // Treat unrecognized status codes as INTERNAL_ERROR as
1935 // recommended by the HTTP/2 spec.
1936 status = GOAWAY_INTERNAL_ERROR;
1940 // Finished parsing the GOAWAY header, call frame handler.
1941 visitor_->OnGoAway(current_frame_stream_id_, status);
1945 // Handle remaining data as opaque.
1946 bool processed_successfully = true;
1947 if (len > 0) {
1948 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1950 remaining_data_length_ -= original_len;
1951 if (!processed_successfully) {
1952 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1953 } else if (remaining_data_length_ == 0) {
1954 // Signal that there is not more opaque data.
1955 visitor_->OnGoAwayFrameData(NULL, 0);
1956 CHANGE_STATE(SPDY_AUTO_RESET);
1958 return original_len;
1961 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1962 if (len == 0) {
1963 return 0;
1965 // Clamp to the actual remaining payload.
1966 if (len > remaining_data_length_) {
1967 len = remaining_data_length_;
1969 size_t original_len = len;
1971 // Check if we had already read enough bytes to parse the fixed-length portion
1972 // of the RST_STREAM frame.
1973 const size_t header_size = GetRstStreamMinimumSize();
1974 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1975 bool already_parsed_header = (unread_header_bytes == 0);
1976 if (!already_parsed_header) {
1977 // Buffer the new RST_STREAM header bytes we got.
1978 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1980 // Do we have enough to parse the constant size RST_STREAM header?
1981 if (current_frame_buffer_length_ == header_size) {
1982 // Parse out the last good stream id.
1983 SpdyFrameReader reader(current_frame_buffer_.get(),
1984 current_frame_buffer_length_);
1985 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1986 if (protocol_version() <= SPDY3) {
1987 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1988 DCHECK(successful_read);
1991 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1992 uint32 status_raw = status;
1993 bool successful_read = reader.ReadUInt32(&status_raw);
1994 DCHECK(successful_read);
1995 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1996 status_raw)) {
1997 status =
1998 SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw);
1999 } else {
2000 if (protocol_version() > SPDY3) {
2001 // Treat unrecognized status codes as INTERNAL_ERROR as
2002 // recommended by the HTTP/2 spec.
2003 status = RST_STREAM_INTERNAL_ERROR;
2006 // Finished parsing the RST_STREAM header, call frame handler.
2007 visitor_->OnRstStream(current_frame_stream_id_, status);
2011 // Handle remaining data as opaque.
2012 bool processed_successfully = true;
2013 if (len > 0) {
2014 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
2016 remaining_data_length_ -= original_len;
2017 if (!processed_successfully) {
2018 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
2019 } else if (remaining_data_length_ == 0) {
2020 // Signal that there is not more opaque data.
2021 visitor_->OnRstStreamFrameData(NULL, 0);
2022 CHANGE_STATE(SPDY_AUTO_RESET);
2024 return original_len;
2027 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
2028 if (len == 0) {
2029 return 0;
2032 // Clamp to the actual remaining payload.
2033 len = std::min(len, remaining_data_length_);
2035 if (altsvc_scratch_.buffer.get() == nullptr) {
2036 altsvc_scratch_.buffer.reset(
2037 new char[current_frame_length_ - GetControlFrameHeaderSize()]);
2038 altsvc_scratch_.buffer_length = 0;
2040 memcpy(altsvc_scratch_.buffer.get() + altsvc_scratch_.buffer_length, data,
2041 len);
2042 altsvc_scratch_.buffer_length += len;
2043 remaining_data_length_ -= len;
2044 if (remaining_data_length_ > 0) {
2045 return len;
2048 SpdyFrameReader reader(altsvc_scratch_.buffer.get(),
2049 altsvc_scratch_.buffer_length);
2050 StringPiece origin;
2051 bool successful_read = reader.ReadStringPiece16(&origin);
2052 if (!successful_read) {
2053 set_error(SPDY_INVALID_CONTROL_FRAME);
2054 return 0;
2056 StringPiece value(altsvc_scratch_.buffer.get() + reader.GetBytesConsumed(),
2057 altsvc_scratch_.buffer_length - reader.GetBytesConsumed());
2059 SpdyAltSvcWireFormat::AlternativeService altsvc;
2060 bool success = SpdyAltSvcWireFormat::ParseHeaderFieldValue(value, &altsvc);
2061 if (!success || altsvc.protocol_id.length() == 0) {
2062 set_error(SPDY_INVALID_CONTROL_FRAME);
2063 return 0;
2066 visitor_->OnAltSvc(current_frame_stream_id_, origin, altsvc);
2067 CHANGE_STATE(SPDY_AUTO_RESET);
2068 return len;
2071 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
2072 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_);
2073 DCHECK_EQ(0u, remaining_padding_payload_length_);
2074 DCHECK_EQ(DATA, current_frame_type_);
2076 size_t original_len = len;
2077 if (current_frame_flags_ & DATA_FLAG_PADDED) {
2078 if (len != 0) {
2079 if (remaining_data_length_ < kPadLengthFieldSize) {
2080 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2081 return 0;
2084 static_assert(kPadLengthFieldSize == 1,
2085 "Unexpected pad length field size.");
2086 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data);
2087 ++data;
2088 --len;
2089 --remaining_data_length_;
2090 visitor_->OnStreamPadding(current_frame_stream_id_, kPadLengthFieldSize);
2091 } else {
2092 // We don't have the data available for parsing the pad length field. Keep
2093 // waiting.
2094 return 0;
2098 if (remaining_padding_payload_length_ > remaining_data_length_) {
2099 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2100 return 0;
2102 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2103 return original_len - len;
2106 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2107 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2109 size_t original_len = len;
2110 if (remaining_padding_payload_length_ > 0) {
2111 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2112 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2113 if (current_frame_type_ == DATA && amount_to_discard > 0) {
2114 DCHECK_LE(SPDY4, protocol_version());
2115 visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
2117 data += amount_to_discard;
2118 len -= amount_to_discard;
2119 remaining_padding_payload_length_ -= amount_to_discard;
2120 remaining_data_length_ -= amount_to_discard;
2123 if (remaining_data_length_ == 0) {
2124 // If the FIN flag is set, or this ends a header block which set FIN,
2125 // inform the visitor of EOF via a 0-length data frame.
2126 if (expect_continuation_ == 0 &&
2127 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2128 end_stream_when_done_)) {
2129 end_stream_when_done_ = false;
2130 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2132 CHANGE_STATE(SPDY_AUTO_RESET);
2134 return original_len - len;
2137 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2138 size_t original_len = len;
2139 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2140 size_t amount_to_forward = std::min(
2141 remaining_data_length_ - remaining_padding_payload_length_, len);
2142 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2143 // Only inform the visitor if there is data.
2144 if (amount_to_forward) {
2145 visitor_->OnStreamFrameData(
2146 current_frame_stream_id_, data, amount_to_forward, false);
2149 data += amount_to_forward;
2150 len -= amount_to_forward;
2151 remaining_data_length_ -= amount_to_forward;
2154 if (remaining_data_length_ == remaining_padding_payload_length_) {
2155 CHANGE_STATE(SPDY_CONSUME_PADDING);
2157 return original_len - len;
2160 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2161 size_t len) {
2162 size_t original_len = len;
2163 if (remaining_data_length_ > 0) {
2164 size_t amount_to_ignore = std::min(remaining_data_length_, len);
2165 len -= amount_to_ignore;
2166 remaining_data_length_ -= amount_to_ignore;
2169 if (remaining_data_length_ == 0) {
2170 CHANGE_STATE(SPDY_AUTO_RESET);
2172 return original_len - len;
2175 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2176 size_t header_length,
2177 SpdyHeaderBlock* block) const {
2178 SpdyFrameReader reader(header_data, header_length);
2180 // Read number of headers.
2181 uint32 num_headers;
2182 if (protocol_version() <= SPDY2) {
2183 uint16 temp;
2184 if (!reader.ReadUInt16(&temp)) {
2185 DVLOG(1) << "Unable to read number of headers.";
2186 return 0;
2188 num_headers = temp;
2189 } else {
2190 if (!reader.ReadUInt32(&num_headers)) {
2191 DVLOG(1) << "Unable to read number of headers.";
2192 return 0;
2196 // Read each header.
2197 for (uint32 index = 0; index < num_headers; ++index) {
2198 base::StringPiece temp;
2200 // Read header name.
2201 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2202 : !reader.ReadStringPiece32(&temp)) {
2203 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2204 << num_headers << ").";
2205 return 0;
2207 std::string name = temp.as_string();
2209 // Read header value.
2210 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2211 : !reader.ReadStringPiece32(&temp)) {
2212 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2213 << num_headers << ").";
2214 return 0;
2216 std::string value = temp.as_string();
2218 // Ensure no duplicates.
2219 if (block->find(name) != block->end()) {
2220 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2221 << num_headers << ").";
2222 return 0;
2225 // Store header.
2226 (*block)[name] = value;
2228 return reader.GetBytesConsumed();
2231 SpdySerializedFrame* SpdyFramer::SerializeData(
2232 const SpdyDataIR& data_ir) const {
2233 uint8 flags = DATA_FLAG_NONE;
2234 if (data_ir.fin()) {
2235 flags = DATA_FLAG_FIN;
2238 if (protocol_version() > SPDY3) {
2239 int num_padding_fields = 0;
2240 if (data_ir.padded()) {
2241 flags |= DATA_FLAG_PADDED;
2242 ++num_padding_fields;
2245 const size_t size_with_padding = num_padding_fields +
2246 data_ir.data().length() + data_ir.padding_payload_len() +
2247 GetDataFrameMinimumSize();
2248 SpdyFrameBuilder builder(size_with_padding, protocol_version());
2249 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2250 if (data_ir.padded()) {
2251 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2253 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2254 if (data_ir.padding_payload_len() > 0) {
2255 string padding(data_ir.padding_payload_len(), 0);
2256 builder.WriteBytes(padding.data(), padding.length());
2258 DCHECK_EQ(size_with_padding, builder.length());
2259 return builder.take();
2260 } else {
2261 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2262 SpdyFrameBuilder builder(size, protocol_version());
2263 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2264 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2265 DCHECK_EQ(size, builder.length());
2266 return builder.take();
2270 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2271 const SpdyDataIR& data_ir) const {
2272 uint8 flags = DATA_FLAG_NONE;
2273 if (data_ir.fin()) {
2274 flags = DATA_FLAG_FIN;
2277 size_t frame_size = GetDataFrameMinimumSize();
2278 size_t num_padding_fields = 0;
2279 if (protocol_version() > SPDY3) {
2280 if (data_ir.padded()) {
2281 flags |= DATA_FLAG_PADDED;
2282 ++num_padding_fields;
2284 frame_size += num_padding_fields;
2287 SpdyFrameBuilder builder(frame_size, protocol_version());
2288 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2289 if (protocol_version() > SPDY3) {
2290 if (data_ir.padded()) {
2291 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2293 builder.OverwriteLength(*this, num_padding_fields +
2294 data_ir.data().length() + data_ir.padding_payload_len());
2295 } else {
2296 builder.OverwriteLength(*this, data_ir.data().length());
2298 DCHECK_EQ(frame_size, builder.length());
2299 return builder.take();
2302 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2303 const SpdySynStreamIR& syn_stream) {
2304 DCHECK_GE(SPDY3, protocol_version());
2305 uint8 flags = 0;
2306 if (syn_stream.fin()) {
2307 flags |= CONTROL_FLAG_FIN;
2309 if (syn_stream.unidirectional()) {
2310 // TODO(hkhalil): invalid for HTTP2.
2311 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2314 // Sanitize priority.
2315 uint8 priority = syn_stream.priority();
2316 if (priority > GetLowestPriority()) {
2317 DLOG(DFATAL) << "Priority out-of-bounds.";
2318 priority = GetLowestPriority();
2321 // The size of this frame, including variable-length name-value block.
2322 size_t size = GetSynStreamMinimumSize() +
2323 GetSerializedLength(syn_stream.name_value_block());
2325 SpdyFrameBuilder builder(size, protocol_version());
2326 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2327 builder.WriteUInt32(syn_stream.stream_id());
2328 builder.WriteUInt32(syn_stream.associated_to_stream_id());
2329 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2330 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
2331 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2332 SerializeNameValueBlock(&builder, syn_stream);
2334 if (debug_visitor_) {
2335 const size_t payload_len =
2336 GetSerializedLength(protocol_version(),
2337 &(syn_stream.name_value_block()));
2338 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2339 SYN_STREAM,
2340 payload_len,
2341 builder.length());
2344 return builder.take();
2347 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2348 const SpdySynReplyIR& syn_reply) {
2349 DCHECK_GE(SPDY3, protocol_version());
2350 uint8 flags = 0;
2351 if (syn_reply.fin()) {
2352 flags |= CONTROL_FLAG_FIN;
2355 // The size of this frame, including variable-length name-value block.
2356 const size_t size = GetSynReplyMinimumSize() +
2357 GetSerializedLength(syn_reply.name_value_block());
2359 SpdyFrameBuilder builder(size, protocol_version());
2360 if (protocol_version() <= SPDY3) {
2361 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2362 builder.WriteUInt32(syn_reply.stream_id());
2363 } else {
2364 builder.BeginNewFrame(*this,
2365 HEADERS,
2366 flags,
2367 syn_reply.stream_id());
2369 if (protocol_version() < SPDY3) {
2370 builder.WriteUInt16(0); // Unused.
2372 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2373 SerializeNameValueBlock(&builder, syn_reply);
2375 if (debug_visitor_) {
2376 const size_t payload_len = GetSerializedLength(
2377 protocol_version(), &(syn_reply.name_value_block()));
2378 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2379 SYN_REPLY,
2380 payload_len,
2381 builder.length());
2384 return builder.take();
2387 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2388 const SpdyRstStreamIR& rst_stream) const {
2389 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2390 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2391 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2392 // commented but left in place to simplify future patching.
2393 // Compute the output buffer size, taking opaque data into account.
2394 size_t expected_length = GetRstStreamMinimumSize();
2395 if (protocol_version() > SPDY3) {
2396 expected_length += rst_stream.description().size();
2398 SpdyFrameBuilder builder(expected_length, protocol_version());
2400 // Serialize the RST_STREAM frame.
2401 if (protocol_version() <= SPDY3) {
2402 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2403 builder.WriteUInt32(rst_stream.stream_id());
2404 } else {
2405 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2408 builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
2409 protocol_version(), rst_stream.status()));
2411 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2412 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2413 builder.WriteBytes(rst_stream.description().data(),
2414 rst_stream.description().size());
2417 DCHECK_EQ(expected_length, builder.length());
2418 return builder.take();
2421 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2422 const SpdySettingsIR& settings) const {
2423 uint8 flags = 0;
2425 if (protocol_version() <= SPDY3) {
2426 if (settings.clear_settings()) {
2427 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2429 } else {
2430 if (settings.is_ack()) {
2431 flags |= SETTINGS_FLAG_ACK;
2434 const SpdySettingsIR::ValueMap* values = &(settings.values());
2436 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
2437 // Size, in bytes, of this SETTINGS frame.
2438 const size_t size = GetSettingsMinimumSize() +
2439 (values->size() * setting_size);
2440 SpdyFrameBuilder builder(size, protocol_version());
2441 if (protocol_version() <= SPDY3) {
2442 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2443 } else {
2444 builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2447 // If this is an ACK, payload should be empty.
2448 if (protocol_version() > SPDY3 && settings.is_ack()) {
2449 return builder.take();
2452 if (protocol_version() <= SPDY3) {
2453 builder.WriteUInt32(values->size());
2455 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2456 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2457 it != values->end();
2458 ++it) {
2459 int setting_id =
2460 SpdyConstants::SerializeSettingId(protocol_version(), it->first);
2461 DCHECK_GE(setting_id, 0);
2462 if (protocol_version() <= SPDY3) {
2463 uint8 setting_flags = 0;
2464 if (it->second.persist_value) {
2465 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2467 if (it->second.persisted) {
2468 setting_flags |= SETTINGS_FLAG_PERSISTED;
2470 SettingsFlagsAndId flags_and_id(setting_flags, setting_id);
2471 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2472 builder.WriteBytes(&id_and_flags_wire, 4);
2473 } else {
2474 builder.WriteUInt16(static_cast<uint16>(setting_id));
2476 builder.WriteUInt32(it->second.value);
2478 DCHECK_EQ(size, builder.length());
2479 return builder.take();
2482 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2483 SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2484 if (protocol_version() <= SPDY3) {
2485 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2486 builder.WriteUInt32(static_cast<uint32>(ping.id()));
2487 } else {
2488 uint8 flags = 0;
2489 if (ping.is_ack()) {
2490 flags |= PING_FLAG_ACK;
2492 builder.BeginNewFrame(*this, PING, flags, 0);
2493 builder.WriteUInt64(ping.id());
2495 DCHECK_EQ(GetPingSize(), builder.length());
2496 return builder.take();
2499 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2500 const SpdyGoAwayIR& goaway) const {
2502 // Compute the output buffer size, take opaque data into account.
2503 size_t expected_length = GetGoAwayMinimumSize();
2504 if (protocol_version() > SPDY3) {
2505 expected_length += goaway.description().size();
2507 SpdyFrameBuilder builder(expected_length, protocol_version());
2509 // Serialize the GOAWAY frame.
2510 if (protocol_version() <= SPDY3) {
2511 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2512 } else {
2513 builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2516 // GOAWAY frames specify the last good stream id for all SPDY versions.
2517 builder.WriteUInt32(goaway.last_good_stream_id());
2519 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2520 if (protocol_version() >= SPDY3) {
2521 // TODO(jgraettinger): Merge back to server-side.
2522 builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2523 goaway.status()));
2526 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2527 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2528 builder.WriteBytes(goaway.description().data(),
2529 goaway.description().size());
2532 DCHECK_EQ(expected_length, builder.length());
2533 return builder.take();
2536 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2537 const SpdyHeadersIR& headers) {
2538 uint8 flags = 0;
2539 if (headers.fin()) {
2540 flags |= CONTROL_FLAG_FIN;
2542 if (protocol_version() > SPDY3) {
2543 // This will get overwritten if we overflow into a CONTINUATION frame.
2544 flags |= HEADERS_FLAG_END_HEADERS;
2545 if (headers.has_priority()) {
2546 flags |= HEADERS_FLAG_PRIORITY;
2548 if (headers.padded()) {
2549 flags |= HEADERS_FLAG_PADDED;
2553 // The size of this frame, including padding (if there is any)
2554 // and variable-length name-value block.
2555 size_t size = GetHeadersMinimumSize();
2557 if (protocol_version() > SPDY3 && headers.padded()) {
2558 size += kPadLengthFieldSize;
2559 size += headers.padding_payload_len();
2562 SpdyPriority priority = static_cast<SpdyPriority>(headers.priority());
2563 if (headers.has_priority()) {
2564 if (headers.priority() > GetLowestPriority()) {
2565 DLOG(DFATAL) << "Priority out-of-bounds.";
2566 priority = GetLowestPriority();
2568 size += 5;
2571 string hpack_encoding;
2572 if (protocol_version() > SPDY3) {
2573 if (enable_compression_) {
2574 GetHpackEncoder()->EncodeHeaderSet(
2575 headers.name_value_block(), &hpack_encoding);
2576 } else {
2577 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2578 headers.name_value_block(), &hpack_encoding);
2580 size += hpack_encoding.size();
2581 if (size > kMaxControlFrameSize) {
2582 size += GetNumberRequiredContinuationFrames(size) *
2583 GetContinuationMinimumSize();
2584 flags &= ~HEADERS_FLAG_END_HEADERS;
2586 } else {
2587 size += GetSerializedLength(headers.name_value_block());
2590 SpdyFrameBuilder builder(size, protocol_version());
2591 if (protocol_version() <= SPDY3) {
2592 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2593 builder.WriteUInt32(headers.stream_id());
2594 } else {
2595 builder.BeginNewFrame(*this,
2596 HEADERS,
2597 flags,
2598 headers.stream_id());
2600 if (protocol_version() <= SPDY2) {
2601 builder.WriteUInt16(0); // Unused.
2603 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2605 if (protocol_version() > SPDY3) {
2606 int padding_payload_len = 0;
2607 if (headers.padded()) {
2608 builder.WriteUInt8(headers.padding_payload_len());
2609 padding_payload_len = headers.padding_payload_len();
2611 if (headers.has_priority()) {
2612 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2613 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2614 builder.WriteUInt8(MapPriorityToWeight(priority));
2616 WritePayloadWithContinuation(&builder,
2617 hpack_encoding,
2618 headers.stream_id(),
2619 HEADERS,
2620 padding_payload_len);
2621 } else {
2622 SerializeNameValueBlock(&builder, headers);
2625 if (debug_visitor_) {
2626 // SPDY4 uses HPACK for header compression. However, continue to
2627 // use GetSerializedLength() for an apples-to-apples comparision of
2628 // compression performance between HPACK and SPDY w/ deflate.
2629 const size_t payload_len =
2630 GetSerializedLength(protocol_version(),
2631 &(headers.name_value_block()));
2632 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2633 HEADERS,
2634 payload_len,
2635 builder.length());
2638 return builder.take();
2641 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2642 const SpdyWindowUpdateIR& window_update) const {
2643 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2644 if (protocol_version() <= SPDY3) {
2645 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2646 builder.WriteUInt32(window_update.stream_id());
2647 } else {
2648 builder.BeginNewFrame(*this,
2649 WINDOW_UPDATE,
2650 kNoFlags,
2651 window_update.stream_id());
2653 builder.WriteUInt32(window_update.delta());
2654 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2655 return builder.take();
2658 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2659 DCHECK_LT(SPDY3, protocol_version());
2660 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2661 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2662 return builder.take();
2665 SpdyFrame* SpdyFramer::SerializePushPromise(
2666 const SpdyPushPromiseIR& push_promise) {
2667 DCHECK_LT(SPDY3, protocol_version());
2668 uint8 flags = 0;
2669 // This will get overwritten if we overflow into a CONTINUATION frame.
2670 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2671 // The size of this frame, including variable-length name-value block.
2672 size_t size = GetPushPromiseMinimumSize();
2674 if (push_promise.padded()) {
2675 flags |= PUSH_PROMISE_FLAG_PADDED;
2676 size += kPadLengthFieldSize;
2677 size += push_promise.padding_payload_len();
2680 string hpack_encoding;
2681 if (enable_compression_) {
2682 GetHpackEncoder()->EncodeHeaderSet(
2683 push_promise.name_value_block(), &hpack_encoding);
2684 } else {
2685 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2686 push_promise.name_value_block(), &hpack_encoding);
2688 size += hpack_encoding.size();
2689 if (size > kMaxControlFrameSize) {
2690 size += GetNumberRequiredContinuationFrames(size) *
2691 GetContinuationMinimumSize();
2692 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2695 SpdyFrameBuilder builder(size, protocol_version());
2696 builder.BeginNewFrame(*this,
2697 PUSH_PROMISE,
2698 flags,
2699 push_promise.stream_id());
2700 int padding_payload_len = 0;
2701 if (push_promise.padded()) {
2702 builder.WriteUInt8(push_promise.padding_payload_len());
2703 builder.WriteUInt32(push_promise.promised_stream_id());
2704 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
2705 builder.length());
2707 padding_payload_len = push_promise.padding_payload_len();
2708 } else {
2709 builder.WriteUInt32(push_promise.promised_stream_id());
2710 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2713 WritePayloadWithContinuation(&builder,
2714 hpack_encoding,
2715 push_promise.stream_id(),
2716 PUSH_PROMISE,
2717 padding_payload_len);
2719 if (debug_visitor_) {
2720 // SPDY4 uses HPACK for header compression. However, continue to
2721 // use GetSerializedLength() for an apples-to-apples comparision of
2722 // compression performance between HPACK and SPDY w/ deflate.
2723 const size_t payload_len =
2724 GetSerializedLength(protocol_version(),
2725 &(push_promise.name_value_block()));
2726 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2727 PUSH_PROMISE,
2728 payload_len,
2729 builder.length());
2732 return builder.take();
2735 // TODO(jgraettinger): This implementation is incorrect. The continuation
2736 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2737 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2738 SpdyFrame* SpdyFramer::SerializeContinuation(
2739 const SpdyContinuationIR& continuation) {
2740 CHECK_LT(SPDY3, protocol_version());
2741 uint8 flags = 0;
2742 if (continuation.end_headers()) {
2743 flags |= HEADERS_FLAG_END_HEADERS;
2746 // The size of this frame, including variable-length name-value block.
2747 size_t size = GetContinuationMinimumSize();
2748 string hpack_encoding;
2749 if (enable_compression_) {
2750 GetHpackEncoder()->EncodeHeaderSet(
2751 continuation.name_value_block(), &hpack_encoding);
2752 } else {
2753 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2754 continuation.name_value_block(), &hpack_encoding);
2756 size += hpack_encoding.size();
2758 SpdyFrameBuilder builder(size, protocol_version());
2759 builder.BeginNewFrame(*this, CONTINUATION, flags,
2760 continuation.stream_id());
2761 DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2763 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2764 return builder.take();
2767 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
2768 DCHECK_LT(SPDY3, protocol_version());
2770 size_t size = GetAltSvcMinimumSize();
2771 size += altsvc.origin().length();
2772 string value =
2773 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc.altsvc());
2774 size += value.length();
2776 SpdyFrameBuilder builder(size, protocol_version());
2777 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
2779 builder.WriteUInt16(altsvc.origin().length());
2780 builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
2781 builder.WriteBytes(value.data(), value.length());
2782 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2783 return builder.take();
2786 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const {
2787 DCHECK_LT(SPDY3, protocol_version());
2788 size_t size = GetPrioritySize();
2790 SpdyFrameBuilder builder(size, protocol_version());
2791 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
2793 // Make sure the highest-order bit in the parent stream id is zeroed out.
2794 uint32 parent_stream_id = priority.parent_stream_id() & 0x7fffffff;
2795 uint32 exclusive = priority.exclusive() ? 0x80000000 : 0;
2796 // Set the one-bit exclusivity flag.
2797 uint32 flag_and_parent_id = parent_stream_id | exclusive;
2798 builder.WriteUInt32(flag_and_parent_id);
2799 builder.WriteUInt8(priority.weight());
2800 DCHECK_EQ(GetPrioritySize(), builder.length());
2801 return builder.take();
2804 namespace {
2806 class FrameSerializationVisitor : public SpdyFrameVisitor {
2807 public:
2808 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2809 ~FrameSerializationVisitor() override {}
2811 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2813 void VisitData(const SpdyDataIR& data) override {
2814 frame_.reset(framer_->SerializeData(data));
2816 void VisitSynStream(const SpdySynStreamIR& syn_stream) override {
2817 frame_.reset(framer_->SerializeSynStream(syn_stream));
2819 void VisitSynReply(const SpdySynReplyIR& syn_reply) override {
2820 frame_.reset(framer_->SerializeSynReply(syn_reply));
2822 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2823 frame_.reset(framer_->SerializeRstStream(rst_stream));
2825 void VisitSettings(const SpdySettingsIR& settings) override {
2826 frame_.reset(framer_->SerializeSettings(settings));
2828 void VisitPing(const SpdyPingIR& ping) override {
2829 frame_.reset(framer_->SerializePing(ping));
2831 void VisitGoAway(const SpdyGoAwayIR& goaway) override {
2832 frame_.reset(framer_->SerializeGoAway(goaway));
2834 void VisitHeaders(const SpdyHeadersIR& headers) override {
2835 frame_.reset(framer_->SerializeHeaders(headers));
2837 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2838 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2840 void VisitBlocked(const SpdyBlockedIR& blocked) override {
2841 frame_.reset(framer_->SerializeBlocked(blocked));
2843 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2844 frame_.reset(framer_->SerializePushPromise(push_promise));
2846 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2847 frame_.reset(framer_->SerializeContinuation(continuation));
2849 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
2850 frame_.reset(framer_->SerializeAltSvc(altsvc));
2852 void VisitPriority(const SpdyPriorityIR& priority) override {
2853 frame_.reset(framer_->SerializePriority(priority));
2856 private:
2857 SpdyFramer* framer_;
2858 scoped_ptr<SpdySerializedFrame> frame_;
2861 } // namespace
2863 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2864 FrameSerializationVisitor visitor(this);
2865 frame.Visit(&visitor);
2866 return visitor.ReleaseSerializedFrame();
2869 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2870 CHECK_GE(SPDY3, protocol_version());
2871 const size_t uncompressed_length =
2872 GetSerializedLength(protocol_version(), &headers);
2873 if (!enable_compression_) {
2874 return uncompressed_length;
2876 z_stream* compressor = GetHeaderCompressor();
2877 // Since we'll be performing lots of flushes when compressing the data,
2878 // zlib's lower bounds may be insufficient.
2879 return 2 * deflateBound(compressor, uncompressed_length);
2882 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2883 DCHECK_GT(protocol_version(), SPDY3);
2884 DCHECK_GT(size, kMaxControlFrameSize);
2885 size_t overflow = size - kMaxControlFrameSize;
2886 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
2887 // This is ceiling(overflow/payload_size) using integer arithmetics.
2888 return (overflow - 1) / payload_size + 1;
2891 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2892 const string& hpack_encoding,
2893 SpdyStreamId stream_id,
2894 SpdyFrameType type,
2895 int padding_payload_len) {
2896 uint8 end_flag = 0;
2897 uint8 flags = 0;
2898 if (type == HEADERS) {
2899 end_flag = HEADERS_FLAG_END_HEADERS;
2900 } else if (type == PUSH_PROMISE) {
2901 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2902 } else {
2903 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2904 << FrameTypeToString(type);
2907 // Write all the padding payload and as much of the data payload as possible
2908 // into the initial frame.
2909 size_t bytes_remaining = 0;
2910 bytes_remaining =
2911 hpack_encoding.size() -
2912 std::min(hpack_encoding.size(),
2913 kMaxControlFrameSize - builder->length() - padding_payload_len);
2914 builder->WriteBytes(&hpack_encoding[0],
2915 hpack_encoding.size() - bytes_remaining);
2916 if (padding_payload_len > 0) {
2917 string padding = string(padding_payload_len, 0);
2918 builder->WriteBytes(padding.data(), padding.length());
2920 if (bytes_remaining > 0) {
2921 builder->OverwriteLength(
2922 *this, kMaxControlFrameSize - GetControlFrameHeaderSize());
2925 // Tack on CONTINUATION frames for the overflow.
2926 while (bytes_remaining > 0) {
2927 size_t bytes_to_write = std::min(
2928 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize());
2929 // Write CONTINUATION frame prefix.
2930 if (bytes_remaining == bytes_to_write) {
2931 flags |= end_flag;
2933 builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
2934 // Write payload fragment.
2935 builder->WriteBytes(
2936 &hpack_encoding[hpack_encoding.size() - bytes_remaining],
2937 bytes_to_write);
2938 bytes_remaining -= bytes_to_write;
2942 // The following compression setting are based on Brian Olson's analysis. See
2943 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2944 // for more details.
2945 #if defined(USE_SYSTEM_ZLIB)
2946 // System zlib is not expected to have workaround for http://crbug.com/139744,
2947 // so disable compression in that case.
2948 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2949 static const int kCompressorLevel = 0;
2950 #else // !defined(USE_SYSTEM_ZLIB)
2951 static const int kCompressorLevel = 9;
2952 #endif // !defined(USE_SYSTEM_ZLIB)
2953 static const int kCompressorWindowSizeInBits = 11;
2954 static const int kCompressorMemLevel = 1;
2956 z_stream* SpdyFramer::GetHeaderCompressor() {
2957 if (header_compressor_.get())
2958 return header_compressor_.get(); // Already initialized.
2960 header_compressor_.reset(new z_stream);
2961 memset(header_compressor_.get(), 0, sizeof(z_stream));
2963 int success = deflateInit2(header_compressor_.get(),
2964 kCompressorLevel,
2965 Z_DEFLATED,
2966 kCompressorWindowSizeInBits,
2967 kCompressorMemLevel,
2968 Z_DEFAULT_STRATEGY);
2969 if (success == Z_OK) {
2970 const char* dictionary = (protocol_version() <= SPDY2) ?
2971 kV2Dictionary : kV3Dictionary;
2972 const int dictionary_size = (protocol_version() <= SPDY2) ?
2973 kV2DictionarySize : kV3DictionarySize;
2974 success = deflateSetDictionary(header_compressor_.get(),
2975 reinterpret_cast<const Bytef*>(dictionary),
2976 dictionary_size);
2978 if (success != Z_OK) {
2979 LOG(WARNING) << "deflateSetDictionary failure: " << success;
2980 header_compressor_.reset(NULL);
2981 return NULL;
2983 return header_compressor_.get();
2986 z_stream* SpdyFramer::GetHeaderDecompressor() {
2987 if (header_decompressor_.get())
2988 return header_decompressor_.get(); // Already initialized.
2990 header_decompressor_.reset(new z_stream);
2991 memset(header_decompressor_.get(), 0, sizeof(z_stream));
2993 int success = inflateInit(header_decompressor_.get());
2994 if (success != Z_OK) {
2995 LOG(WARNING) << "inflateInit failure: " << success;
2996 header_decompressor_.reset(NULL);
2997 return NULL;
2999 return header_decompressor_.get();
3002 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3003 DCHECK_LT(SPDY3, protocol_version());
3004 if (hpack_encoder_.get() == nullptr) {
3005 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3007 return hpack_encoder_.get();
3010 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3011 DCHECK_LT(SPDY3, protocol_version());
3012 if (hpack_decoder_.get() == nullptr) {
3013 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3015 return hpack_decoder_.get();
3018 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3019 const float kSteps = 255.9f / 7.f;
3020 return static_cast<uint8>(kSteps * (7.f - priority));
3023 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3024 const float kSteps = 255.9f / 7.f;
3025 return static_cast<SpdyPriority>(7.f - weight / kSteps);
3028 // Incrementally decompress the control frame's header block, feeding the
3029 // result to the visitor in chunks. Continue this until the visitor
3030 // indicates that it cannot process any more data, or (more commonly) we
3031 // run out of data to deliver.
3032 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3033 SpdyStreamId stream_id,
3034 const char* data,
3035 size_t len) {
3036 // Get a decompressor or set error.
3037 z_stream* decomp = GetHeaderDecompressor();
3038 if (decomp == NULL) {
3039 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3040 set_error(SPDY_DECOMPRESS_FAILURE);
3041 return false;
3044 bool processed_successfully = true;
3045 char buffer[kHeaderDataChunkMaxSize];
3047 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3048 decomp->avail_in = len;
3049 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3050 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3051 // reached this method successfully, stream_id should be nonzero.
3052 DCHECK_LT(0u, stream_id);
3053 while (decomp->avail_in > 0 && processed_successfully) {
3054 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3055 decomp->avail_out = arraysize(buffer);
3057 int rv = inflate(decomp, Z_SYNC_FLUSH);
3058 if (rv == Z_NEED_DICT) {
3059 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3060 : kV3Dictionary;
3061 const int dictionary_size = (protocol_version() <= SPDY2) ?
3062 kV2DictionarySize : kV3DictionarySize;
3063 const DictionaryIds& ids = g_dictionary_ids.Get();
3064 const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3065 ids.v2_dictionary_id : ids.v3_dictionary_id;
3066 // Need to try again with the right dictionary.
3067 if (decomp->adler == dictionary_id) {
3068 rv = inflateSetDictionary(decomp,
3069 reinterpret_cast<const Bytef*>(dictionary),
3070 dictionary_size);
3071 if (rv == Z_OK)
3072 rv = inflate(decomp, Z_SYNC_FLUSH);
3076 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3077 // without producing any output. The input is consumed and
3078 // buffered internally by zlib so we can detect this condition by
3079 // checking if avail_in is 0 after the call to inflate.
3080 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3081 if ((rv == Z_OK) || input_exhausted) {
3082 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3083 if (decompressed_len > 0) {
3084 processed_successfully = visitor_->OnControlFrameHeaderData(
3085 stream_id, buffer, decompressed_len);
3087 if (!processed_successfully) {
3088 // Assume that the problem was the header block was too large for the
3089 // visitor.
3090 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3092 } else {
3093 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3094 set_error(SPDY_DECOMPRESS_FAILURE);
3095 processed_successfully = false;
3098 return processed_successfully;
3101 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3102 SpdyStreamId stream_id, const char* data, size_t len) {
3103 bool read_successfully = true;
3104 while (read_successfully && len > 0) {
3105 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3106 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3107 bytes_to_deliver);
3108 data += bytes_to_deliver;
3109 len -= bytes_to_deliver;
3110 if (!read_successfully) {
3111 // Assume that the problem was the header block was too large for the
3112 // visitor.
3113 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3116 return read_successfully;
3119 void SpdyFramer::UpdateHeaderTableSizeSetting(uint32 value) {
3120 header_table_size_bound_ = value;
3121 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value);
3122 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value);
3125 // Return size bound of the header compression table.
3126 size_t SpdyFramer::header_table_size_bound() const {
3127 return header_table_size_bound_;
3130 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3131 SpdyFrameBuilder* builder,
3132 const SpdyNameValueBlock& name_value_block) const {
3133 // Serialize number of headers.
3134 if (protocol_version() <= SPDY2) {
3135 builder->WriteUInt16(static_cast<uint16>(name_value_block.size()));
3136 } else {
3137 builder->WriteUInt32(name_value_block.size());
3140 // Serialize each header.
3141 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3142 it != name_value_block.end();
3143 ++it) {
3144 if (protocol_version() <= SPDY2) {
3145 builder->WriteStringPiece16(it->first);
3146 builder->WriteStringPiece16(it->second);
3147 } else {
3148 builder->WriteStringPiece32(it->first);
3149 builder->WriteStringPiece32(it->second);
3154 void SpdyFramer::SerializeNameValueBlock(
3155 SpdyFrameBuilder* builder,
3156 const SpdyFrameWithNameValueBlockIR& frame) {
3157 CHECK_GE(SPDY3, protocol_version());
3158 if (!enable_compression_) {
3159 return SerializeNameValueBlockWithoutCompression(builder,
3160 frame.name_value_block());
3163 // First build an uncompressed version to be fed into the compressor.
3164 const size_t uncompressed_len = GetSerializedLength(
3165 protocol_version(), &(frame.name_value_block()));
3166 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3167 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
3168 frame.name_value_block());
3169 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3171 z_stream* compressor = GetHeaderCompressor();
3172 if (!compressor) {
3173 LOG(DFATAL) << "Could not obtain compressor.";
3174 return;
3176 // Create an output frame.
3177 // Since we'll be performing lots of flushes when compressing the data,
3178 // zlib's lower bounds may be insufficient.
3180 // TODO(akalin): Avoid the duplicate calculation with
3181 // GetSerializedLength(const SpdyHeaderBlock&).
3182 const int compressed_max_size =
3183 2 * deflateBound(compressor, uncompressed_len);
3185 // TODO(phajdan.jr): Clean up after we no longer need
3186 // to workaround http://crbug.com/139744.
3187 #if defined(USE_SYSTEM_ZLIB)
3188 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3189 compressor->avail_in = uncompressed_len;
3190 #endif // defined(USE_SYSTEM_ZLIB)
3191 compressor->next_out = reinterpret_cast<Bytef*>(
3192 builder->GetWritableBuffer(compressed_max_size));
3193 compressor->avail_out = compressed_max_size;
3195 // TODO(phajdan.jr): Clean up after we no longer need
3196 // to workaround http://crbug.com/139744.
3197 #if defined(USE_SYSTEM_ZLIB)
3198 int rv = deflate(compressor, Z_SYNC_FLUSH);
3199 if (rv != Z_OK) { // How can we know that it compressed everything?
3200 // This shouldn't happen, right?
3201 LOG(WARNING) << "deflate failure: " << rv;
3202 // TODO(akalin): Upstream this return.
3203 return;
3205 #else
3206 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
3207 #endif // defined(USE_SYSTEM_ZLIB)
3209 int compressed_size = compressed_max_size - compressor->avail_out;
3210 builder->Seek(compressed_size);
3211 builder->RewriteLength(*this);
3214 } // namespace net