We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blobea5eaa564b3b9b92667fd03bac10d1f59ce1a943
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_framer.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/third_party/valgrind/memcheck.h"
10 #include "net/spdy/spdy_frame_builder.h"
11 #include "net/spdy/spdy_frame_reader.h"
12 #include "net/spdy/spdy_bitmasks.h"
13 #include "third_party/zlib/zlib.h"
15 using base::StringPiece;
16 using std::string;
17 using std::vector;
19 namespace net {
21 namespace {
23 // Compute the id of our dictionary so that we know we're using the
24 // right one when asked for it.
25 uLong CalculateDictionaryId(const char* dictionary,
26 const size_t dictionary_size) {
27 uLong initial_value = adler32(0L, Z_NULL, 0);
28 return adler32(initial_value,
29 reinterpret_cast<const Bytef*>(dictionary),
30 dictionary_size);
33 // Check to see if the name and value of a cookie are both empty.
34 bool IsCookieEmpty(const base::StringPiece& cookie) {
35 if (cookie.size() == 0) {
36 return true;
38 size_t pos = cookie.find('=');
39 if (pos == base::StringPiece::npos) {
40 return false;
42 // Ignore leading whitespaces of cookie value.
43 size_t value_start = pos + 1;
44 for (; value_start < cookie.size(); value_start++) {
45 if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) {
46 break;
49 return (pos == 0) && ((cookie.size() - value_start) == 0);
52 struct DictionaryIds {
53 DictionaryIds()
54 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
55 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
57 const uLong v2_dictionary_id;
58 const uLong v3_dictionary_id;
61 // Adler ID for the SPDY header compressor dictionaries. Note that they are
62 // initialized lazily to avoid static initializers.
63 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
65 // Used to indicate no flags in a SPDY flags field.
66 const uint8 kNoFlags = 0;
68 // Wire sizes of priority payloads.
69 const size_t kPriorityDependencyPayloadSize = 4;
70 const size_t kPriorityWeightPayloadSize = 1;
72 // Wire size of pad length field.
73 const size_t kPadLengthFieldSize = 1;
75 } // namespace
77 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
78 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
79 // We fragment sent control frames at smaller payload boundaries.
80 const size_t SpdyFramer::kMaxControlFrameSize = 1024;
81 // The size of the control frame buffer. Must be >= the minimum size of the
82 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
83 // calculation details.
84 const size_t SpdyFramer::kControlFrameBufferSize = 19;
86 #ifdef DEBUG_SPDY_STATE_CHANGES
87 #define CHANGE_STATE(newstate) \
88 do { \
89 DVLOG(1) << "Changing state from: " \
90 << StateToString(state_) \
91 << " to " << StateToString(newstate) << "\n"; \
92 DCHECK(state_ != SPDY_ERROR); \
93 DCHECK_EQ(previous_state_, state_); \
94 previous_state_ = state_; \
95 state_ = newstate; \
96 } while (false)
97 #else
98 #define CHANGE_STATE(newstate) \
99 do { \
100 DCHECK(state_ != SPDY_ERROR); \
101 DCHECK_EQ(previous_state_, state_); \
102 previous_state_ = state_; \
103 state_ = newstate; \
104 } while (false)
105 #endif
107 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
108 SpdyMajorVersion version, uint32 wire) {
109 if (version < SPDY3) {
110 ConvertFlagsAndIdForSpdy2(&wire);
112 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
115 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
116 : flags_(flags), id_(id & 0x00ffffff) {
117 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
120 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
121 const {
122 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
123 if (version < SPDY3) {
124 ConvertFlagsAndIdForSpdy2(&wire);
126 return wire;
129 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
130 // This method is used to preserve buggy behavior and works on both
131 // little-endian and big-endian hosts.
132 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
133 // as well as vice versa).
134 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
135 uint8* wire_array = reinterpret_cast<uint8*>(val);
136 std::swap(wire_array[0], wire_array[3]);
137 std::swap(wire_array[1], wire_array[2]);
140 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
141 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
143 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
144 size_t len) {
145 return true;
148 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
149 const char* rst_stream_data,
150 size_t len) {
151 return true;
154 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
155 : current_frame_buffer_(new char[kControlFrameBufferSize]),
156 expect_continuation_(0),
157 visitor_(NULL),
158 debug_visitor_(NULL),
159 display_protocol_("SPDY"),
160 protocol_version_(version),
161 enable_compression_(true),
162 syn_frame_processed_(false),
163 probable_http_response_(false),
164 end_stream_when_done_(false) {
165 DCHECK_GE(protocol_version_, SPDY_MIN_VERSION);
166 DCHECK_LE(protocol_version_, SPDY_MAX_VERSION);
167 DCHECK_LE(kMaxControlFrameSize,
168 SpdyConstants::GetFrameMaximumSize(protocol_version_) +
169 SpdyConstants::GetControlFrameHeaderSize(protocol_version_));
170 Reset();
173 SpdyFramer::~SpdyFramer() {
174 if (header_compressor_.get()) {
175 deflateEnd(header_compressor_.get());
177 if (header_decompressor_.get()) {
178 inflateEnd(header_decompressor_.get());
182 void SpdyFramer::Reset() {
183 state_ = SPDY_RESET;
184 previous_state_ = SPDY_RESET;
185 error_code_ = SPDY_NO_ERROR;
186 remaining_data_length_ = 0;
187 remaining_control_header_ = 0;
188 current_frame_buffer_length_ = 0;
189 current_frame_type_ = DATA;
190 current_frame_flags_ = 0;
191 current_frame_length_ = 0;
192 current_frame_stream_id_ = kInvalidStream;
193 settings_scratch_.Reset();
194 altsvc_scratch_.Reset();
195 remaining_padding_payload_length_ = 0;
198 size_t SpdyFramer::GetDataFrameMinimumSize() const {
199 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
202 // Size, in bytes, of the control frame header.
203 size_t SpdyFramer::GetControlFrameHeaderSize() const {
204 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
207 size_t SpdyFramer::GetSynStreamMinimumSize() const {
208 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
209 // name-value block.
210 if (protocol_version() <= SPDY3) {
211 // Calculated as:
212 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
213 // + 1 (unused, was credential slot)
214 return GetControlFrameHeaderSize() + 10;
215 } else {
216 return GetControlFrameHeaderSize() +
217 kPriorityDependencyPayloadSize +
218 kPriorityWeightPayloadSize;
222 size_t SpdyFramer::GetSynReplyMinimumSize() const {
223 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
224 // name-value block.
225 size_t size = GetControlFrameHeaderSize();
226 if (protocol_version() <= SPDY3) {
227 // Calculated as:
228 // control frame header + 4 (stream IDs)
229 size += 4;
232 // In SPDY 2, there were 2 unused bytes before payload.
233 if (protocol_version() < SPDY3) {
234 size += 2;
237 return size;
240 size_t SpdyFramer::GetRstStreamMinimumSize() const {
241 // Size, in bytes, of a RST_STREAM frame.
242 if (protocol_version() <= SPDY3) {
243 // Calculated as:
244 // control frame header + 4 (stream id) + 4 (status code)
245 return GetControlFrameHeaderSize() + 8;
246 } else {
247 // Calculated as:
248 // frame prefix + 4 (status code)
249 return GetControlFrameHeaderSize() + 4;
253 size_t SpdyFramer::GetSettingsMinimumSize() const {
254 // Size, in bytes, of a SETTINGS frame not including the IDs and values
255 // from the variable-length value block. Calculated as:
256 // control frame header + 4 (number of ID/value pairs)
257 if (protocol_version() <= SPDY3) {
258 return GetControlFrameHeaderSize() + 4;
259 } else {
260 return GetControlFrameHeaderSize();
264 size_t SpdyFramer::GetPingSize() const {
265 // Size, in bytes, of this PING frame.
266 if (protocol_version() <= SPDY3) {
267 // Calculated as:
268 // control frame header + 4 (id)
269 return GetControlFrameHeaderSize() + 4;
270 } else {
271 // Calculated as:
272 // control frame header + 8 (id)
273 return GetControlFrameHeaderSize() + 8;
277 size_t SpdyFramer::GetGoAwayMinimumSize() const {
278 // Size, in bytes, of this GOAWAY frame. Calculated as:
279 // 1. Control frame header size
280 size_t size = GetControlFrameHeaderSize();
282 // 2. Last good stream id (4 bytes)
283 size += 4;
285 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
286 if (protocol_version() >= SPDY3) {
287 size += 4;
290 return size;
293 size_t SpdyFramer::GetHeadersMinimumSize() const {
294 // Size, in bytes, of a HEADERS frame not including the variable-length
295 // name-value block.
296 size_t size = GetControlFrameHeaderSize();
297 if (protocol_version() <= SPDY3) {
298 // Calculated as:
299 // control frame header + 4 (stream IDs)
300 size += 4;
303 // In SPDY 2, there were 2 unused bytes before payload.
304 if (protocol_version() <= SPDY2) {
305 size += 2;
308 return size;
311 size_t SpdyFramer::GetWindowUpdateSize() const {
312 // Size, in bytes, of a WINDOW_UPDATE frame.
313 if (protocol_version() <= SPDY3) {
314 // Calculated as:
315 // control frame header + 4 (stream id) + 4 (delta)
316 return GetControlFrameHeaderSize() + 8;
317 } else {
318 // Calculated as:
319 // frame prefix + 4 (delta)
320 return GetControlFrameHeaderSize() + 4;
324 size_t SpdyFramer::GetBlockedSize() const {
325 DCHECK_LT(SPDY3, protocol_version());
326 // Size, in bytes, of a BLOCKED frame.
327 // The BLOCKED frame has no payload beyond the control frame header.
328 return GetControlFrameHeaderSize();
331 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
332 DCHECK_LT(SPDY3, protocol_version());
333 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
334 // Calculated as frame prefix + 4 (promised stream id).
335 return GetControlFrameHeaderSize() + 4;
338 size_t SpdyFramer::GetContinuationMinimumSize() const {
339 // Size, in bytes, of a CONTINUATION frame not including the variable-length
340 // headers fragments.
341 return GetControlFrameHeaderSize();
344 size_t SpdyFramer::GetAltSvcMinimumSize() const {
345 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
346 // (optional) Origin fields, all of which can vary in length.
347 // Note that this gives a lower bound on the frame size rather than a true
348 // minimum; the actual frame should always be larger than this.
349 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
350 // + 1 (pid_len) + 1 (host_len).
351 return GetControlFrameHeaderSize() + 9;
354 size_t SpdyFramer::GetPrioritySize() const {
355 // Size, in bytes, of a PRIORITY frame.
356 return GetControlFrameHeaderSize() +
357 kPriorityDependencyPayloadSize +
358 kPriorityWeightPayloadSize;
361 size_t SpdyFramer::GetFrameMinimumSize() const {
362 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
365 size_t SpdyFramer::GetFrameMaximumSize() const {
366 return SpdyConstants::GetFrameMaximumSize(protocol_version());
369 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
370 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
373 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
374 return SpdyConstants::GetPrefixLength(type, protocol_version());
377 const char* SpdyFramer::StateToString(int state) {
378 switch (state) {
379 case SPDY_ERROR:
380 return "ERROR";
381 case SPDY_AUTO_RESET:
382 return "AUTO_RESET";
383 case SPDY_RESET:
384 return "RESET";
385 case SPDY_READING_COMMON_HEADER:
386 return "READING_COMMON_HEADER";
387 case SPDY_CONTROL_FRAME_PAYLOAD:
388 return "CONTROL_FRAME_PAYLOAD";
389 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
390 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
391 case SPDY_CONSUME_PADDING:
392 return "SPDY_CONSUME_PADDING";
393 case SPDY_IGNORE_REMAINING_PAYLOAD:
394 return "IGNORE_REMAINING_PAYLOAD";
395 case SPDY_FORWARD_STREAM_FRAME:
396 return "FORWARD_STREAM_FRAME";
397 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
398 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
399 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
400 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
401 case SPDY_GOAWAY_FRAME_PAYLOAD:
402 return "SPDY_GOAWAY_FRAME_PAYLOAD";
403 case SPDY_RST_STREAM_FRAME_PAYLOAD:
404 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
405 case SPDY_SETTINGS_FRAME_PAYLOAD:
406 return "SPDY_SETTINGS_FRAME_PAYLOAD";
407 case SPDY_ALTSVC_FRAME_PAYLOAD:
408 return "SPDY_ALTSVC_FRAME_PAYLOAD";
410 return "UNKNOWN_STATE";
413 void SpdyFramer::set_error(SpdyError error) {
414 DCHECK(visitor_);
415 error_code_ = error;
416 // These values will usually get reset once we come to the end
417 // of a header block, but if we run into an error that
418 // might not happen, so reset them here.
419 expect_continuation_ = 0;
420 end_stream_when_done_ = false;
422 CHANGE_STATE(SPDY_ERROR);
423 visitor_->OnError(this);
426 const char* SpdyFramer::ErrorCodeToString(int error_code) {
427 switch (error_code) {
428 case SPDY_NO_ERROR:
429 return "NO_ERROR";
430 case SPDY_INVALID_CONTROL_FRAME:
431 return "INVALID_CONTROL_FRAME";
432 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
433 return "CONTROL_PAYLOAD_TOO_LARGE";
434 case SPDY_ZLIB_INIT_FAILURE:
435 return "ZLIB_INIT_FAILURE";
436 case SPDY_UNSUPPORTED_VERSION:
437 return "UNSUPPORTED_VERSION";
438 case SPDY_DECOMPRESS_FAILURE:
439 return "DECOMPRESS_FAILURE";
440 case SPDY_COMPRESS_FAILURE:
441 return "COMPRESS_FAILURE";
442 case SPDY_INVALID_DATA_FRAME_FLAGS:
443 return "SPDY_INVALID_DATA_FRAME_FLAGS";
444 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
445 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
446 case SPDY_UNEXPECTED_FRAME:
447 return "UNEXPECTED_FRAME";
449 return "UNKNOWN_ERROR";
452 const char* SpdyFramer::StatusCodeToString(int status_code) {
453 switch (status_code) {
454 case RST_STREAM_INVALID:
455 return "INVALID";
456 case RST_STREAM_PROTOCOL_ERROR:
457 return "PROTOCOL_ERROR";
458 case RST_STREAM_INVALID_STREAM:
459 return "INVALID_STREAM";
460 case RST_STREAM_REFUSED_STREAM:
461 return "REFUSED_STREAM";
462 case RST_STREAM_UNSUPPORTED_VERSION:
463 return "UNSUPPORTED_VERSION";
464 case RST_STREAM_CANCEL:
465 return "CANCEL";
466 case RST_STREAM_INTERNAL_ERROR:
467 return "INTERNAL_ERROR";
468 case RST_STREAM_FLOW_CONTROL_ERROR:
469 return "FLOW_CONTROL_ERROR";
470 case RST_STREAM_STREAM_IN_USE:
471 return "STREAM_IN_USE";
472 case RST_STREAM_STREAM_ALREADY_CLOSED:
473 return "STREAM_ALREADY_CLOSED";
474 case RST_STREAM_INVALID_CREDENTIALS:
475 return "INVALID_CREDENTIALS";
476 case RST_STREAM_FRAME_TOO_LARGE:
477 return "FRAME_TOO_LARGE";
478 case RST_STREAM_CONNECT_ERROR:
479 return "CONNECT_ERROR";
480 case RST_STREAM_ENHANCE_YOUR_CALM:
481 return "ENHANCE_YOUR_CALM";
482 case RST_STREAM_INADEQUATE_SECURITY:
483 return "INADEQUATE_SECURITY";
484 case RST_STREAM_HTTP_1_1_REQUIRED:
485 return "HTTP_1_1_REQUIRED";
487 return "UNKNOWN_STATUS";
490 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
491 switch (type) {
492 case DATA:
493 return "DATA";
494 case SYN_STREAM:
495 return "SYN_STREAM";
496 case SYN_REPLY:
497 return "SYN_REPLY";
498 case RST_STREAM:
499 return "RST_STREAM";
500 case SETTINGS:
501 return "SETTINGS";
502 case PING:
503 return "PING";
504 case GOAWAY:
505 return "GOAWAY";
506 case HEADERS:
507 return "HEADERS";
508 case WINDOW_UPDATE:
509 return "WINDOW_UPDATE";
510 case CREDENTIAL:
511 return "CREDENTIAL";
512 case PUSH_PROMISE:
513 return "PUSH_PROMISE";
514 case CONTINUATION:
515 return "CONTINUATION";
516 case PRIORITY:
517 return "PRIORITY";
518 case ALTSVC:
519 return "ALTSVC";
520 case BLOCKED:
521 return "BLOCKED";
523 return "UNKNOWN_CONTROL_TYPE";
526 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
527 DCHECK(visitor_);
528 DCHECK(data);
530 size_t original_len = len;
531 do {
532 previous_state_ = state_;
533 switch (state_) {
534 case SPDY_ERROR:
535 goto bottom;
537 case SPDY_AUTO_RESET:
538 case SPDY_RESET:
539 Reset();
540 if (len > 0) {
541 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
543 break;
545 case SPDY_READING_COMMON_HEADER: {
546 size_t bytes_read = ProcessCommonHeader(data, len);
547 len -= bytes_read;
548 data += bytes_read;
549 break;
552 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
553 // Control frames that contain header blocks
554 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
555 // take a different path through the state machine - they
556 // will go:
557 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
558 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
560 // SETTINGS frames take a slightly modified route:
561 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
562 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
564 // All other control frames will use the alternate route directly to
565 // SPDY_CONTROL_FRAME_PAYLOAD
566 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
567 len -= bytes_read;
568 data += bytes_read;
569 break;
572 case SPDY_SETTINGS_FRAME_PAYLOAD: {
573 int bytes_read = ProcessSettingsFramePayload(data, len);
574 len -= bytes_read;
575 data += bytes_read;
576 break;
579 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
580 int bytes_read = ProcessControlFrameHeaderBlock(
581 data, len, protocol_version() > SPDY3);
582 len -= bytes_read;
583 data += bytes_read;
584 break;
587 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
588 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
589 len -= bytes_read;
590 data += bytes_read;
591 break;
594 case SPDY_GOAWAY_FRAME_PAYLOAD: {
595 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
596 len -= bytes_read;
597 data += bytes_read;
598 break;
601 case SPDY_ALTSVC_FRAME_PAYLOAD: {
602 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
603 len -= bytes_read;
604 data += bytes_read;
605 break;
608 case SPDY_CONTROL_FRAME_PAYLOAD: {
609 size_t bytes_read = ProcessControlFramePayload(data, len);
610 len -= bytes_read;
611 data += bytes_read;
612 break;
615 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: {
616 size_t bytes_read = ProcessDataFramePaddingLength(data, len);
617 len -= bytes_read;
618 data += bytes_read;
619 break;
622 case SPDY_CONSUME_PADDING: {
623 size_t bytes_read = ProcessFramePadding(data, len);
624 len -= bytes_read;
625 data += bytes_read;
626 break;
629 case SPDY_IGNORE_REMAINING_PAYLOAD: {
630 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
631 len -= bytes_read;
632 data += bytes_read;
633 break;
636 case SPDY_FORWARD_STREAM_FRAME: {
637 size_t bytes_read = ProcessDataFramePayload(data, len);
638 len -= bytes_read;
639 data += bytes_read;
640 break;
643 default:
644 LOG(DFATAL) << "Invalid value for " << display_protocol_
645 << " framer state: " << state_;
646 // This ensures that we don't infinite-loop if state_ gets an
647 // invalid value somehow, such as due to a SpdyFramer getting deleted
648 // from a callback it calls.
649 goto bottom;
651 } while (state_ != previous_state_);
652 bottom:
653 DCHECK(len == 0 || state_ == SPDY_ERROR);
654 if (current_frame_buffer_length_ == 0 &&
655 remaining_data_length_ == 0 &&
656 remaining_control_header_ == 0) {
657 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
658 << "State: " << StateToString(state_);
661 return original_len - len;
664 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
665 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
666 // state.
667 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
669 size_t original_len = len;
671 // Update current frame buffer as needed.
672 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
673 size_t bytes_desired =
674 GetControlFrameHeaderSize() - current_frame_buffer_length_;
675 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
678 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
679 // Not enough information to do anything meaningful.
680 return original_len - len;
683 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
684 // when processing DATA frames below.
685 scoped_ptr<SpdyFrameReader> reader(
686 new SpdyFrameReader(current_frame_buffer_.get(),
687 current_frame_buffer_length_));
689 bool is_control_frame = false;
691 int control_frame_type_field =
692 SpdyConstants::DataFrameType(protocol_version());
693 // ProcessControlFrameHeader() will set current_frame_type_ to the
694 // correct value if this is a valid control frame.
695 current_frame_type_ = DATA;
696 if (protocol_version() <= SPDY3) {
697 uint16 version = 0;
698 bool successful_read = reader->ReadUInt16(&version);
699 DCHECK(successful_read);
700 is_control_frame = (version & kControlFlagMask) != 0;
701 version &= ~kControlFlagMask; // Only valid for control frames.
702 if (is_control_frame) {
703 // We check version before we check validity: version can never be
704 // 'invalid', it can only be unsupported.
705 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
706 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
707 SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
708 // Version does not match the version the framer was initialized with.
709 DVLOG(1) << "Unsupported SPDY version "
710 << version
711 << " (expected " << protocol_version() << ")";
712 set_error(SPDY_UNSUPPORTED_VERSION);
713 return 0;
715 // We check control_frame_type_field's validity in
716 // ProcessControlFrameHeader().
717 uint16 control_frame_type_field_uint16;
718 successful_read = reader->ReadUInt16(&control_frame_type_field_uint16);
719 control_frame_type_field = control_frame_type_field_uint16;
720 } else {
721 reader->Rewind();
722 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
724 DCHECK(successful_read);
726 successful_read = reader->ReadUInt8(&current_frame_flags_);
727 DCHECK(successful_read);
729 uint32 length_field = 0;
730 successful_read = reader->ReadUInt24(&length_field);
731 DCHECK(successful_read);
732 remaining_data_length_ = length_field;
733 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
734 } else {
735 uint32 length_field = 0;
736 bool successful_read = reader->ReadUInt24(&length_field);
737 DCHECK(successful_read);
739 uint8 control_frame_type_field_uint8;
740 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
741 DCHECK(successful_read);
742 // We check control_frame_type_field's validity in
743 // ProcessControlFrameHeader().
744 control_frame_type_field = control_frame_type_field_uint8;
745 is_control_frame = control_frame_type_field !=
746 SpdyConstants::SerializeFrameType(protocol_version(), DATA);
748 if (is_control_frame) {
749 current_frame_length_ = length_field + GetControlFrameHeaderSize();
750 } else {
751 current_frame_length_ = length_field + GetDataFrameMinimumSize();
754 successful_read = reader->ReadUInt8(&current_frame_flags_);
755 DCHECK(successful_read);
757 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
758 DCHECK(successful_read);
760 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
762 // Before we accept a DATA frame, we need to make sure we're not in the
763 // middle of processing a header block.
764 const bool is_continuation_frame = (control_frame_type_field ==
765 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
766 if ((expect_continuation_ != 0) != is_continuation_frame) {
767 if (expect_continuation_ != 0) {
768 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
769 << "frame, but instead received frame type "
770 << control_frame_type_field;
771 } else {
772 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
774 set_error(SPDY_UNEXPECTED_FRAME);
775 return original_len - len;
778 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
779 : GetDataFrameMinimumSize(),
780 reader->GetBytesConsumed());
781 DCHECK_EQ(current_frame_length_,
782 remaining_data_length_ + reader->GetBytesConsumed());
784 // This is just a sanity check for help debugging early frame errors.
785 if (remaining_data_length_ > 1000000u) {
786 // The strncmp for 5 is safe because we only hit this point if we
787 // have kMinCommonHeader (8) bytes
788 if (!syn_frame_processed_ &&
789 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
790 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
791 << " request";
792 probable_http_response_ = true;
793 } else {
794 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
795 << " session is likely corrupt.";
799 // if we're here, then we have the common header all received.
800 if (!is_control_frame) {
801 if (protocol_version() > SPDY3) {
802 // Catch bogus tests sending oversized DATA frames.
803 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
804 << "DATA frame too large for SPDY >= 4.";
807 uint8 valid_data_flags = 0;
808 if (protocol_version() > SPDY3) {
809 valid_data_flags =
810 DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
811 } else {
812 valid_data_flags = DATA_FLAG_FIN;
815 if (current_frame_flags_ & ~valid_data_flags) {
816 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
817 } else {
818 visitor_->OnDataFrameHeader(current_frame_stream_id_,
819 remaining_data_length_,
820 current_frame_flags_ & DATA_FLAG_FIN);
821 if (remaining_data_length_ > 0) {
822 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH);
823 } else {
824 // Empty data frame.
825 if (current_frame_flags_ & DATA_FLAG_FIN) {
826 visitor_->OnStreamFrameData(
827 current_frame_stream_id_, NULL, 0, true);
829 CHANGE_STATE(SPDY_AUTO_RESET);
832 } else {
833 ProcessControlFrameHeader(control_frame_type_field);
836 return original_len - len;
839 void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
840 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
841 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
843 // TODO(mlavan): Either remove credential frames from the code entirely,
844 // or add them to parsing + serialization methods for SPDY3.
845 // Early detection of deprecated frames that we ignore.
846 if (protocol_version() <= SPDY3) {
847 if (control_frame_type_field == CREDENTIAL) {
848 current_frame_type_ = CREDENTIAL;
849 DCHECK_EQ(SPDY3, protocol_version());
850 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
851 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
852 return;
856 if (!SpdyConstants::IsValidFrameType(protocol_version(),
857 control_frame_type_field)) {
858 if (protocol_version() <= SPDY3) {
859 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
860 << " (protocol version: " << protocol_version() << ")";
861 set_error(SPDY_INVALID_CONTROL_FRAME);
862 return;
863 } else {
864 // In HTTP2 we ignore unknown frame types for extensibility, as long as
865 // the rest of the control frame header is valid.
866 // We rely on the visitor to check validity of current_frame_stream_id_.
867 bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_,
868 control_frame_type_field);
869 if (valid_stream) {
870 DVLOG(1) << "Ignoring unknown frame type.";
871 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
872 } else {
873 // Report an invalid frame error and close the stream if the
874 // stream_id is not valid.
875 DLOG(WARNING) << "Unknown control frame type "
876 << control_frame_type_field
877 << " received on invalid stream "
878 << current_frame_stream_id_;
879 set_error(SPDY_INVALID_CONTROL_FRAME);
881 return;
885 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
886 control_frame_type_field);
888 // Do some sanity checking on the control frame sizes and flags.
889 switch (current_frame_type_) {
890 case SYN_STREAM:
891 if (current_frame_length_ < GetSynStreamMinimumSize()) {
892 set_error(SPDY_INVALID_CONTROL_FRAME);
893 } else if (current_frame_flags_ &
894 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
895 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
897 break;
898 case SYN_REPLY:
899 if (current_frame_length_ < GetSynReplyMinimumSize()) {
900 set_error(SPDY_INVALID_CONTROL_FRAME);
901 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
902 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
904 break;
905 case RST_STREAM:
906 // For SPDY versions < 4, the header has a fixed length.
907 // For SPDY version 4 and up, the RST_STREAM frame may include optional
908 // opaque data, so we only have a lower limit on the frame size.
909 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
910 protocol_version() <= SPDY3) ||
911 (current_frame_length_ < GetRstStreamMinimumSize() &&
912 protocol_version() > SPDY3)) {
913 set_error(SPDY_INVALID_CONTROL_FRAME);
914 } else if (current_frame_flags_ != 0) {
915 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
917 break;
918 case SETTINGS:
920 // Make sure that we have an integral number of 8-byte key/value pairs,
921 // plus a 4-byte length field in SPDY3 and below.
922 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
923 // Size of each key/value pair in bytes.
924 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
925 if (current_frame_length_ < GetSettingsMinimumSize() ||
926 (current_frame_length_ - GetControlFrameHeaderSize())
927 % setting_size != values_prefix_size) {
928 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
929 << current_frame_length_;
930 set_error(SPDY_INVALID_CONTROL_FRAME);
931 } else if (protocol_version() <= SPDY3 &&
932 current_frame_flags_ &
933 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
934 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
935 } else if (protocol_version() > SPDY3 &&
936 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
937 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
938 } else if (protocol_version() > SPDY3 &&
939 current_frame_flags_ & SETTINGS_FLAG_ACK &&
940 current_frame_length_ > GetSettingsMinimumSize()) {
941 set_error(SPDY_INVALID_CONTROL_FRAME);
943 break;
945 case PING:
946 if (current_frame_length_ != GetPingSize()) {
947 set_error(SPDY_INVALID_CONTROL_FRAME);
948 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
949 (current_frame_flags_ & ~PING_FLAG_ACK)) {
950 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
952 break;
953 case GOAWAY:
955 // For SPDY version < 4, there are only mandatory fields and the header
956 // has a fixed length. For SPDY version >= 4, optional opaque data may
957 // be appended to the GOAWAY frame, thus there is only a minimal length
958 // restriction.
959 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
960 protocol_version() <= SPDY3) ||
961 (current_frame_length_ < GetGoAwayMinimumSize() &&
962 protocol_version() > SPDY3)) {
963 set_error(SPDY_INVALID_CONTROL_FRAME);
964 } else if (current_frame_flags_ != 0) {
965 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
967 break;
969 case HEADERS:
971 size_t min_size = GetHeadersMinimumSize();
972 if (protocol_version() > SPDY3 &&
973 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
974 min_size += 4;
976 if (current_frame_length_ < min_size) {
977 // TODO(mlavan): check here for HEADERS with no payload?
978 // (not allowed in SPDY4)
979 set_error(SPDY_INVALID_CONTROL_FRAME);
980 } else if (protocol_version() <= SPDY3 &&
981 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
982 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
983 } else if (protocol_version() > SPDY3 &&
984 current_frame_flags_ &
985 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
986 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
987 HEADERS_FLAG_PADDED)) {
988 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
991 break;
992 case WINDOW_UPDATE:
993 if (current_frame_length_ != GetWindowUpdateSize()) {
994 set_error(SPDY_INVALID_CONTROL_FRAME);
995 } else if (current_frame_flags_ != 0) {
996 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
998 break;
999 case BLOCKED:
1000 if (current_frame_length_ != GetBlockedSize() ||
1001 protocol_version() <= SPDY3) {
1002 set_error(SPDY_INVALID_CONTROL_FRAME);
1003 } else if (current_frame_flags_ != 0) {
1004 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1006 break;
1007 case PUSH_PROMISE:
1008 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
1009 set_error(SPDY_INVALID_CONTROL_FRAME);
1010 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
1011 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1012 } else if (protocol_version() > SPDY3 &&
1013 current_frame_flags_ &
1014 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
1015 HEADERS_FLAG_PADDED)) {
1016 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1018 break;
1019 case CONTINUATION:
1020 if (current_frame_length_ < GetContinuationMinimumSize() ||
1021 protocol_version() <= SPDY3) {
1022 set_error(SPDY_INVALID_CONTROL_FRAME);
1023 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
1024 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1026 break;
1027 case ALTSVC:
1028 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
1029 set_error(SPDY_INVALID_CONTROL_FRAME);
1030 } else if (current_frame_flags_ != 0) {
1031 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1033 break;
1034 case PRIORITY:
1035 if (current_frame_length_ != GetPrioritySize() ||
1036 protocol_version() <= SPDY3) {
1037 set_error(SPDY_INVALID_CONTROL_FRAME);
1038 } else if (current_frame_flags_ != 0) {
1039 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1041 break;
1042 default:
1043 LOG(WARNING) << "Valid " << display_protocol_
1044 << " control frame with unhandled type: "
1045 << current_frame_type_;
1046 // This branch should be unreachable because of the frame type bounds
1047 // check above. However, we DLOG(FATAL) here in an effort to painfully
1048 // club the head of the developer who failed to keep this file in sync
1049 // with spdy_protocol.h.
1050 DLOG(FATAL);
1051 set_error(SPDY_INVALID_CONTROL_FRAME);
1052 break;
1055 if (state_ == SPDY_ERROR) {
1056 return;
1059 if (current_frame_length_ >
1060 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1061 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1062 DLOG(WARNING) << "Received control frame of type " << current_frame_type_
1063 << " with way too big of a payload: "
1064 << current_frame_length_;
1065 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1066 return;
1069 if (current_frame_type_ == GOAWAY) {
1070 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1071 return;
1074 if (current_frame_type_ == RST_STREAM) {
1075 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1076 return;
1079 if (current_frame_type_ == ALTSVC) {
1080 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1081 return;
1083 // Determine the frame size without variable-length data.
1084 int32 frame_size_without_variable_data;
1085 switch (current_frame_type_) {
1086 case SYN_STREAM:
1087 syn_frame_processed_ = true;
1088 frame_size_without_variable_data = GetSynStreamMinimumSize();
1089 break;
1090 case SYN_REPLY:
1091 syn_frame_processed_ = true;
1092 frame_size_without_variable_data = GetSynReplyMinimumSize();
1093 break;
1094 case SETTINGS:
1095 frame_size_without_variable_data = GetSettingsMinimumSize();
1096 break;
1097 case HEADERS:
1098 frame_size_without_variable_data = GetHeadersMinimumSize();
1099 if (protocol_version() > SPDY3) {
1100 if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
1101 frame_size_without_variable_data += kPadLengthFieldSize;
1103 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1104 frame_size_without_variable_data +=
1105 kPriorityDependencyPayloadSize +
1106 kPriorityWeightPayloadSize;
1109 break;
1110 case PUSH_PROMISE:
1111 frame_size_without_variable_data = GetPushPromiseMinimumSize();
1112 if (protocol_version() > SPDY3 &&
1113 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1114 frame_size_without_variable_data += kPadLengthFieldSize;
1116 break;
1117 case CONTINUATION:
1118 frame_size_without_variable_data = GetContinuationMinimumSize();
1119 break;
1120 default:
1121 frame_size_without_variable_data = -1;
1122 break;
1125 if ((frame_size_without_variable_data == -1) &&
1126 (current_frame_length_ > kControlFrameBufferSize)) {
1127 // We should already be in an error state. Double-check.
1128 DCHECK_EQ(SPDY_ERROR, state_);
1129 if (state_ != SPDY_ERROR) {
1130 LOG(DFATAL) << display_protocol_
1131 << " control frame buffer too small for fixed-length frame.";
1132 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1134 return;
1137 if (frame_size_without_variable_data > 0) {
1138 // We have a control frame with a header block. We need to parse the
1139 // remainder of the control frame's header before we can parse the header
1140 // block. The start of the header block varies with the control type.
1141 DCHECK_GE(frame_size_without_variable_data,
1142 static_cast<int32>(current_frame_buffer_length_));
1143 remaining_control_header_ = frame_size_without_variable_data -
1144 current_frame_buffer_length_;
1146 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1147 return;
1150 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1153 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1154 size_t max_bytes) {
1155 size_t bytes_to_read = std::min(*len, max_bytes);
1156 if (bytes_to_read > 0) {
1157 DCHECK_GE(kControlFrameBufferSize,
1158 current_frame_buffer_length_ + bytes_to_read);
1159 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1160 *data,
1161 bytes_to_read);
1162 current_frame_buffer_length_ += bytes_to_read;
1163 *data += bytes_to_read;
1164 *len -= bytes_to_read;
1166 return bytes_to_read;
1169 size_t SpdyFramer::GetSerializedLength(
1170 const SpdyMajorVersion spdy_version,
1171 const SpdyHeaderBlock* headers) {
1172 const size_t num_name_value_pairs_size
1173 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1174 const size_t length_of_name_size = num_name_value_pairs_size;
1175 const size_t length_of_value_size = num_name_value_pairs_size;
1177 size_t total_length = num_name_value_pairs_size;
1178 for (SpdyHeaderBlock::const_iterator it = headers->begin();
1179 it != headers->end();
1180 ++it) {
1181 // We add space for the length of the name and the length of the value as
1182 // well as the length of the name and the length of the value.
1183 total_length += length_of_name_size + it->first.size() +
1184 length_of_value_size + it->second.size();
1186 return total_length;
1189 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1190 const SpdyMajorVersion spdy_version,
1191 const SpdyHeaderBlock* headers) {
1192 if (spdy_version < SPDY3) {
1193 frame->WriteUInt16(static_cast<uint16>(headers->size()));
1194 } else {
1195 frame->WriteUInt32(headers->size());
1197 SpdyHeaderBlock::const_iterator it;
1198 for (it = headers->begin(); it != headers->end(); ++it) {
1199 if (spdy_version < SPDY3) {
1200 frame->WriteStringPiece16(it->first);
1201 frame->WriteStringPiece16(it->second);
1202 } else {
1203 frame->WriteStringPiece32(it->first);
1204 frame->WriteStringPiece32(it->second);
1209 // TODO(phajdan.jr): Clean up after we no longer need
1210 // to workaround http://crbug.com/139744.
1211 #if !defined(USE_SYSTEM_ZLIB)
1213 // These constants are used by zlib to differentiate between normal data and
1214 // cookie data. Cookie data is handled specially by zlib when compressing.
1215 enum ZDataClass {
1216 // kZStandardData is compressed normally, save that it will never match
1217 // against any other class of data in the window.
1218 kZStandardData = Z_CLASS_STANDARD,
1219 // kZCookieData is compressed in its own Huffman blocks and only matches in
1220 // its entirety and only against other kZCookieData blocks. Any matches must
1221 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1222 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1223 // prefix matches.
1224 kZCookieData = Z_CLASS_COOKIE,
1225 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1226 // against the window.
1227 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1230 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1231 // needed when switching between classes of data.
1232 static void WriteZ(const base::StringPiece& data,
1233 ZDataClass clas,
1234 z_stream* out) {
1235 int rv;
1237 // If we are switching from standard to non-standard data then we need to end
1238 // the current Huffman context to avoid it leaking between them.
1239 if (out->clas == kZStandardData &&
1240 clas != kZStandardData) {
1241 out->avail_in = 0;
1242 rv = deflate(out, Z_PARTIAL_FLUSH);
1243 DCHECK_EQ(Z_OK, rv);
1244 DCHECK_EQ(0u, out->avail_in);
1245 DCHECK_LT(0u, out->avail_out);
1248 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1249 out->avail_in = data.size();
1250 out->clas = clas;
1251 if (clas == kZStandardData) {
1252 rv = deflate(out, Z_NO_FLUSH);
1253 } else {
1254 rv = deflate(out, Z_PARTIAL_FLUSH);
1256 if (!data.empty()) {
1257 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1258 DCHECK_EQ(Z_OK, rv);
1260 DCHECK_EQ(0u, out->avail_in);
1261 DCHECK_LT(0u, out->avail_out);
1264 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1265 static void WriteLengthZ(size_t n,
1266 unsigned length,
1267 ZDataClass clas,
1268 z_stream* out) {
1269 char buf[4];
1270 DCHECK_LE(length, sizeof(buf));
1271 for (unsigned i = 1; i <= length; i++) {
1272 buf[length - i] = static_cast<char>(n);
1273 n >>= 8;
1275 WriteZ(base::StringPiece(buf, length), clas, out);
1278 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1279 // manner that resists the length of the compressed data from compromising
1280 // cookie data.
1281 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1282 z_stream* z) const {
1283 unsigned length_length = 4;
1284 if (protocol_version() < 3)
1285 length_length = 2;
1287 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1289 std::map<std::string, std::string>::const_iterator it;
1290 for (it = headers->begin(); it != headers->end(); ++it) {
1291 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1292 WriteZ(it->first, kZStandardData, z);
1294 if (it->first == "cookie") {
1295 // We require the cookie values (save for the last) to end with a
1296 // semicolon and (save for the first) to start with a space. This is
1297 // typically the format that we are given them in but we reserialize them
1298 // to be sure.
1300 std::vector<base::StringPiece> cookie_values;
1301 size_t cookie_length = 0;
1302 base::StringPiece cookie_data(it->second);
1304 for (;;) {
1305 while (!cookie_data.empty() &&
1306 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1307 cookie_data.remove_prefix(1);
1309 if (cookie_data.empty())
1310 break;
1312 size_t i;
1313 for (i = 0; i < cookie_data.size(); i++) {
1314 if (cookie_data[i] == ';')
1315 break;
1317 if (i < cookie_data.size()) {
1318 if (!IsCookieEmpty(cookie_data.substr(0, i))) {
1319 cookie_values.push_back(cookie_data.substr(0, i));
1320 cookie_length += i + 2 /* semicolon and space */;
1322 cookie_data.remove_prefix(i + 1);
1323 } else {
1324 if (!IsCookieEmpty(cookie_data)) {
1325 cookie_values.push_back(cookie_data);
1326 cookie_length += cookie_data.size();
1327 } else if (cookie_length > 2) {
1328 cookie_length -= 2 /* compensate for previously added length */;
1330 cookie_data.remove_prefix(i);
1334 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1335 for (size_t i = 0; i < cookie_values.size(); i++) {
1336 std::string cookie;
1337 // Since zlib will only back-reference complete cookies, a cookie that
1338 // is currently last (and so doesn't have a trailing semicolon) won't
1339 // match if it's later in a non-final position. The same is true of
1340 // the first cookie.
1341 if (i == 0 && cookie_values.size() == 1) {
1342 cookie = cookie_values[i].as_string();
1343 } else if (i == 0) {
1344 cookie = cookie_values[i].as_string() + ";";
1345 } else if (i < cookie_values.size() - 1) {
1346 cookie = " " + cookie_values[i].as_string() + ";";
1347 } else {
1348 cookie = " " + cookie_values[i].as_string();
1350 WriteZ(cookie, kZCookieData, z);
1352 } else if (it->first == "accept" ||
1353 it->first == "accept-charset" ||
1354 it->first == "accept-encoding" ||
1355 it->first == "accept-language" ||
1356 it->first == "host" ||
1357 it->first == "version" ||
1358 it->first == "method" ||
1359 it->first == "scheme" ||
1360 it->first == ":host" ||
1361 it->first == ":version" ||
1362 it->first == ":method" ||
1363 it->first == ":scheme" ||
1364 it->first == "user-agent") {
1365 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1366 WriteZ(it->second, kZStandardData, z);
1367 } else {
1368 // Non-whitelisted headers are Huffman compressed in their own block, but
1369 // don't match against the window.
1370 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1371 WriteZ(it->second, kZHuffmanOnlyData, z);
1375 z->avail_in = 0;
1376 int rv = deflate(z, Z_SYNC_FLUSH);
1377 DCHECK_EQ(Z_OK, rv);
1378 z->clas = kZStandardData;
1381 #endif // !defined(USE_SYSTEM_ZLIB)
1383 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1384 size_t len) {
1385 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1386 const size_t original_len = len;
1388 if (remaining_control_header_ > 0) {
1389 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1390 remaining_control_header_);
1391 remaining_control_header_ -= bytes_read;
1392 remaining_data_length_ -= bytes_read;
1395 if (remaining_control_header_ == 0) {
1396 SpdyFrameReader reader(current_frame_buffer_.get(),
1397 current_frame_buffer_length_);
1398 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1400 switch (current_frame_type_) {
1401 case SYN_STREAM:
1403 DCHECK_GE(SPDY3, protocol_version());
1404 bool successful_read = true;
1405 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1406 DCHECK(successful_read);
1407 if (current_frame_stream_id_ == 0) {
1408 set_error(SPDY_INVALID_CONTROL_FRAME);
1409 break;
1412 SpdyStreamId associated_to_stream_id = kInvalidStream;
1413 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1414 DCHECK(successful_read);
1416 SpdyPriority priority = 0;
1417 successful_read = reader.ReadUInt8(&priority);
1418 DCHECK(successful_read);
1419 if (protocol_version() <= SPDY2) {
1420 priority = priority >> 6;
1421 } else {
1422 priority = priority >> 5;
1425 // Seek past unused byte; used to be credential slot in SPDY 3.
1426 reader.Seek(1);
1428 DCHECK(reader.IsDoneReading());
1429 if (debug_visitor_) {
1430 debug_visitor_->OnReceiveCompressedFrame(
1431 current_frame_stream_id_,
1432 current_frame_type_,
1433 current_frame_length_);
1435 visitor_->OnSynStream(
1436 current_frame_stream_id_,
1437 associated_to_stream_id,
1438 priority,
1439 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1440 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1442 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1443 break;
1444 case SETTINGS:
1445 if (protocol_version() > SPDY3 &&
1446 current_frame_flags_ & SETTINGS_FLAG_ACK) {
1447 visitor_->OnSettingsAck();
1448 CHANGE_STATE(SPDY_AUTO_RESET);
1449 } else {
1450 visitor_->OnSettings(current_frame_flags_ &
1451 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1452 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1454 break;
1455 case SYN_REPLY:
1456 case HEADERS:
1457 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1459 if (protocol_version() > SPDY3) {
1460 DCHECK_EQ(HEADERS, current_frame_type_);
1462 bool successful_read = true;
1463 if (protocol_version() <= SPDY3) {
1464 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1465 DCHECK(successful_read);
1467 if (current_frame_stream_id_ == 0) {
1468 set_error(SPDY_INVALID_CONTROL_FRAME);
1469 break;
1471 if (protocol_version() <= SPDY2) {
1472 // SPDY 2 had two unused bytes here. Seek past them.
1473 reader.Seek(2);
1475 if (protocol_version() > SPDY3 &&
1476 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1477 current_frame_type_ == HEADERS) {
1478 expect_continuation_ = current_frame_stream_id_;
1479 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1481 if (protocol_version() > SPDY3 &&
1482 current_frame_flags_ & HEADERS_FLAG_PADDED) {
1483 uint8 pad_payload_len = 0;
1484 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1485 successful_read = reader.ReadUInt8(&pad_payload_len);
1486 DCHECK(successful_read);
1487 remaining_padding_payload_length_ = pad_payload_len;
1489 const bool has_priority =
1490 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1491 SpdyPriority priority = 0;
1492 if (protocol_version() > SPDY3 && has_priority) {
1493 // TODO(jgraettinger): Process dependency rather than ignoring it.
1494 reader.Seek(kPriorityDependencyPayloadSize);
1495 uint8 weight = 0;
1496 successful_read = reader.ReadUInt8(&weight);
1497 if (successful_read) {
1498 priority = MapWeightToPriority(weight);
1501 DCHECK(reader.IsDoneReading());
1502 if (debug_visitor_) {
1503 debug_visitor_->OnReceiveCompressedFrame(
1504 current_frame_stream_id_,
1505 current_frame_type_,
1506 current_frame_length_);
1508 if (current_frame_type_ == SYN_REPLY) {
1509 visitor_->OnSynReply(
1510 current_frame_stream_id_,
1511 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1512 } else {
1513 visitor_->OnHeaders(
1514 current_frame_stream_id_,
1515 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, priority,
1516 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1517 expect_continuation_ == 0);
1520 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1521 break;
1522 case PUSH_PROMISE:
1524 DCHECK_LT(SPDY3, protocol_version());
1525 if (current_frame_stream_id_ == 0) {
1526 set_error(SPDY_INVALID_CONTROL_FRAME);
1527 break;
1529 bool successful_read = true;
1530 if (protocol_version() > SPDY3 &&
1531 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1532 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1533 uint8 pad_payload_len = 0;
1534 successful_read = reader.ReadUInt8(&pad_payload_len);
1535 DCHECK(successful_read);
1536 remaining_padding_payload_length_ = pad_payload_len;
1540 SpdyStreamId promised_stream_id = kInvalidStream;
1541 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1542 DCHECK(successful_read);
1543 DCHECK(reader.IsDoneReading());
1544 if (promised_stream_id == 0) {
1545 set_error(SPDY_INVALID_CONTROL_FRAME);
1546 break;
1548 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1549 expect_continuation_ = current_frame_stream_id_;
1551 if (debug_visitor_) {
1552 debug_visitor_->OnReceiveCompressedFrame(
1553 current_frame_stream_id_,
1554 current_frame_type_,
1555 current_frame_length_);
1557 visitor_->OnPushPromise(current_frame_stream_id_,
1558 promised_stream_id,
1559 (current_frame_flags_ &
1560 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1562 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1563 break;
1564 case CONTINUATION:
1566 // Check to make sure the stream id of the current frame is
1567 // the same as that of the preceding frame.
1568 // If we're at this point we should already know that
1569 // expect_continuation_ != 0, so this doubles as a check
1570 // that current_frame_stream_id != 0.
1571 if (current_frame_stream_id_ != expect_continuation_) {
1572 set_error(SPDY_INVALID_CONTROL_FRAME);
1573 break;
1575 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1576 expect_continuation_ = 0;
1578 if (debug_visitor_) {
1579 debug_visitor_->OnReceiveCompressedFrame(
1580 current_frame_stream_id_,
1581 current_frame_type_,
1582 current_frame_length_);
1584 visitor_->OnContinuation(current_frame_stream_id_,
1585 (current_frame_flags_ &
1586 HEADERS_FLAG_END_HEADERS) != 0);
1588 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1589 break;
1590 default:
1591 DCHECK(false);
1594 return original_len - len;
1597 // Does not buffer the control payload. Instead, either passes directly to the
1598 // visitor or decompresses and then passes directly to the visitor, via
1599 // IncrementallyDeliverControlFrameHeaderData() or
1600 // IncrementallyDecompressControlFrameHeaderData() respectively.
1601 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1602 size_t data_len,
1603 bool is_hpack_header_block) {
1604 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1606 bool processed_successfully = true;
1607 if (current_frame_type_ != SYN_STREAM &&
1608 current_frame_type_ != SYN_REPLY &&
1609 current_frame_type_ != HEADERS &&
1610 current_frame_type_ != PUSH_PROMISE &&
1611 current_frame_type_ != CONTINUATION) {
1612 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1614 size_t process_bytes = std::min(
1615 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1616 if (is_hpack_header_block) {
1617 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1618 current_frame_stream_id_, data, process_bytes)) {
1619 // TODO(jgraettinger): Finer-grained HPACK error codes.
1620 set_error(SPDY_DECOMPRESS_FAILURE);
1621 processed_successfully = false;
1623 } else if (process_bytes > 0) {
1624 if (enable_compression_ && protocol_version() <= SPDY3) {
1625 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1626 current_frame_stream_id_, data, process_bytes);
1627 } else {
1628 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1629 current_frame_stream_id_, data, process_bytes);
1632 remaining_data_length_ -= process_bytes;
1634 // Handle the case that there is no futher data in this frame.
1635 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1636 processed_successfully) {
1637 if (expect_continuation_ == 0) {
1638 if (is_hpack_header_block) {
1639 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1640 current_frame_stream_id_)) {
1641 set_error(SPDY_DECOMPRESS_FAILURE);
1642 processed_successfully = false;
1643 } else {
1644 // TODO(jgraettinger): To be removed with migration to
1645 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1646 // block, delivered via reentrant call to
1647 // ProcessControlFrameHeaderBlock().
1648 DeliverHpackBlockAsSpdy3Block();
1649 return process_bytes;
1651 } else {
1652 // The complete header block has been delivered. We send a zero-length
1653 // OnControlFrameHeaderData() to indicate this.
1654 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1657 if (processed_successfully) {
1658 CHANGE_STATE(SPDY_CONSUME_PADDING);
1662 // Handle error.
1663 if (!processed_successfully) {
1664 return data_len;
1667 // Return amount processed.
1668 return process_bytes;
1671 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1672 size_t data_len) {
1673 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1674 DCHECK_EQ(SETTINGS, current_frame_type_);
1675 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1676 size_t processed_bytes = 0;
1678 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
1680 // Loop over our incoming data.
1681 while (unprocessed_bytes > 0) {
1682 // Process up to one setting at a time.
1683 size_t processing = std::min(
1684 unprocessed_bytes,
1685 static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
1687 // Check if we have a complete setting in our input.
1688 if (processing == setting_size) {
1689 // Parse the setting directly out of the input without buffering.
1690 if (!ProcessSetting(data + processed_bytes)) {
1691 set_error(SPDY_INVALID_CONTROL_FRAME);
1692 return processed_bytes;
1694 } else {
1695 // Continue updating settings_scratch_.setting_buf.
1696 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1697 data + processed_bytes,
1698 processing);
1699 settings_scratch_.setting_buf_len += processing;
1701 // Check if we have a complete setting buffered.
1702 if (settings_scratch_.setting_buf_len == setting_size) {
1703 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1704 set_error(SPDY_INVALID_CONTROL_FRAME);
1705 return processed_bytes;
1707 // Reset settings_scratch_.setting_buf for our next setting.
1708 settings_scratch_.setting_buf_len = 0;
1712 // Iterate.
1713 unprocessed_bytes -= processing;
1714 processed_bytes += processing;
1717 // Check if we're done handling this SETTINGS frame.
1718 remaining_data_length_ -= processed_bytes;
1719 if (remaining_data_length_ == 0) {
1720 visitor_->OnSettingsEnd();
1721 CHANGE_STATE(SPDY_AUTO_RESET);
1724 return processed_bytes;
1727 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1728 DCHECK_LT(SPDY3, protocol_version());
1729 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1731 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
1732 if (block.empty()) {
1733 // Special-case this to make tests happy.
1734 ProcessControlFrameHeaderBlock(NULL, 0, false);
1735 return;
1737 SpdyFrameBuilder builder(
1738 GetSerializedLength(protocol_version(), &block),
1739 SPDY3);
1741 SerializeNameValueBlockWithoutCompression(&builder, block);
1742 scoped_ptr<SpdyFrame> frame(builder.take());
1744 // Preserve padding length, and reset it after the re-entrant call.
1745 size_t remaining_padding = remaining_padding_payload_length_;
1747 remaining_padding_payload_length_ = 0;
1748 remaining_data_length_ = frame->size();
1750 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1752 remaining_padding_payload_length_ = remaining_padding;
1753 remaining_data_length_ = remaining_padding;
1756 bool SpdyFramer::ProcessSetting(const char* data) {
1757 int id_field;
1758 SpdySettingsIds id;
1759 uint8 flags = 0;
1760 uint32 value;
1762 // Extract fields.
1763 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1764 if (protocol_version() <= SPDY3) {
1765 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1766 SettingsFlagsAndId id_and_flags =
1767 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1768 id_field = id_and_flags.id();
1769 flags = id_and_flags.flags();
1770 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1771 } else {
1772 id_field = ntohs(*(reinterpret_cast<const uint16*>(data)));
1773 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2)));
1776 // Validate id.
1777 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1778 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1779 if (protocol_version() <= SPDY3) {
1780 return false;
1781 } else {
1782 // In HTTP2 we ignore unknown settings for extensibility.
1783 return true;
1786 id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1788 if (protocol_version() <= SPDY3) {
1789 // Detect duplicates.
1790 if (id <= settings_scratch_.last_setting_id) {
1791 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1792 << " in " << display_protocol_ << " SETTINGS frame "
1793 << "(last setting id was "
1794 << settings_scratch_.last_setting_id << ").";
1795 return false;
1797 settings_scratch_.last_setting_id = id;
1799 // Validate flags.
1800 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1801 if ((flags & ~(kFlagsMask)) != 0) {
1802 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1803 << flags;
1804 return false;
1808 // Validation succeeded. Pass on to visitor.
1809 visitor_->OnSetting(id, flags, value);
1810 return true;
1813 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1814 size_t original_len = len;
1815 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1816 remaining_data_length_);
1817 remaining_data_length_ -= bytes_read;
1818 if (remaining_data_length_ == 0) {
1819 SpdyFrameReader reader(current_frame_buffer_.get(),
1820 current_frame_buffer_length_);
1821 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1823 // Use frame-specific handlers.
1824 switch (current_frame_type_) {
1825 case PING: {
1826 SpdyPingId id = 0;
1827 bool is_ack = protocol_version() > SPDY3 &&
1828 (current_frame_flags_ & PING_FLAG_ACK);
1829 bool successful_read = true;
1830 if (protocol_version() <= SPDY3) {
1831 uint32 id32 = 0;
1832 successful_read = reader.ReadUInt32(&id32);
1833 id = id32;
1834 } else {
1835 successful_read = reader.ReadUInt64(&id);
1837 DCHECK(successful_read);
1838 DCHECK(reader.IsDoneReading());
1839 visitor_->OnPing(id, is_ack);
1841 break;
1842 case WINDOW_UPDATE: {
1843 uint32 delta_window_size = 0;
1844 bool successful_read = true;
1845 if (protocol_version() <= SPDY3) {
1846 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1847 DCHECK(successful_read);
1849 successful_read = reader.ReadUInt32(&delta_window_size);
1850 DCHECK(successful_read);
1851 DCHECK(reader.IsDoneReading());
1852 visitor_->OnWindowUpdate(current_frame_stream_id_,
1853 delta_window_size);
1855 break;
1856 case BLOCKED: {
1857 DCHECK_LT(SPDY3, protocol_version());
1858 DCHECK(reader.IsDoneReading());
1859 visitor_->OnBlocked(current_frame_stream_id_);
1861 break;
1862 case PRIORITY: {
1863 DCHECK_LT(SPDY3, protocol_version());
1864 uint32 parent_stream_id;
1865 uint8 weight;
1866 bool exclusive;
1867 bool successful_read = true;
1868 successful_read = reader.ReadUInt32(&parent_stream_id);
1869 DCHECK(successful_read);
1870 // Exclusivity is indicated by a single bit flag.
1871 exclusive = (parent_stream_id >> 31) != 0;
1872 // Zero out the highest-order bit to get the parent stream id.
1873 parent_stream_id &= 0x7fffffff;
1874 successful_read = reader.ReadUInt8(&weight);
1875 DCHECK(successful_read);
1876 DCHECK(reader.IsDoneReading());
1877 visitor_->OnPriority(
1878 current_frame_stream_id_, parent_stream_id, weight, exclusive);
1880 break;
1881 default:
1882 // Unreachable.
1883 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1886 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1888 return original_len - len;
1891 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1892 if (len == 0) {
1893 return 0;
1895 // Clamp to the actual remaining payload.
1896 if (len > remaining_data_length_) {
1897 len = remaining_data_length_;
1899 size_t original_len = len;
1901 // Check if we had already read enough bytes to parse the GOAWAY header.
1902 const size_t header_size = GetGoAwayMinimumSize();
1903 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1904 bool already_parsed_header = (unread_header_bytes == 0);
1905 if (!already_parsed_header) {
1906 // Buffer the new GOAWAY header bytes we got.
1907 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1909 // Do we have enough to parse the constant size GOAWAY header?
1910 if (current_frame_buffer_length_ == header_size) {
1911 // Parse out the last good stream id.
1912 SpdyFrameReader reader(current_frame_buffer_.get(),
1913 current_frame_buffer_length_);
1914 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1915 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1916 DCHECK(successful_read);
1918 // In SPDYv3 and up, frames also specify a status code - parse it out.
1919 SpdyGoAwayStatus status = GOAWAY_OK;
1920 if (protocol_version() >= SPDY3) {
1921 uint32 status_raw = GOAWAY_OK;
1922 successful_read = reader.ReadUInt32(&status_raw);
1923 DCHECK(successful_read);
1924 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1925 status_raw)) {
1926 status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1927 status_raw);
1928 } else {
1929 if (protocol_version() > SPDY3) {
1930 // Treat unrecognized status codes as INTERNAL_ERROR as
1931 // recommended by the HTTP/2 spec.
1932 status = GOAWAY_INTERNAL_ERROR;
1936 // Finished parsing the GOAWAY header, call frame handler.
1937 visitor_->OnGoAway(current_frame_stream_id_, status);
1941 // Handle remaining data as opaque.
1942 bool processed_successfully = true;
1943 if (len > 0) {
1944 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1946 remaining_data_length_ -= original_len;
1947 if (!processed_successfully) {
1948 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1949 } else if (remaining_data_length_ == 0) {
1950 // Signal that there is not more opaque data.
1951 visitor_->OnGoAwayFrameData(NULL, 0);
1952 CHANGE_STATE(SPDY_AUTO_RESET);
1954 return original_len;
1957 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1958 if (len == 0) {
1959 return 0;
1961 // Clamp to the actual remaining payload.
1962 if (len > remaining_data_length_) {
1963 len = remaining_data_length_;
1965 size_t original_len = len;
1967 // Check if we had already read enough bytes to parse the fixed-length portion
1968 // of the RST_STREAM frame.
1969 const size_t header_size = GetRstStreamMinimumSize();
1970 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1971 bool already_parsed_header = (unread_header_bytes == 0);
1972 if (!already_parsed_header) {
1973 // Buffer the new RST_STREAM header bytes we got.
1974 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1976 // Do we have enough to parse the constant size RST_STREAM header?
1977 if (current_frame_buffer_length_ == header_size) {
1978 // Parse out the last good stream id.
1979 SpdyFrameReader reader(current_frame_buffer_.get(),
1980 current_frame_buffer_length_);
1981 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1982 if (protocol_version() <= SPDY3) {
1983 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1984 DCHECK(successful_read);
1987 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1988 uint32 status_raw = status;
1989 bool successful_read = reader.ReadUInt32(&status_raw);
1990 DCHECK(successful_read);
1991 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1992 status_raw)) {
1993 status =
1994 SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw);
1995 } else {
1996 if (protocol_version() > SPDY3) {
1997 // Treat unrecognized status codes as INTERNAL_ERROR as
1998 // recommended by the HTTP/2 spec.
1999 status = RST_STREAM_INTERNAL_ERROR;
2002 // Finished parsing the RST_STREAM header, call frame handler.
2003 visitor_->OnRstStream(current_frame_stream_id_, status);
2007 // Handle remaining data as opaque.
2008 bool processed_successfully = true;
2009 if (len > 0) {
2010 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
2012 remaining_data_length_ -= original_len;
2013 if (!processed_successfully) {
2014 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
2015 } else if (remaining_data_length_ == 0) {
2016 // Signal that there is not more opaque data.
2017 visitor_->OnRstStreamFrameData(NULL, 0);
2018 CHANGE_STATE(SPDY_AUTO_RESET);
2020 return original_len;
2023 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
2024 if (len == 0) {
2025 return 0;
2028 // Clamp to the actual remaining payload.
2029 len = std::min(len, remaining_data_length_);
2031 size_t processed_bytes = 0;
2032 size_t processing = 0;
2033 size_t bytes_remaining;
2034 char* buffer;
2035 size_t* buffer_len;
2037 while (len > 0) {
2038 if (altsvc_scratch_.pid_len == 0) {
2039 // The size of the frame up to the PID_LEN field.
2040 size_t fixed_len_portion = GetAltSvcMinimumSize() - 1;
2041 bytes_remaining = fixed_len_portion - current_frame_buffer_length_;
2042 processing = std::min(len, bytes_remaining);
2043 // Buffer the new ALTSVC bytes we got.
2044 UpdateCurrentFrameBuffer(&data, &len, processing);
2046 // Do we have enough to parse the length of the protocol id?
2047 if (current_frame_buffer_length_ == fixed_len_portion) {
2048 // Parse out the max age, port, and pid_len.
2049 SpdyFrameReader reader(current_frame_buffer_.get(),
2050 current_frame_buffer_length_);
2051 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2052 bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age);
2053 reader.ReadUInt16(&altsvc_scratch_.port);
2054 reader.Seek(1); // Reserved byte.
2055 successful_read = successful_read &&
2056 reader.ReadUInt8(&altsvc_scratch_.pid_len);
2057 DCHECK(successful_read);
2058 // Sanity check length value.
2059 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >=
2060 current_frame_length_) {
2061 set_error(SPDY_INVALID_CONTROL_FRAME);
2062 return 0;
2064 altsvc_scratch_.protocol_id.reset(
2065 new char[size_t(altsvc_scratch_.pid_len)]);
2067 processed_bytes += processing;
2068 continue;
2069 } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) {
2070 // Buffer protocol id field as in comes in.
2071 buffer = altsvc_scratch_.protocol_id.get();
2072 buffer_len = &altsvc_scratch_.pid_buf_len;
2073 bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len;
2074 } else if (altsvc_scratch_.host_len == 0) {
2075 // Parse out the host length.
2076 processing = 1;
2077 altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data);
2078 // Sanity check length value.
2079 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len +
2080 altsvc_scratch_.host_len > current_frame_length_) {
2081 set_error(SPDY_INVALID_CONTROL_FRAME);
2082 return 0;
2084 altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]);
2085 // Once we have host length, we can also determine the origin length
2086 // by process of elimination.
2087 altsvc_scratch_.origin_len = current_frame_length_ -
2088 GetAltSvcMinimumSize() -
2089 altsvc_scratch_.pid_len -
2090 altsvc_scratch_.host_len;
2091 if (altsvc_scratch_.origin_len > 0) {
2092 altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]);
2094 data += processing;
2095 processed_bytes += processing;
2096 len -= processing;
2097 continue;
2098 } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) {
2099 // Buffer host field as it comes in.
2100 // TODO(mlavan): check formatting for host and origin
2101 buffer = altsvc_scratch_.host.get();
2102 buffer_len = &altsvc_scratch_.host_buf_len;
2103 bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len;
2104 } else {
2105 // Buffer (optional) origin field as it comes in.
2106 if (altsvc_scratch_.origin_len <= 0) {
2107 set_error(SPDY_INVALID_CONTROL_FRAME);
2108 return 0;
2110 buffer = altsvc_scratch_.origin.get();
2111 buffer_len = &altsvc_scratch_.origin_buf_len;
2112 bytes_remaining = remaining_data_length_ -
2113 processed_bytes -
2114 altsvc_scratch_.origin_buf_len;
2115 if (len > bytes_remaining) {
2116 // This is our last field; there shouldn't be any more bytes.
2117 set_error(SPDY_INVALID_CONTROL_FRAME);
2118 return 0;
2122 // Copy data bytes into the appropriate field.
2123 processing = std::min(len, bytes_remaining);
2124 memcpy(buffer + *buffer_len,
2125 data,
2126 processing);
2127 *buffer_len += processing;
2128 data += processing;
2129 processed_bytes += processing;
2130 len -= processing;
2133 remaining_data_length_ -= processed_bytes;
2134 if (remaining_data_length_ == 0) {
2135 visitor_->OnAltSvc(current_frame_stream_id_,
2136 altsvc_scratch_.max_age,
2137 altsvc_scratch_.port,
2138 StringPiece(altsvc_scratch_.protocol_id.get(),
2139 altsvc_scratch_.pid_len),
2140 StringPiece(altsvc_scratch_.host.get(),
2141 altsvc_scratch_.host_len),
2142 StringPiece(altsvc_scratch_.origin.get(),
2143 altsvc_scratch_.origin_len));
2144 CHANGE_STATE(SPDY_AUTO_RESET);
2147 return processed_bytes;
2150 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
2151 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_);
2152 DCHECK_EQ(0u, remaining_padding_payload_length_);
2153 DCHECK_EQ(DATA, current_frame_type_);
2155 size_t original_len = len;
2156 if (current_frame_flags_ & DATA_FLAG_PADDED) {
2157 if (len != 0) {
2158 if (remaining_data_length_ < kPadLengthFieldSize) {
2159 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2160 return 0;
2163 static_assert(kPadLengthFieldSize == 1,
2164 "Unexpected pad length field size.");
2165 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data);
2166 ++data;
2167 --len;
2168 --remaining_data_length_;
2169 visitor_->OnStreamPadding(current_frame_stream_id_, kPadLengthFieldSize);
2170 } else {
2171 // We don't have the data available for parsing the pad length field. Keep
2172 // waiting.
2173 return 0;
2177 if (remaining_padding_payload_length_ > remaining_data_length_) {
2178 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2179 return 0;
2181 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2182 return original_len - len;
2185 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2186 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2188 size_t original_len = len;
2189 if (remaining_padding_payload_length_ > 0) {
2190 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2191 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2192 if (current_frame_type_ == DATA && amount_to_discard > 0) {
2193 DCHECK_LE(SPDY4, protocol_version());
2194 visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
2196 data += amount_to_discard;
2197 len -= amount_to_discard;
2198 remaining_padding_payload_length_ -= amount_to_discard;
2199 remaining_data_length_ -= amount_to_discard;
2202 if (remaining_data_length_ == 0) {
2203 // If the FIN flag is set, or this ends a header block which set FIN,
2204 // inform the visitor of EOF via a 0-length data frame.
2205 if (expect_continuation_ == 0 &&
2206 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2207 end_stream_when_done_)) {
2208 end_stream_when_done_ = false;
2209 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2211 CHANGE_STATE(SPDY_AUTO_RESET);
2213 return original_len - len;
2216 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2217 size_t original_len = len;
2218 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2219 size_t amount_to_forward = std::min(
2220 remaining_data_length_ - remaining_padding_payload_length_, len);
2221 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2222 // Only inform the visitor if there is data.
2223 if (amount_to_forward) {
2224 visitor_->OnStreamFrameData(
2225 current_frame_stream_id_, data, amount_to_forward, false);
2228 data += amount_to_forward;
2229 len -= amount_to_forward;
2230 remaining_data_length_ -= amount_to_forward;
2233 if (remaining_data_length_ == remaining_padding_payload_length_) {
2234 CHANGE_STATE(SPDY_CONSUME_PADDING);
2236 return original_len - len;
2239 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2240 size_t len) {
2241 size_t original_len = len;
2242 if (remaining_data_length_ > 0) {
2243 size_t amount_to_ignore = std::min(remaining_data_length_, len);
2244 len -= amount_to_ignore;
2245 remaining_data_length_ -= amount_to_ignore;
2248 if (remaining_data_length_ == 0) {
2249 CHANGE_STATE(SPDY_AUTO_RESET);
2251 return original_len - len;
2254 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2255 size_t header_length,
2256 SpdyHeaderBlock* block) const {
2257 SpdyFrameReader reader(header_data, header_length);
2259 // Read number of headers.
2260 uint32 num_headers;
2261 if (protocol_version() <= SPDY2) {
2262 uint16 temp;
2263 if (!reader.ReadUInt16(&temp)) {
2264 DVLOG(1) << "Unable to read number of headers.";
2265 return 0;
2267 num_headers = temp;
2268 } else {
2269 if (!reader.ReadUInt32(&num_headers)) {
2270 DVLOG(1) << "Unable to read number of headers.";
2271 return 0;
2275 // Read each header.
2276 for (uint32 index = 0; index < num_headers; ++index) {
2277 base::StringPiece temp;
2279 // Read header name.
2280 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2281 : !reader.ReadStringPiece32(&temp)) {
2282 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2283 << num_headers << ").";
2284 return 0;
2286 std::string name = temp.as_string();
2288 // Read header value.
2289 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2290 : !reader.ReadStringPiece32(&temp)) {
2291 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2292 << num_headers << ").";
2293 return 0;
2295 std::string value = temp.as_string();
2297 // Ensure no duplicates.
2298 if (block->find(name) != block->end()) {
2299 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2300 << num_headers << ").";
2301 return 0;
2304 // Store header.
2305 (*block)[name] = value;
2307 return reader.GetBytesConsumed();
2310 SpdySerializedFrame* SpdyFramer::SerializeData(
2311 const SpdyDataIR& data_ir) const {
2312 uint8 flags = DATA_FLAG_NONE;
2313 if (data_ir.fin()) {
2314 flags = DATA_FLAG_FIN;
2317 if (protocol_version() > SPDY3) {
2318 int num_padding_fields = 0;
2319 if (data_ir.padded()) {
2320 flags |= DATA_FLAG_PADDED;
2321 ++num_padding_fields;
2324 const size_t size_with_padding = num_padding_fields +
2325 data_ir.data().length() + data_ir.padding_payload_len() +
2326 GetDataFrameMinimumSize();
2327 SpdyFrameBuilder builder(size_with_padding, protocol_version());
2328 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2329 if (data_ir.padded()) {
2330 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2332 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2333 if (data_ir.padding_payload_len() > 0) {
2334 string padding(data_ir.padding_payload_len(), 0);
2335 builder.WriteBytes(padding.data(), padding.length());
2337 DCHECK_EQ(size_with_padding, builder.length());
2338 return builder.take();
2339 } else {
2340 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2341 SpdyFrameBuilder builder(size, protocol_version());
2342 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2343 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2344 DCHECK_EQ(size, builder.length());
2345 return builder.take();
2349 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2350 const SpdyDataIR& data_ir) const {
2351 uint8 flags = DATA_FLAG_NONE;
2352 if (data_ir.fin()) {
2353 flags = DATA_FLAG_FIN;
2356 size_t frame_size = GetDataFrameMinimumSize();
2357 size_t num_padding_fields = 0;
2358 if (protocol_version() > SPDY3) {
2359 if (data_ir.padded()) {
2360 flags |= DATA_FLAG_PADDED;
2361 ++num_padding_fields;
2363 frame_size += num_padding_fields;
2366 SpdyFrameBuilder builder(frame_size, protocol_version());
2367 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2368 if (protocol_version() > SPDY3) {
2369 if (data_ir.padded()) {
2370 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2372 builder.OverwriteLength(*this, num_padding_fields +
2373 data_ir.data().length() + data_ir.padding_payload_len());
2374 } else {
2375 builder.OverwriteLength(*this, data_ir.data().length());
2377 DCHECK_EQ(frame_size, builder.length());
2378 return builder.take();
2381 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2382 const SpdySynStreamIR& syn_stream) {
2383 DCHECK_GE(SPDY3, protocol_version());
2384 uint8 flags = 0;
2385 if (syn_stream.fin()) {
2386 flags |= CONTROL_FLAG_FIN;
2388 if (syn_stream.unidirectional()) {
2389 // TODO(hkhalil): invalid for HTTP2.
2390 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2393 // Sanitize priority.
2394 uint8 priority = syn_stream.priority();
2395 if (priority > GetLowestPriority()) {
2396 DLOG(DFATAL) << "Priority out-of-bounds.";
2397 priority = GetLowestPriority();
2400 // The size of this frame, including variable-length name-value block.
2401 size_t size = GetSynStreamMinimumSize() +
2402 GetSerializedLength(syn_stream.name_value_block());
2404 SpdyFrameBuilder builder(size, protocol_version());
2405 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2406 builder.WriteUInt32(syn_stream.stream_id());
2407 builder.WriteUInt32(syn_stream.associated_to_stream_id());
2408 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2409 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
2410 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2411 SerializeNameValueBlock(&builder, syn_stream);
2413 if (debug_visitor_) {
2414 const size_t payload_len =
2415 GetSerializedLength(protocol_version(),
2416 &(syn_stream.name_value_block()));
2417 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2418 SYN_STREAM,
2419 payload_len,
2420 builder.length());
2423 return builder.take();
2426 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2427 const SpdySynReplyIR& syn_reply) {
2428 DCHECK_GE(SPDY3, protocol_version());
2429 uint8 flags = 0;
2430 if (syn_reply.fin()) {
2431 flags |= CONTROL_FLAG_FIN;
2434 // The size of this frame, including variable-length name-value block.
2435 const size_t size = GetSynReplyMinimumSize() +
2436 GetSerializedLength(syn_reply.name_value_block());
2438 SpdyFrameBuilder builder(size, protocol_version());
2439 if (protocol_version() <= SPDY3) {
2440 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2441 builder.WriteUInt32(syn_reply.stream_id());
2442 } else {
2443 builder.BeginNewFrame(*this,
2444 HEADERS,
2445 flags,
2446 syn_reply.stream_id());
2448 if (protocol_version() < SPDY3) {
2449 builder.WriteUInt16(0); // Unused.
2451 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2452 SerializeNameValueBlock(&builder, syn_reply);
2454 if (debug_visitor_) {
2455 const size_t payload_len = GetSerializedLength(
2456 protocol_version(), &(syn_reply.name_value_block()));
2457 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2458 SYN_REPLY,
2459 payload_len,
2460 builder.length());
2463 return builder.take();
2466 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2467 const SpdyRstStreamIR& rst_stream) const {
2468 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2469 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2470 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2471 // commented but left in place to simplify future patching.
2472 // Compute the output buffer size, taking opaque data into account.
2473 size_t expected_length = GetRstStreamMinimumSize();
2474 if (protocol_version() > SPDY3) {
2475 expected_length += rst_stream.description().size();
2477 SpdyFrameBuilder builder(expected_length, protocol_version());
2479 // Serialize the RST_STREAM frame.
2480 if (protocol_version() <= SPDY3) {
2481 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2482 builder.WriteUInt32(rst_stream.stream_id());
2483 } else {
2484 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2487 builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
2488 protocol_version(), rst_stream.status()));
2490 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2491 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2492 builder.WriteBytes(rst_stream.description().data(),
2493 rst_stream.description().size());
2496 DCHECK_EQ(expected_length, builder.length());
2497 return builder.take();
2500 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2501 const SpdySettingsIR& settings) const {
2502 uint8 flags = 0;
2504 if (protocol_version() <= SPDY3) {
2505 if (settings.clear_settings()) {
2506 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2508 } else {
2509 if (settings.is_ack()) {
2510 flags |= SETTINGS_FLAG_ACK;
2513 const SpdySettingsIR::ValueMap* values = &(settings.values());
2515 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
2516 // Size, in bytes, of this SETTINGS frame.
2517 const size_t size = GetSettingsMinimumSize() +
2518 (values->size() * setting_size);
2519 SpdyFrameBuilder builder(size, protocol_version());
2520 if (protocol_version() <= SPDY3) {
2521 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2522 } else {
2523 builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2526 // If this is an ACK, payload should be empty.
2527 if (protocol_version() > SPDY3 && settings.is_ack()) {
2528 return builder.take();
2531 if (protocol_version() <= SPDY3) {
2532 builder.WriteUInt32(values->size());
2534 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2535 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2536 it != values->end();
2537 ++it) {
2538 int setting_id =
2539 SpdyConstants::SerializeSettingId(protocol_version(), it->first);
2540 DCHECK_GE(setting_id, 0);
2541 if (protocol_version() <= SPDY3) {
2542 uint8 setting_flags = 0;
2543 if (it->second.persist_value) {
2544 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2546 if (it->second.persisted) {
2547 setting_flags |= SETTINGS_FLAG_PERSISTED;
2549 SettingsFlagsAndId flags_and_id(setting_flags, setting_id);
2550 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2551 builder.WriteBytes(&id_and_flags_wire, 4);
2552 } else {
2553 builder.WriteUInt16(static_cast<uint16>(setting_id));
2555 builder.WriteUInt32(it->second.value);
2557 DCHECK_EQ(size, builder.length());
2558 return builder.take();
2561 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2562 SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2563 if (protocol_version() <= SPDY3) {
2564 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2565 builder.WriteUInt32(static_cast<uint32>(ping.id()));
2566 } else {
2567 uint8 flags = 0;
2568 if (ping.is_ack()) {
2569 flags |= PING_FLAG_ACK;
2571 builder.BeginNewFrame(*this, PING, flags, 0);
2572 builder.WriteUInt64(ping.id());
2574 DCHECK_EQ(GetPingSize(), builder.length());
2575 return builder.take();
2578 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2579 const SpdyGoAwayIR& goaway) const {
2581 // Compute the output buffer size, take opaque data into account.
2582 size_t expected_length = GetGoAwayMinimumSize();
2583 if (protocol_version() > SPDY3) {
2584 expected_length += goaway.description().size();
2586 SpdyFrameBuilder builder(expected_length, protocol_version());
2588 // Serialize the GOAWAY frame.
2589 if (protocol_version() <= SPDY3) {
2590 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2591 } else {
2592 builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2595 // GOAWAY frames specify the last good stream id for all SPDY versions.
2596 builder.WriteUInt32(goaway.last_good_stream_id());
2598 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2599 if (protocol_version() >= SPDY3) {
2600 // TODO(jgraettinger): Merge back to server-side.
2601 builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2602 goaway.status()));
2605 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2606 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2607 builder.WriteBytes(goaway.description().data(),
2608 goaway.description().size());
2611 DCHECK_EQ(expected_length, builder.length());
2612 return builder.take();
2615 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2616 const SpdyHeadersIR& headers) {
2617 uint8 flags = 0;
2618 if (headers.fin()) {
2619 flags |= CONTROL_FLAG_FIN;
2621 if (protocol_version() > SPDY3) {
2622 // This will get overwritten if we overflow into a CONTINUATION frame.
2623 flags |= HEADERS_FLAG_END_HEADERS;
2624 if (headers.has_priority()) {
2625 flags |= HEADERS_FLAG_PRIORITY;
2627 if (headers.padded()) {
2628 flags |= HEADERS_FLAG_PADDED;
2632 // The size of this frame, including padding (if there is any)
2633 // and variable-length name-value block.
2634 size_t size = GetHeadersMinimumSize();
2636 if (protocol_version() > SPDY3 && headers.padded()) {
2637 size += kPadLengthFieldSize;
2638 size += headers.padding_payload_len();
2641 SpdyPriority priority = static_cast<SpdyPriority>(headers.priority());
2642 if (headers.has_priority()) {
2643 if (headers.priority() > GetLowestPriority()) {
2644 DLOG(DFATAL) << "Priority out-of-bounds.";
2645 priority = GetLowestPriority();
2647 size += 5;
2650 string hpack_encoding;
2651 if (protocol_version() > SPDY3) {
2652 if (enable_compression_) {
2653 GetHpackEncoder()->EncodeHeaderSet(
2654 headers.name_value_block(), &hpack_encoding);
2655 } else {
2656 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2657 headers.name_value_block(), &hpack_encoding);
2659 size += hpack_encoding.size();
2660 if (size > kMaxControlFrameSize) {
2661 size += GetNumberRequiredContinuationFrames(size) *
2662 GetContinuationMinimumSize();
2663 flags &= ~HEADERS_FLAG_END_HEADERS;
2665 } else {
2666 size += GetSerializedLength(headers.name_value_block());
2669 SpdyFrameBuilder builder(size, protocol_version());
2670 if (protocol_version() <= SPDY3) {
2671 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2672 builder.WriteUInt32(headers.stream_id());
2673 } else {
2674 builder.BeginNewFrame(*this,
2675 HEADERS,
2676 flags,
2677 headers.stream_id());
2679 if (protocol_version() <= SPDY2) {
2680 builder.WriteUInt16(0); // Unused.
2682 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2684 if (protocol_version() > SPDY3) {
2685 int padding_payload_len = 0;
2686 if (headers.padded()) {
2687 builder.WriteUInt8(headers.padding_payload_len());
2688 padding_payload_len = headers.padding_payload_len();
2690 if (headers.has_priority()) {
2691 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2692 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2693 builder.WriteUInt8(MapPriorityToWeight(priority));
2695 WritePayloadWithContinuation(&builder,
2696 hpack_encoding,
2697 headers.stream_id(),
2698 HEADERS,
2699 padding_payload_len);
2700 } else {
2701 SerializeNameValueBlock(&builder, headers);
2704 if (debug_visitor_) {
2705 // SPDY4 uses HPACK for header compression. However, continue to
2706 // use GetSerializedLength() for an apples-to-apples comparision of
2707 // compression performance between HPACK and SPDY w/ deflate.
2708 const size_t payload_len =
2709 GetSerializedLength(protocol_version(),
2710 &(headers.name_value_block()));
2711 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2712 HEADERS,
2713 payload_len,
2714 builder.length());
2717 return builder.take();
2720 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2721 const SpdyWindowUpdateIR& window_update) const {
2722 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2723 if (protocol_version() <= SPDY3) {
2724 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2725 builder.WriteUInt32(window_update.stream_id());
2726 } else {
2727 builder.BeginNewFrame(*this,
2728 WINDOW_UPDATE,
2729 kNoFlags,
2730 window_update.stream_id());
2732 builder.WriteUInt32(window_update.delta());
2733 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2734 return builder.take();
2737 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2738 DCHECK_LT(SPDY3, protocol_version());
2739 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2740 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2741 return builder.take();
2744 SpdyFrame* SpdyFramer::SerializePushPromise(
2745 const SpdyPushPromiseIR& push_promise) {
2746 DCHECK_LT(SPDY3, protocol_version());
2747 uint8 flags = 0;
2748 // This will get overwritten if we overflow into a CONTINUATION frame.
2749 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2750 // The size of this frame, including variable-length name-value block.
2751 size_t size = GetPushPromiseMinimumSize();
2753 if (push_promise.padded()) {
2754 flags |= PUSH_PROMISE_FLAG_PADDED;
2755 size += kPadLengthFieldSize;
2756 size += push_promise.padding_payload_len();
2759 string hpack_encoding;
2760 if (enable_compression_) {
2761 GetHpackEncoder()->EncodeHeaderSet(
2762 push_promise.name_value_block(), &hpack_encoding);
2763 } else {
2764 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2765 push_promise.name_value_block(), &hpack_encoding);
2767 size += hpack_encoding.size();
2768 if (size > kMaxControlFrameSize) {
2769 size += GetNumberRequiredContinuationFrames(size) *
2770 GetContinuationMinimumSize();
2771 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2774 SpdyFrameBuilder builder(size, protocol_version());
2775 builder.BeginNewFrame(*this,
2776 PUSH_PROMISE,
2777 flags,
2778 push_promise.stream_id());
2779 int padding_payload_len = 0;
2780 if (push_promise.padded()) {
2781 builder.WriteUInt8(push_promise.padding_payload_len());
2782 builder.WriteUInt32(push_promise.promised_stream_id());
2783 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
2784 builder.length());
2786 padding_payload_len = push_promise.padding_payload_len();
2787 } else {
2788 builder.WriteUInt32(push_promise.promised_stream_id());
2789 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2792 WritePayloadWithContinuation(&builder,
2793 hpack_encoding,
2794 push_promise.stream_id(),
2795 PUSH_PROMISE,
2796 padding_payload_len);
2798 if (debug_visitor_) {
2799 // SPDY4 uses HPACK for header compression. However, continue to
2800 // use GetSerializedLength() for an apples-to-apples comparision of
2801 // compression performance between HPACK and SPDY w/ deflate.
2802 const size_t payload_len =
2803 GetSerializedLength(protocol_version(),
2804 &(push_promise.name_value_block()));
2805 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2806 PUSH_PROMISE,
2807 payload_len,
2808 builder.length());
2811 return builder.take();
2814 // TODO(jgraettinger): This implementation is incorrect. The continuation
2815 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2816 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2817 SpdyFrame* SpdyFramer::SerializeContinuation(
2818 const SpdyContinuationIR& continuation) {
2819 CHECK_LT(SPDY3, protocol_version());
2820 uint8 flags = 0;
2821 if (continuation.end_headers()) {
2822 flags |= HEADERS_FLAG_END_HEADERS;
2825 // The size of this frame, including variable-length name-value block.
2826 size_t size = GetContinuationMinimumSize();
2827 string hpack_encoding;
2828 if (enable_compression_) {
2829 GetHpackEncoder()->EncodeHeaderSet(
2830 continuation.name_value_block(), &hpack_encoding);
2831 } else {
2832 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2833 continuation.name_value_block(), &hpack_encoding);
2835 size += hpack_encoding.size();
2837 SpdyFrameBuilder builder(size, protocol_version());
2838 builder.BeginNewFrame(*this, CONTINUATION, flags,
2839 continuation.stream_id());
2840 DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2842 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2843 return builder.take();
2846 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
2847 DCHECK_LT(SPDY3, protocol_version());
2848 size_t size = GetAltSvcMinimumSize();
2849 size += altsvc.protocol_id().length();
2850 size += altsvc.host().length();
2851 size += altsvc.origin().length();
2853 SpdyFrameBuilder builder(size, protocol_version());
2854 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
2856 // TODO(bnc): http://crbug.com/438263
2857 // Update the binary format here to the new text-based payload format.
2858 builder.WriteUInt32(altsvc.max_age());
2859 builder.WriteUInt16(altsvc.port());
2860 builder.WriteUInt8(0); // Reserved.
2861 builder.WriteUInt8(static_cast<uint8>(altsvc.protocol_id().length()));
2862 builder.WriteBytes(altsvc.protocol_id().data(),
2863 altsvc.protocol_id().length());
2864 builder.WriteUInt8(static_cast<uint8>(altsvc.host().length()));
2865 builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
2866 builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
2867 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2868 return builder.take();
2871 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const {
2872 DCHECK_LT(SPDY3, protocol_version());
2873 size_t size = GetPrioritySize();
2875 SpdyFrameBuilder builder(size, protocol_version());
2876 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
2878 // Make sure the highest-order bit in the parent stream id is zeroed out.
2879 uint32 parent_stream_id = priority.parent_stream_id() & 0x7fffffff;
2880 uint32 exclusive = priority.exclusive() ? 0x80000000 : 0;
2881 // Set the one-bit exclusivity flag.
2882 uint32 flag_and_parent_id = parent_stream_id | exclusive;
2883 builder.WriteUInt32(flag_and_parent_id);
2884 builder.WriteUInt8(priority.weight());
2885 DCHECK_EQ(GetPrioritySize(), builder.length());
2886 return builder.take();
2889 namespace {
2891 class FrameSerializationVisitor : public SpdyFrameVisitor {
2892 public:
2893 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2894 ~FrameSerializationVisitor() override {}
2896 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2898 void VisitData(const SpdyDataIR& data) override {
2899 frame_.reset(framer_->SerializeData(data));
2901 void VisitSynStream(const SpdySynStreamIR& syn_stream) override {
2902 frame_.reset(framer_->SerializeSynStream(syn_stream));
2904 void VisitSynReply(const SpdySynReplyIR& syn_reply) override {
2905 frame_.reset(framer_->SerializeSynReply(syn_reply));
2907 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2908 frame_.reset(framer_->SerializeRstStream(rst_stream));
2910 void VisitSettings(const SpdySettingsIR& settings) override {
2911 frame_.reset(framer_->SerializeSettings(settings));
2913 void VisitPing(const SpdyPingIR& ping) override {
2914 frame_.reset(framer_->SerializePing(ping));
2916 void VisitGoAway(const SpdyGoAwayIR& goaway) override {
2917 frame_.reset(framer_->SerializeGoAway(goaway));
2919 void VisitHeaders(const SpdyHeadersIR& headers) override {
2920 frame_.reset(framer_->SerializeHeaders(headers));
2922 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2923 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2925 void VisitBlocked(const SpdyBlockedIR& blocked) override {
2926 frame_.reset(framer_->SerializeBlocked(blocked));
2928 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2929 frame_.reset(framer_->SerializePushPromise(push_promise));
2931 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2932 frame_.reset(framer_->SerializeContinuation(continuation));
2934 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
2935 frame_.reset(framer_->SerializeAltSvc(altsvc));
2937 void VisitPriority(const SpdyPriorityIR& priority) override {
2938 frame_.reset(framer_->SerializePriority(priority));
2941 private:
2942 SpdyFramer* framer_;
2943 scoped_ptr<SpdySerializedFrame> frame_;
2946 } // namespace
2948 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2949 FrameSerializationVisitor visitor(this);
2950 frame.Visit(&visitor);
2951 return visitor.ReleaseSerializedFrame();
2954 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2955 CHECK_GE(SPDY3, protocol_version());
2956 const size_t uncompressed_length =
2957 GetSerializedLength(protocol_version(), &headers);
2958 if (!enable_compression_) {
2959 return uncompressed_length;
2961 z_stream* compressor = GetHeaderCompressor();
2962 // Since we'll be performing lots of flushes when compressing the data,
2963 // zlib's lower bounds may be insufficient.
2964 return 2 * deflateBound(compressor, uncompressed_length);
2967 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2968 DCHECK_GT(protocol_version(), SPDY3);
2969 DCHECK_GT(size, kMaxControlFrameSize);
2970 size_t overflow = size - kMaxControlFrameSize;
2971 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
2972 // This is ceiling(overflow/payload_size) using integer arithmetics.
2973 return (overflow - 1) / payload_size + 1;
2976 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2977 const string& hpack_encoding,
2978 SpdyStreamId stream_id,
2979 SpdyFrameType type,
2980 int padding_payload_len) {
2981 uint8 end_flag = 0;
2982 uint8 flags = 0;
2983 if (type == HEADERS) {
2984 end_flag = HEADERS_FLAG_END_HEADERS;
2985 } else if (type == PUSH_PROMISE) {
2986 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2987 } else {
2988 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2989 << FrameTypeToString(type);
2992 // Write all the padding payload and as much of the data payload as possible
2993 // into the initial frame.
2994 size_t bytes_remaining = 0;
2995 bytes_remaining =
2996 hpack_encoding.size() -
2997 std::min(hpack_encoding.size(),
2998 kMaxControlFrameSize - builder->length() - padding_payload_len);
2999 builder->WriteBytes(&hpack_encoding[0],
3000 hpack_encoding.size() - bytes_remaining);
3001 if (padding_payload_len > 0) {
3002 string padding = string(padding_payload_len, 0);
3003 builder->WriteBytes(padding.data(), padding.length());
3005 if (bytes_remaining > 0) {
3006 builder->OverwriteLength(
3007 *this, kMaxControlFrameSize - GetControlFrameHeaderSize());
3010 // Tack on CONTINUATION frames for the overflow.
3011 while (bytes_remaining > 0) {
3012 size_t bytes_to_write = std::min(
3013 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize());
3014 // Write CONTINUATION frame prefix.
3015 if (bytes_remaining == bytes_to_write) {
3016 flags |= end_flag;
3018 builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
3019 // Write payload fragment.
3020 builder->WriteBytes(
3021 &hpack_encoding[hpack_encoding.size() - bytes_remaining],
3022 bytes_to_write);
3023 bytes_remaining -= bytes_to_write;
3027 // The following compression setting are based on Brian Olson's analysis. See
3028 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
3029 // for more details.
3030 #if defined(USE_SYSTEM_ZLIB)
3031 // System zlib is not expected to have workaround for http://crbug.com/139744,
3032 // so disable compression in that case.
3033 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
3034 static const int kCompressorLevel = 0;
3035 #else // !defined(USE_SYSTEM_ZLIB)
3036 static const int kCompressorLevel = 9;
3037 #endif // !defined(USE_SYSTEM_ZLIB)
3038 static const int kCompressorWindowSizeInBits = 11;
3039 static const int kCompressorMemLevel = 1;
3041 z_stream* SpdyFramer::GetHeaderCompressor() {
3042 if (header_compressor_.get())
3043 return header_compressor_.get(); // Already initialized.
3045 header_compressor_.reset(new z_stream);
3046 memset(header_compressor_.get(), 0, sizeof(z_stream));
3048 int success = deflateInit2(header_compressor_.get(),
3049 kCompressorLevel,
3050 Z_DEFLATED,
3051 kCompressorWindowSizeInBits,
3052 kCompressorMemLevel,
3053 Z_DEFAULT_STRATEGY);
3054 if (success == Z_OK) {
3055 const char* dictionary = (protocol_version() <= SPDY2) ?
3056 kV2Dictionary : kV3Dictionary;
3057 const int dictionary_size = (protocol_version() <= SPDY2) ?
3058 kV2DictionarySize : kV3DictionarySize;
3059 success = deflateSetDictionary(header_compressor_.get(),
3060 reinterpret_cast<const Bytef*>(dictionary),
3061 dictionary_size);
3063 if (success != Z_OK) {
3064 LOG(WARNING) << "deflateSetDictionary failure: " << success;
3065 header_compressor_.reset(NULL);
3066 return NULL;
3068 return header_compressor_.get();
3071 z_stream* SpdyFramer::GetHeaderDecompressor() {
3072 if (header_decompressor_.get())
3073 return header_decompressor_.get(); // Already initialized.
3075 header_decompressor_.reset(new z_stream);
3076 memset(header_decompressor_.get(), 0, sizeof(z_stream));
3078 int success = inflateInit(header_decompressor_.get());
3079 if (success != Z_OK) {
3080 LOG(WARNING) << "inflateInit failure: " << success;
3081 header_decompressor_.reset(NULL);
3082 return NULL;
3084 return header_decompressor_.get();
3087 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3088 DCHECK_LT(SPDY3, protocol_version());
3089 if (hpack_encoder_.get() == nullptr) {
3090 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3092 return hpack_encoder_.get();
3095 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3096 DCHECK_LT(SPDY3, protocol_version());
3097 if (hpack_decoder_.get() == nullptr) {
3098 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3100 return hpack_decoder_.get();
3103 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3104 const float kSteps = 255.9f / 7.f;
3105 return static_cast<uint8>(kSteps * (7.f - priority));
3108 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3109 const float kSteps = 255.9f / 7.f;
3110 return static_cast<SpdyPriority>(7.f - weight / kSteps);
3113 // Incrementally decompress the control frame's header block, feeding the
3114 // result to the visitor in chunks. Continue this until the visitor
3115 // indicates that it cannot process any more data, or (more commonly) we
3116 // run out of data to deliver.
3117 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3118 SpdyStreamId stream_id,
3119 const char* data,
3120 size_t len) {
3121 // Get a decompressor or set error.
3122 z_stream* decomp = GetHeaderDecompressor();
3123 if (decomp == NULL) {
3124 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3125 set_error(SPDY_DECOMPRESS_FAILURE);
3126 return false;
3129 bool processed_successfully = true;
3130 char buffer[kHeaderDataChunkMaxSize];
3132 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3133 decomp->avail_in = len;
3134 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3135 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3136 // reached this method successfully, stream_id should be nonzero.
3137 DCHECK_LT(0u, stream_id);
3138 while (decomp->avail_in > 0 && processed_successfully) {
3139 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3140 decomp->avail_out = arraysize(buffer);
3142 int rv = inflate(decomp, Z_SYNC_FLUSH);
3143 if (rv == Z_NEED_DICT) {
3144 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3145 : kV3Dictionary;
3146 const int dictionary_size = (protocol_version() <= SPDY2) ?
3147 kV2DictionarySize : kV3DictionarySize;
3148 const DictionaryIds& ids = g_dictionary_ids.Get();
3149 const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3150 ids.v2_dictionary_id : ids.v3_dictionary_id;
3151 // Need to try again with the right dictionary.
3152 if (decomp->adler == dictionary_id) {
3153 rv = inflateSetDictionary(decomp,
3154 reinterpret_cast<const Bytef*>(dictionary),
3155 dictionary_size);
3156 if (rv == Z_OK)
3157 rv = inflate(decomp, Z_SYNC_FLUSH);
3161 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3162 // without producing any output. The input is consumed and
3163 // buffered internally by zlib so we can detect this condition by
3164 // checking if avail_in is 0 after the call to inflate.
3165 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3166 if ((rv == Z_OK) || input_exhausted) {
3167 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3168 if (decompressed_len > 0) {
3169 processed_successfully = visitor_->OnControlFrameHeaderData(
3170 stream_id, buffer, decompressed_len);
3172 if (!processed_successfully) {
3173 // Assume that the problem was the header block was too large for the
3174 // visitor.
3175 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3177 } else {
3178 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3179 set_error(SPDY_DECOMPRESS_FAILURE);
3180 processed_successfully = false;
3183 return processed_successfully;
3186 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3187 SpdyStreamId stream_id, const char* data, size_t len) {
3188 bool read_successfully = true;
3189 while (read_successfully && len > 0) {
3190 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3191 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3192 bytes_to_deliver);
3193 data += bytes_to_deliver;
3194 len -= bytes_to_deliver;
3195 if (!read_successfully) {
3196 // Assume that the problem was the header block was too large for the
3197 // visitor.
3198 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3201 return read_successfully;
3204 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3205 SpdyFrameBuilder* builder,
3206 const SpdyNameValueBlock& name_value_block) const {
3207 // Serialize number of headers.
3208 if (protocol_version() <= SPDY2) {
3209 builder->WriteUInt16(static_cast<uint16>(name_value_block.size()));
3210 } else {
3211 builder->WriteUInt32(name_value_block.size());
3214 // Serialize each header.
3215 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3216 it != name_value_block.end();
3217 ++it) {
3218 if (protocol_version() <= SPDY2) {
3219 builder->WriteStringPiece16(it->first);
3220 builder->WriteStringPiece16(it->second);
3221 } else {
3222 builder->WriteStringPiece32(it->first);
3223 builder->WriteStringPiece32(it->second);
3228 void SpdyFramer::SerializeNameValueBlock(
3229 SpdyFrameBuilder* builder,
3230 const SpdyFrameWithNameValueBlockIR& frame) {
3231 CHECK_GE(SPDY3, protocol_version());
3232 if (!enable_compression_) {
3233 return SerializeNameValueBlockWithoutCompression(builder,
3234 frame.name_value_block());
3237 // First build an uncompressed version to be fed into the compressor.
3238 const size_t uncompressed_len = GetSerializedLength(
3239 protocol_version(), &(frame.name_value_block()));
3240 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3241 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
3242 frame.name_value_block());
3243 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3245 z_stream* compressor = GetHeaderCompressor();
3246 if (!compressor) {
3247 LOG(DFATAL) << "Could not obtain compressor.";
3248 return;
3250 // Create an output frame.
3251 // Since we'll be performing lots of flushes when compressing the data,
3252 // zlib's lower bounds may be insufficient.
3254 // TODO(akalin): Avoid the duplicate calculation with
3255 // GetSerializedLength(const SpdyHeaderBlock&).
3256 const int compressed_max_size =
3257 2 * deflateBound(compressor, uncompressed_len);
3259 // TODO(phajdan.jr): Clean up after we no longer need
3260 // to workaround http://crbug.com/139744.
3261 #if defined(USE_SYSTEM_ZLIB)
3262 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3263 compressor->avail_in = uncompressed_len;
3264 #endif // defined(USE_SYSTEM_ZLIB)
3265 compressor->next_out = reinterpret_cast<Bytef*>(
3266 builder->GetWritableBuffer(compressed_max_size));
3267 compressor->avail_out = compressed_max_size;
3269 // TODO(phajdan.jr): Clean up after we no longer need
3270 // to workaround http://crbug.com/139744.
3271 #if defined(USE_SYSTEM_ZLIB)
3272 int rv = deflate(compressor, Z_SYNC_FLUSH);
3273 if (rv != Z_OK) { // How can we know that it compressed everything?
3274 // This shouldn't happen, right?
3275 LOG(WARNING) << "deflate failure: " << rv;
3276 // TODO(akalin): Upstream this return.
3277 return;
3279 #else
3280 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
3281 #endif // defined(USE_SYSTEM_ZLIB)
3283 int compressed_size = compressed_max_size - compressor->avail_out;
3284 builder->Seek(compressed_size);
3285 builder->RewriteLength(*this);
3288 } // namespace net