Fix more MSVC warnings, courgette/ edition.
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blobedcc82e5fa021a3e68a7cd7ee206b8f2c92a2d97
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/metrics/stats_counters.h"
10 #include "base/third_party/valgrind/memcheck.h"
11 #include "net/spdy/spdy_frame_builder.h"
12 #include "net/spdy/spdy_frame_reader.h"
13 #include "net/spdy/spdy_bitmasks.h"
14 #include "third_party/zlib/zlib.h"
16 using base::StringPiece;
17 using std::string;
18 using std::vector;
20 namespace net {
22 namespace {
24 // Compute the id of our dictionary so that we know we're using the
25 // right one when asked for it.
26 uLong CalculateDictionaryId(const char* dictionary,
27 const size_t dictionary_size) {
28 uLong initial_value = adler32(0L, Z_NULL, 0);
29 return adler32(initial_value,
30 reinterpret_cast<const Bytef*>(dictionary),
31 dictionary_size);
34 // Check to see if the name and value of a cookie are both empty.
35 bool IsCookieEmpty(const base::StringPiece& cookie) {
36 if (cookie.size() == 0) {
37 return true;
39 size_t pos = cookie.find('=');
40 if (pos == base::StringPiece::npos) {
41 return false;
43 // Ignore leading whitespaces of cookie value.
44 size_t value_start = pos + 1;
45 for (; value_start < cookie.size(); value_start++) {
46 if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) {
47 break;
50 return (pos == 0) && ((cookie.size() - value_start) == 0);
53 struct DictionaryIds {
54 DictionaryIds()
55 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
56 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
58 const uLong v2_dictionary_id;
59 const uLong v3_dictionary_id;
62 // Adler ID for the SPDY header compressor dictionaries. Note that they are
63 // initialized lazily to avoid static initializers.
64 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
66 // Used to indicate no flags in a SPDY flags field.
67 const uint8 kNoFlags = 0;
69 // Wire sizes of priority payloads.
70 const size_t kPriorityDependencyPayloadSize = 4;
71 const size_t kPriorityWeightPayloadSize = 1;
73 } // namespace
75 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
76 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
77 // The size of the control frame buffer. Must be >= the minimum size of the
78 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
79 // calculation details.
80 const size_t SpdyFramer::kControlFrameBufferSize = 19;
82 #ifdef DEBUG_SPDY_STATE_CHANGES
83 #define CHANGE_STATE(newstate) \
84 do { \
85 DVLOG(1) << "Changing state from: " \
86 << StateToString(state_) \
87 << " to " << StateToString(newstate) << "\n"; \
88 DCHECK(state_ != SPDY_ERROR); \
89 DCHECK_EQ(previous_state_, state_); \
90 previous_state_ = state_; \
91 state_ = newstate; \
92 } while (false)
93 #else
94 #define CHANGE_STATE(newstate) \
95 do { \
96 DCHECK(state_ != SPDY_ERROR); \
97 DCHECK_EQ(previous_state_, state_); \
98 previous_state_ = state_; \
99 state_ = newstate; \
100 } while (false)
101 #endif
103 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
104 SpdyMajorVersion version, uint32 wire) {
105 if (version < SPDY3) {
106 ConvertFlagsAndIdForSpdy2(&wire);
108 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
111 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
112 : flags_(flags), id_(id & 0x00ffffff) {
113 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
116 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
117 const {
118 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
119 if (version < SPDY3) {
120 ConvertFlagsAndIdForSpdy2(&wire);
122 return wire;
125 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
126 // This method is used to preserve buggy behavior and works on both
127 // little-endian and big-endian hosts.
128 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
129 // as well as vice versa).
130 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
131 uint8* wire_array = reinterpret_cast<uint8*>(val);
132 std::swap(wire_array[0], wire_array[3]);
133 std::swap(wire_array[1], wire_array[2]);
136 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
137 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
139 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
140 size_t len) {
141 return true;
144 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
145 const char* rst_stream_data,
146 size_t len) {
147 return true;
150 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
151 : current_frame_buffer_(new char[kControlFrameBufferSize]),
152 enable_compression_(true),
153 visitor_(NULL),
154 debug_visitor_(NULL),
155 display_protocol_("SPDY"),
156 spdy_version_(version),
157 syn_frame_processed_(false),
158 probable_http_response_(false),
159 expect_continuation_(0),
160 end_stream_when_done_(false) {
161 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
162 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
163 Reset();
166 SpdyFramer::~SpdyFramer() {
167 if (header_compressor_.get()) {
168 deflateEnd(header_compressor_.get());
170 if (header_decompressor_.get()) {
171 inflateEnd(header_decompressor_.get());
175 void SpdyFramer::Reset() {
176 state_ = SPDY_RESET;
177 previous_state_ = SPDY_RESET;
178 error_code_ = SPDY_NO_ERROR;
179 remaining_data_length_ = 0;
180 remaining_control_header_ = 0;
181 current_frame_buffer_length_ = 0;
182 current_frame_type_ = DATA;
183 current_frame_flags_ = 0;
184 current_frame_length_ = 0;
185 current_frame_stream_id_ = kInvalidStream;
186 settings_scratch_.Reset();
187 altsvc_scratch_.Reset();
188 remaining_padding_payload_length_ = 0;
191 size_t SpdyFramer::GetDataFrameMinimumSize() const {
192 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
195 // Size, in bytes, of the control frame header.
196 size_t SpdyFramer::GetControlFrameHeaderSize() const {
197 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
200 size_t SpdyFramer::GetSynStreamMinimumSize() const {
201 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
202 // name-value block.
203 if (protocol_version() <= SPDY3) {
204 // Calculated as:
205 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
206 // + 1 (unused, was credential slot)
207 return GetControlFrameHeaderSize() + 10;
208 } else {
209 return GetControlFrameHeaderSize() +
210 kPriorityDependencyPayloadSize +
211 kPriorityWeightPayloadSize;
215 size_t SpdyFramer::GetSynReplyMinimumSize() const {
216 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
217 // name-value block.
218 size_t size = GetControlFrameHeaderSize();
219 if (protocol_version() <= SPDY3) {
220 // Calculated as:
221 // control frame header + 4 (stream IDs)
222 size += 4;
225 // In SPDY 2, there were 2 unused bytes before payload.
226 if (protocol_version() < SPDY3) {
227 size += 2;
230 return size;
233 size_t SpdyFramer::GetRstStreamMinimumSize() const {
234 // Size, in bytes, of a RST_STREAM frame.
235 if (protocol_version() <= SPDY3) {
236 // Calculated as:
237 // control frame header + 4 (stream id) + 4 (status code)
238 return GetControlFrameHeaderSize() + 8;
239 } else {
240 // Calculated as:
241 // frame prefix + 4 (status code)
242 return GetControlFrameHeaderSize() + 4;
246 size_t SpdyFramer::GetSettingsMinimumSize() const {
247 // Size, in bytes, of a SETTINGS frame not including the IDs and values
248 // from the variable-length value block. Calculated as:
249 // control frame header + 4 (number of ID/value pairs)
250 if (protocol_version() <= SPDY3) {
251 return GetControlFrameHeaderSize() + 4;
252 } else {
253 return GetControlFrameHeaderSize();
257 size_t SpdyFramer::GetPingSize() const {
258 // Size, in bytes, of this PING frame.
259 if (protocol_version() <= SPDY3) {
260 // Calculated as:
261 // control frame header + 4 (id)
262 return GetControlFrameHeaderSize() + 4;
263 } else {
264 // Calculated as:
265 // control frame header + 8 (id)
266 return GetControlFrameHeaderSize() + 8;
270 size_t SpdyFramer::GetGoAwayMinimumSize() const {
271 // Size, in bytes, of this GOAWAY frame. Calculated as:
272 // 1. Control frame header size
273 size_t size = GetControlFrameHeaderSize();
275 // 2. Last good stream id (4 bytes)
276 size += 4;
278 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
279 if (protocol_version() >= SPDY3) {
280 size += 4;
283 return size;
286 size_t SpdyFramer::GetHeadersMinimumSize() const {
287 // Size, in bytes, of a HEADERS frame not including the variable-length
288 // name-value block.
289 size_t size = GetControlFrameHeaderSize();
290 if (protocol_version() <= SPDY3) {
291 // Calculated as:
292 // control frame header + 4 (stream IDs)
293 size += 4;
296 // In SPDY 2, there were 2 unused bytes before payload.
297 if (protocol_version() <= SPDY2) {
298 size += 2;
301 return size;
304 size_t SpdyFramer::GetWindowUpdateSize() const {
305 // Size, in bytes, of a WINDOW_UPDATE frame.
306 if (protocol_version() <= SPDY3) {
307 // Calculated as:
308 // control frame header + 4 (stream id) + 4 (delta)
309 return GetControlFrameHeaderSize() + 8;
310 } else {
311 // Calculated as:
312 // frame prefix + 4 (delta)
313 return GetControlFrameHeaderSize() + 4;
317 size_t SpdyFramer::GetBlockedSize() const {
318 DCHECK_LT(SPDY3, protocol_version());
319 // Size, in bytes, of a BLOCKED frame.
320 // The BLOCKED frame has no payload beyond the control frame header.
321 return GetControlFrameHeaderSize();
324 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
325 DCHECK_LT(SPDY3, protocol_version());
326 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
327 // Calculated as frame prefix + 4 (promised stream id).
328 return GetControlFrameHeaderSize() + 4;
331 size_t SpdyFramer::GetContinuationMinimumSize() const {
332 // Size, in bytes, of a CONTINUATION frame not including the variable-length
333 // headers fragments.
334 return GetControlFrameHeaderSize();
337 size_t SpdyFramer::GetAltSvcMinimumSize() const {
338 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
339 // (optional) Origin fields, all of which can vary in length.
340 // Note that this gives a lower bound on the frame size rather than a true
341 // minimum; the actual frame should always be larger than this.
342 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
343 // + 1 (pid_len) + 1 (host_len).
344 return GetControlFrameHeaderSize() + 9;
347 size_t SpdyFramer::GetPrioritySize() const {
348 // Size, in bytes, of a PRIORITY frame.
349 return GetControlFrameHeaderSize() +
350 kPriorityDependencyPayloadSize +
351 kPriorityWeightPayloadSize;
354 size_t SpdyFramer::GetFrameMinimumSize() const {
355 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
358 size_t SpdyFramer::GetFrameMaximumSize() const {
359 return SpdyConstants::GetFrameMaximumSize(protocol_version());
362 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
363 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
366 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
367 return SpdyConstants::GetPrefixLength(type, protocol_version());
370 const char* SpdyFramer::StateToString(int state) {
371 switch (state) {
372 case SPDY_ERROR:
373 return "ERROR";
374 case SPDY_AUTO_RESET:
375 return "AUTO_RESET";
376 case SPDY_RESET:
377 return "RESET";
378 case SPDY_READING_COMMON_HEADER:
379 return "READING_COMMON_HEADER";
380 case SPDY_CONTROL_FRAME_PAYLOAD:
381 return "CONTROL_FRAME_PAYLOAD";
382 case SPDY_READ_PADDING_LENGTH:
383 return "SPDY_READ_PADDING_LENGTH";
384 case SPDY_CONSUME_PADDING:
385 return "SPDY_CONSUME_PADDING";
386 case SPDY_IGNORE_REMAINING_PAYLOAD:
387 return "IGNORE_REMAINING_PAYLOAD";
388 case SPDY_FORWARD_STREAM_FRAME:
389 return "FORWARD_STREAM_FRAME";
390 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
391 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
392 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
393 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
394 case SPDY_GOAWAY_FRAME_PAYLOAD:
395 return "SPDY_GOAWAY_FRAME_PAYLOAD";
396 case SPDY_RST_STREAM_FRAME_PAYLOAD:
397 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
398 case SPDY_SETTINGS_FRAME_PAYLOAD:
399 return "SPDY_SETTINGS_FRAME_PAYLOAD";
400 case SPDY_ALTSVC_FRAME_PAYLOAD:
401 return "SPDY_ALTSVC_FRAME_PAYLOAD";
403 return "UNKNOWN_STATE";
406 void SpdyFramer::set_error(SpdyError error) {
407 DCHECK(visitor_);
408 error_code_ = error;
409 // These values will usually get reset once we come to the end
410 // of a header block, but if we run into an error that
411 // might not happen, so reset them here.
412 expect_continuation_ = 0;
413 end_stream_when_done_ = false;
415 CHANGE_STATE(SPDY_ERROR);
416 visitor_->OnError(this);
419 const char* SpdyFramer::ErrorCodeToString(int error_code) {
420 switch (error_code) {
421 case SPDY_NO_ERROR:
422 return "NO_ERROR";
423 case SPDY_INVALID_CONTROL_FRAME:
424 return "INVALID_CONTROL_FRAME";
425 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
426 return "CONTROL_PAYLOAD_TOO_LARGE";
427 case SPDY_ZLIB_INIT_FAILURE:
428 return "ZLIB_INIT_FAILURE";
429 case SPDY_UNSUPPORTED_VERSION:
430 return "UNSUPPORTED_VERSION";
431 case SPDY_DECOMPRESS_FAILURE:
432 return "DECOMPRESS_FAILURE";
433 case SPDY_COMPRESS_FAILURE:
434 return "COMPRESS_FAILURE";
435 case SPDY_INVALID_DATA_FRAME_FLAGS:
436 return "SPDY_INVALID_DATA_FRAME_FLAGS";
437 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
438 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
439 case SPDY_UNEXPECTED_FRAME:
440 return "UNEXPECTED_FRAME";
442 return "UNKNOWN_ERROR";
445 const char* SpdyFramer::StatusCodeToString(int status_code) {
446 switch (status_code) {
447 case RST_STREAM_INVALID:
448 return "INVALID";
449 case RST_STREAM_PROTOCOL_ERROR:
450 return "PROTOCOL_ERROR";
451 case RST_STREAM_INVALID_STREAM:
452 return "INVALID_STREAM";
453 case RST_STREAM_REFUSED_STREAM:
454 return "REFUSED_STREAM";
455 case RST_STREAM_UNSUPPORTED_VERSION:
456 return "UNSUPPORTED_VERSION";
457 case RST_STREAM_CANCEL:
458 return "CANCEL";
459 case RST_STREAM_INTERNAL_ERROR:
460 return "INTERNAL_ERROR";
461 case RST_STREAM_FLOW_CONTROL_ERROR:
462 return "FLOW_CONTROL_ERROR";
463 case RST_STREAM_STREAM_IN_USE:
464 return "STREAM_IN_USE";
465 case RST_STREAM_STREAM_ALREADY_CLOSED:
466 return "STREAM_ALREADY_CLOSED";
467 case RST_STREAM_INVALID_CREDENTIALS:
468 return "INVALID_CREDENTIALS";
469 case RST_STREAM_FRAME_TOO_LARGE:
470 return "FRAME_TOO_LARGE";
471 case RST_STREAM_CONNECT_ERROR:
472 return "CONNECT_ERROR";
473 case RST_STREAM_ENHANCE_YOUR_CALM:
474 return "ENHANCE_YOUR_CALM";
476 return "UNKNOWN_STATUS";
479 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
480 switch (type) {
481 case DATA:
482 return "DATA";
483 case SYN_STREAM:
484 return "SYN_STREAM";
485 case SYN_REPLY:
486 return "SYN_REPLY";
487 case RST_STREAM:
488 return "RST_STREAM";
489 case SETTINGS:
490 return "SETTINGS";
491 case PING:
492 return "PING";
493 case GOAWAY:
494 return "GOAWAY";
495 case HEADERS:
496 return "HEADERS";
497 case WINDOW_UPDATE:
498 return "WINDOW_UPDATE";
499 case CREDENTIAL:
500 return "CREDENTIAL";
501 case PUSH_PROMISE:
502 return "PUSH_PROMISE";
503 case CONTINUATION:
504 return "CONTINUATION";
505 case PRIORITY:
506 return "PRIORITY";
507 case ALTSVC:
508 return "ALTSVC";
509 case BLOCKED:
510 return "BLOCKED";
512 return "UNKNOWN_CONTROL_TYPE";
515 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
516 DCHECK(visitor_);
517 DCHECK(data);
519 size_t original_len = len;
520 do {
521 previous_state_ = state_;
522 switch (state_) {
523 case SPDY_ERROR:
524 goto bottom;
526 case SPDY_AUTO_RESET:
527 case SPDY_RESET:
528 Reset();
529 if (len > 0) {
530 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
532 break;
534 case SPDY_READING_COMMON_HEADER: {
535 size_t bytes_read = ProcessCommonHeader(data, len);
536 len -= bytes_read;
537 data += bytes_read;
538 break;
541 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
542 // Control frames that contain header blocks
543 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
544 // take a different path through the state machine - they
545 // will go:
546 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
547 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
549 // SETTINGS frames take a slightly modified route:
550 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
551 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
553 // All other control frames will use the alternate route directly to
554 // SPDY_CONTROL_FRAME_PAYLOAD
555 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
556 len -= bytes_read;
557 data += bytes_read;
558 break;
561 case SPDY_SETTINGS_FRAME_PAYLOAD: {
562 int bytes_read = ProcessSettingsFramePayload(data, len);
563 len -= bytes_read;
564 data += bytes_read;
565 break;
568 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
569 int bytes_read = ProcessControlFrameHeaderBlock(
570 data, len, protocol_version() > SPDY3);
571 len -= bytes_read;
572 data += bytes_read;
573 break;
576 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
577 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
578 len -= bytes_read;
579 data += bytes_read;
580 break;
583 case SPDY_GOAWAY_FRAME_PAYLOAD: {
584 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
585 len -= bytes_read;
586 data += bytes_read;
587 break;
590 case SPDY_ALTSVC_FRAME_PAYLOAD: {
591 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
592 len -= bytes_read;
593 data += bytes_read;
594 break;
597 case SPDY_CONTROL_FRAME_PAYLOAD: {
598 size_t bytes_read = ProcessControlFramePayload(data, len);
599 len -= bytes_read;
600 data += bytes_read;
601 break;
604 case SPDY_READ_PADDING_LENGTH: {
605 size_t bytes_read = ProcessFramePaddingLength(data, len);
606 len -= bytes_read;
607 data += bytes_read;
608 break;
611 case SPDY_CONSUME_PADDING: {
612 size_t bytes_read = ProcessFramePadding(data, len);
613 len -= bytes_read;
614 data += bytes_read;
615 break;
618 case SPDY_IGNORE_REMAINING_PAYLOAD: {
619 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
620 len -= bytes_read;
621 data += bytes_read;
622 break;
625 case SPDY_FORWARD_STREAM_FRAME: {
626 size_t bytes_read = ProcessDataFramePayload(data, len);
627 len -= bytes_read;
628 data += bytes_read;
629 break;
632 default:
633 LOG(DFATAL) << "Invalid value for " << display_protocol_
634 << " framer state: " << state_;
635 // This ensures that we don't infinite-loop if state_ gets an
636 // invalid value somehow, such as due to a SpdyFramer getting deleted
637 // from a callback it calls.
638 goto bottom;
640 } while (state_ != previous_state_);
641 bottom:
642 DCHECK(len == 0 || state_ == SPDY_ERROR);
643 if (current_frame_buffer_length_ == 0 &&
644 remaining_data_length_ == 0 &&
645 remaining_control_header_ == 0) {
646 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
647 << "State: " << StateToString(state_);
650 return original_len - len;
653 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
654 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
655 // state.
656 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
658 size_t original_len = len;
660 // Update current frame buffer as needed.
661 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
662 size_t bytes_desired =
663 GetControlFrameHeaderSize() - current_frame_buffer_length_;
664 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
667 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
668 // Not enough information to do anything meaningful.
669 return original_len - len;
672 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
673 // when processing DATA frames below.
674 scoped_ptr<SpdyFrameReader> reader(
675 new SpdyFrameReader(current_frame_buffer_.get(),
676 current_frame_buffer_length_));
678 uint16 version = 0;
679 bool is_control_frame = false;
681 uint16 control_frame_type_field =
682 SpdyConstants::DataFrameType(protocol_version());
683 // ProcessControlFrameHeader() will set current_frame_type_ to the
684 // correct value if this is a valid control frame.
685 current_frame_type_ = DATA;
686 if (protocol_version() <= SPDY3) {
687 bool successful_read = reader->ReadUInt16(&version);
688 DCHECK(successful_read);
689 is_control_frame = (version & kControlFlagMask) != 0;
690 version &= ~kControlFlagMask; // Only valid for control frames.
691 if (is_control_frame) {
692 // We check version before we check validity: version can never be
693 // 'invalid', it can only be unsupported.
694 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
695 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
696 SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
697 // Version does not match the version the framer was initialized with.
698 DVLOG(1) << "Unsupported SPDY version "
699 << version
700 << " (expected " << protocol_version() << ")";
701 set_error(SPDY_UNSUPPORTED_VERSION);
702 return 0;
703 } else {
704 // Convert version from wire format to SpdyMajorVersion.
705 version = SpdyConstants::ParseMajorVersion(version);
707 // We check control_frame_type_field's validity in
708 // ProcessControlFrameHeader().
709 successful_read = reader->ReadUInt16(&control_frame_type_field);
710 } else {
711 reader->Rewind();
712 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
714 DCHECK(successful_read);
716 successful_read = reader->ReadUInt8(&current_frame_flags_);
717 DCHECK(successful_read);
719 uint32 length_field = 0;
720 successful_read = reader->ReadUInt24(&length_field);
721 DCHECK(successful_read);
722 remaining_data_length_ = length_field;
723 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
724 } else {
725 version = protocol_version();
726 uint32 length_field = 0;
727 bool successful_read = reader->ReadUInt24(&length_field);
728 DCHECK(successful_read);
730 uint8 control_frame_type_field_uint8 =
731 SpdyConstants::DataFrameType(protocol_version());
732 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
733 DCHECK(successful_read);
734 // We check control_frame_type_field's validity in
735 // ProcessControlFrameHeader().
736 control_frame_type_field = control_frame_type_field_uint8;
737 is_control_frame = (protocol_version() > SPDY3) ?
738 control_frame_type_field !=
739 SpdyConstants::SerializeFrameType(protocol_version(), DATA) :
740 control_frame_type_field != 0;
742 if (is_control_frame) {
743 current_frame_length_ = length_field + GetControlFrameHeaderSize();
744 } else {
745 current_frame_length_ = length_field + GetDataFrameMinimumSize();
748 successful_read = reader->ReadUInt8(&current_frame_flags_);
749 DCHECK(successful_read);
751 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
752 DCHECK(successful_read);
754 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
756 // Before we accept a DATA frame, we need to make sure we're not in the
757 // middle of processing a header block.
758 const bool is_continuation_frame = (control_frame_type_field ==
759 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
760 if ((expect_continuation_ != 0) != is_continuation_frame) {
761 if (expect_continuation_ != 0) {
762 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
763 << "frame, but instead received frame type "
764 << control_frame_type_field;
765 } else {
766 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
768 set_error(SPDY_UNEXPECTED_FRAME);
769 return original_len - len;
772 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
773 : GetDataFrameMinimumSize(),
774 reader->GetBytesConsumed());
775 DCHECK_EQ(current_frame_length_,
776 remaining_data_length_ + reader->GetBytesConsumed());
778 // This is just a sanity check for help debugging early frame errors.
779 if (remaining_data_length_ > 1000000u) {
780 // The strncmp for 5 is safe because we only hit this point if we
781 // have kMinCommonHeader (8) bytes
782 if (!syn_frame_processed_ &&
783 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
784 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
785 << " request";
786 probable_http_response_ = true;
787 } else {
788 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
789 << " session is likely corrupt.";
793 // if we're here, then we have the common header all received.
794 if (!is_control_frame) {
795 if (protocol_version() > SPDY3) {
796 // Catch bogus tests sending oversized DATA frames.
797 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
798 << "DATA frame too large for SPDY >= 4.";
801 uint8 valid_data_flags = 0;
802 if (protocol_version() > SPDY3) {
803 valid_data_flags =
804 DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
805 } else {
806 valid_data_flags = DATA_FLAG_FIN;
809 if (current_frame_flags_ & ~valid_data_flags) {
810 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
811 } else {
812 visitor_->OnDataFrameHeader(current_frame_stream_id_,
813 remaining_data_length_,
814 current_frame_flags_ & DATA_FLAG_FIN);
815 if (remaining_data_length_ > 0) {
816 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
817 } else {
818 // Empty data frame.
819 if (current_frame_flags_ & DATA_FLAG_FIN) {
820 visitor_->OnStreamFrameData(
821 current_frame_stream_id_, NULL, 0, true);
823 CHANGE_STATE(SPDY_AUTO_RESET);
826 } else {
827 ProcessControlFrameHeader(control_frame_type_field);
830 return original_len - len;
833 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
834 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
835 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
837 // TODO(mlavan): Either remove credential frames from the code entirely,
838 // or add them to parsing + serialization methods for SPDY3.
839 // Early detection of deprecated frames that we ignore.
840 if (protocol_version() <= SPDY3) {
841 if (control_frame_type_field == CREDENTIAL) {
842 current_frame_type_ = CREDENTIAL;
843 DCHECK_EQ(SPDY3, protocol_version());
844 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
845 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
846 return;
850 if (!SpdyConstants::IsValidFrameType(protocol_version(),
851 control_frame_type_field)) {
852 if (protocol_version() <= SPDY3) {
853 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
854 << " (protocol version: " << protocol_version() << ")";
855 set_error(SPDY_INVALID_CONTROL_FRAME);
856 return;
857 } else {
858 // In HTTP2 we ignore unknown frame types for extensibility, as long as
859 // the rest of the control frame header is valid.
860 // We rely on the visitor to check validity of current_frame_stream_id_.
861 bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_,
862 control_frame_type_field);
863 if (valid_stream) {
864 DVLOG(1) << "Ignoring unknown frame type.";
865 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
866 } else {
867 // Report an invalid frame error and close the stream if the
868 // stream_id is not valid.
869 DLOG(WARNING) << "Unknown control frame type "
870 << control_frame_type_field
871 << " received on invalid stream "
872 << current_frame_stream_id_;
873 set_error(SPDY_INVALID_CONTROL_FRAME);
875 return;
879 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
880 control_frame_type_field);
882 // Do some sanity checking on the control frame sizes and flags.
883 switch (current_frame_type_) {
884 case SYN_STREAM:
885 if (current_frame_length_ < GetSynStreamMinimumSize()) {
886 set_error(SPDY_INVALID_CONTROL_FRAME);
887 } else if (current_frame_flags_ &
888 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
889 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
891 break;
892 case SYN_REPLY:
893 if (current_frame_length_ < GetSynReplyMinimumSize()) {
894 set_error(SPDY_INVALID_CONTROL_FRAME);
895 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
896 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
898 break;
899 case RST_STREAM:
900 // For SPDY versions < 4, the header has a fixed length.
901 // For SPDY version 4 and up, the RST_STREAM frame may include optional
902 // opaque data, so we only have a lower limit on the frame size.
903 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
904 protocol_version() <= SPDY3) ||
905 (current_frame_length_ < GetRstStreamMinimumSize() &&
906 protocol_version() > SPDY3)) {
907 set_error(SPDY_INVALID_CONTROL_FRAME);
908 } else if (current_frame_flags_ != 0) {
909 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
911 break;
912 case SETTINGS:
914 // Make sure that we have an integral number of 8-byte key/value pairs,
915 // plus a 4-byte length field in SPDY3 and below.
916 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
917 // Size of each key/value pair in bytes.
918 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
919 if (current_frame_length_ < GetSettingsMinimumSize() ||
920 (current_frame_length_ - GetControlFrameHeaderSize())
921 % setting_size != values_prefix_size) {
922 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
923 << current_frame_length_;
924 set_error(SPDY_INVALID_CONTROL_FRAME);
925 } else if (protocol_version() <= SPDY3 &&
926 current_frame_flags_ &
927 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
928 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
929 } else if (protocol_version() > SPDY3 &&
930 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
931 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
932 } else if (protocol_version() > SPDY3 &&
933 current_frame_flags_ & SETTINGS_FLAG_ACK &&
934 current_frame_length_ > GetSettingsMinimumSize()) {
935 set_error(SPDY_INVALID_CONTROL_FRAME);
937 break;
939 case PING:
940 if (current_frame_length_ != GetPingSize()) {
941 set_error(SPDY_INVALID_CONTROL_FRAME);
942 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
943 (current_frame_flags_ & ~PING_FLAG_ACK)) {
944 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
946 break;
947 case GOAWAY:
949 // For SPDY version < 4, there are only mandatory fields and the header
950 // has a fixed length. For SPDY version >= 4, optional opaque data may
951 // be appended to the GOAWAY frame, thus there is only a minimal length
952 // restriction.
953 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
954 protocol_version() <= SPDY3) ||
955 (current_frame_length_ < GetGoAwayMinimumSize() &&
956 protocol_version() > SPDY3)) {
957 set_error(SPDY_INVALID_CONTROL_FRAME);
958 } else if (current_frame_flags_ != 0) {
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
961 break;
963 case HEADERS:
965 size_t min_size = GetHeadersMinimumSize();
966 if (protocol_version() > SPDY3 &&
967 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
968 min_size += 4;
970 if (current_frame_length_ < min_size) {
971 // TODO(mlavan): check here for HEADERS with no payload?
972 // (not allowed in SPDY4)
973 set_error(SPDY_INVALID_CONTROL_FRAME);
974 } else if (protocol_version() <= SPDY3 &&
975 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
976 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
977 } else if (protocol_version() > SPDY3 &&
978 current_frame_flags_ &
979 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
980 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
981 HEADERS_FLAG_PADDED)) {
982 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
985 break;
986 case WINDOW_UPDATE:
987 if (current_frame_length_ != GetWindowUpdateSize()) {
988 set_error(SPDY_INVALID_CONTROL_FRAME);
989 } else if (current_frame_flags_ != 0) {
990 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
992 break;
993 case BLOCKED:
994 if (current_frame_length_ != GetBlockedSize() ||
995 protocol_version() <= SPDY3) {
996 set_error(SPDY_INVALID_CONTROL_FRAME);
997 } else if (current_frame_flags_ != 0) {
998 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1000 break;
1001 case PUSH_PROMISE:
1002 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
1003 set_error(SPDY_INVALID_CONTROL_FRAME);
1004 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
1005 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1006 } else if (protocol_version() > SPDY3 &&
1007 current_frame_flags_ &
1008 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
1009 HEADERS_FLAG_PADDED)) {
1010 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1012 break;
1013 case CONTINUATION:
1014 if (current_frame_length_ < GetContinuationMinimumSize() ||
1015 protocol_version() <= SPDY3) {
1016 set_error(SPDY_INVALID_CONTROL_FRAME);
1017 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
1018 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1020 break;
1021 case ALTSVC:
1022 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
1023 set_error(SPDY_INVALID_CONTROL_FRAME);
1024 } else if (current_frame_flags_ != 0) {
1025 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1027 break;
1028 case PRIORITY:
1029 if (current_frame_length_ != GetPrioritySize() ||
1030 protocol_version() <= SPDY3) {
1031 set_error(SPDY_INVALID_CONTROL_FRAME);
1032 } else if (current_frame_flags_ != 0) {
1033 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1035 break;
1036 default:
1037 LOG(WARNING) << "Valid " << display_protocol_
1038 << " control frame with unhandled type: "
1039 << current_frame_type_;
1040 // This branch should be unreachable because of the frame type bounds
1041 // check above. However, we DLOG(FATAL) here in an effort to painfully
1042 // club the head of the developer who failed to keep this file in sync
1043 // with spdy_protocol.h.
1044 DLOG(FATAL);
1045 set_error(SPDY_INVALID_CONTROL_FRAME);
1046 break;
1049 if (state_ == SPDY_ERROR) {
1050 return;
1053 if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
1054 DLOG(WARNING) << "Received control frame with way too big of a payload: "
1055 << current_frame_length_;
1056 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1057 return;
1060 if (current_frame_type_ == GOAWAY) {
1061 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1062 return;
1065 if (current_frame_type_ == RST_STREAM) {
1066 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1067 return;
1070 if (current_frame_type_ == ALTSVC) {
1071 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1072 return;
1074 // Determine the frame size without variable-length data.
1075 int32 frame_size_without_variable_data;
1076 switch (current_frame_type_) {
1077 case SYN_STREAM:
1078 syn_frame_processed_ = true;
1079 frame_size_without_variable_data = GetSynStreamMinimumSize();
1080 break;
1081 case SYN_REPLY:
1082 syn_frame_processed_ = true;
1083 frame_size_without_variable_data = GetSynReplyMinimumSize();
1084 break;
1085 case SETTINGS:
1086 frame_size_without_variable_data = GetSettingsMinimumSize();
1087 break;
1088 case HEADERS:
1089 frame_size_without_variable_data = GetHeadersMinimumSize();
1090 if (protocol_version() > SPDY3 &&
1091 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1092 frame_size_without_variable_data +=
1093 kPriorityDependencyPayloadSize +
1094 kPriorityWeightPayloadSize;
1096 break;
1097 case PUSH_PROMISE:
1098 frame_size_without_variable_data = GetPushPromiseMinimumSize();
1099 break;
1100 case CONTINUATION:
1101 frame_size_without_variable_data = GetContinuationMinimumSize();
1102 break;
1103 default:
1104 frame_size_without_variable_data = -1;
1105 break;
1108 if ((frame_size_without_variable_data == -1) &&
1109 (current_frame_length_ > kControlFrameBufferSize)) {
1110 // We should already be in an error state. Double-check.
1111 DCHECK_EQ(SPDY_ERROR, state_);
1112 if (state_ != SPDY_ERROR) {
1113 LOG(DFATAL) << display_protocol_
1114 << " control frame buffer too small for fixed-length frame.";
1115 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1117 return;
1120 if (frame_size_without_variable_data > 0) {
1121 // We have a control frame with a header block. We need to parse the
1122 // remainder of the control frame's header before we can parse the header
1123 // block. The start of the header block varies with the control type.
1124 DCHECK_GE(frame_size_without_variable_data,
1125 static_cast<int32>(current_frame_buffer_length_));
1126 remaining_control_header_ = frame_size_without_variable_data -
1127 current_frame_buffer_length_;
1129 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1130 return;
1133 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1136 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1137 size_t max_bytes) {
1138 size_t bytes_to_read = std::min(*len, max_bytes);
1139 if (bytes_to_read > 0) {
1140 DCHECK_GE(kControlFrameBufferSize,
1141 current_frame_buffer_length_ + bytes_to_read);
1142 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1143 *data,
1144 bytes_to_read);
1145 current_frame_buffer_length_ += bytes_to_read;
1146 *data += bytes_to_read;
1147 *len -= bytes_to_read;
1149 return bytes_to_read;
1152 size_t SpdyFramer::GetSerializedLength(
1153 const SpdyMajorVersion spdy_version,
1154 const SpdyHeaderBlock* headers) {
1155 const size_t num_name_value_pairs_size
1156 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1157 const size_t length_of_name_size = num_name_value_pairs_size;
1158 const size_t length_of_value_size = num_name_value_pairs_size;
1160 size_t total_length = num_name_value_pairs_size;
1161 for (SpdyHeaderBlock::const_iterator it = headers->begin();
1162 it != headers->end();
1163 ++it) {
1164 // We add space for the length of the name and the length of the value as
1165 // well as the length of the name and the length of the value.
1166 total_length += length_of_name_size + it->first.size() +
1167 length_of_value_size + it->second.size();
1169 return total_length;
1172 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1173 const SpdyMajorVersion spdy_version,
1174 const SpdyHeaderBlock* headers) {
1175 if (spdy_version < SPDY3) {
1176 frame->WriteUInt16(headers->size()); // Number of headers.
1177 } else {
1178 frame->WriteUInt32(headers->size()); // Number of headers.
1180 SpdyHeaderBlock::const_iterator it;
1181 for (it = headers->begin(); it != headers->end(); ++it) {
1182 if (spdy_version < SPDY3) {
1183 frame->WriteString(it->first);
1184 frame->WriteString(it->second);
1185 } else {
1186 frame->WriteStringPiece32(it->first);
1187 frame->WriteStringPiece32(it->second);
1192 // TODO(phajdan.jr): Clean up after we no longer need
1193 // to workaround http://crbug.com/139744.
1194 #if !defined(USE_SYSTEM_ZLIB)
1196 // These constants are used by zlib to differentiate between normal data and
1197 // cookie data. Cookie data is handled specially by zlib when compressing.
1198 enum ZDataClass {
1199 // kZStandardData is compressed normally, save that it will never match
1200 // against any other class of data in the window.
1201 kZStandardData = Z_CLASS_STANDARD,
1202 // kZCookieData is compressed in its own Huffman blocks and only matches in
1203 // its entirety and only against other kZCookieData blocks. Any matches must
1204 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1205 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1206 // prefix matches.
1207 kZCookieData = Z_CLASS_COOKIE,
1208 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1209 // against the window.
1210 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1213 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1214 // needed when switching between classes of data.
1215 static void WriteZ(const base::StringPiece& data,
1216 ZDataClass clas,
1217 z_stream* out) {
1218 int rv;
1220 // If we are switching from standard to non-standard data then we need to end
1221 // the current Huffman context to avoid it leaking between them.
1222 if (out->clas == kZStandardData &&
1223 clas != kZStandardData) {
1224 out->avail_in = 0;
1225 rv = deflate(out, Z_PARTIAL_FLUSH);
1226 DCHECK_EQ(Z_OK, rv);
1227 DCHECK_EQ(0u, out->avail_in);
1228 DCHECK_LT(0u, out->avail_out);
1231 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1232 out->avail_in = data.size();
1233 out->clas = clas;
1234 if (clas == kZStandardData) {
1235 rv = deflate(out, Z_NO_FLUSH);
1236 } else {
1237 rv = deflate(out, Z_PARTIAL_FLUSH);
1239 if (!data.empty()) {
1240 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1241 DCHECK_EQ(Z_OK, rv);
1243 DCHECK_EQ(0u, out->avail_in);
1244 DCHECK_LT(0u, out->avail_out);
1247 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1248 static void WriteLengthZ(size_t n,
1249 unsigned length,
1250 ZDataClass clas,
1251 z_stream* out) {
1252 char buf[4];
1253 DCHECK_LE(length, sizeof(buf));
1254 for (unsigned i = 1; i <= length; i++) {
1255 buf[length - i] = n;
1256 n >>= 8;
1258 WriteZ(base::StringPiece(buf, length), clas, out);
1261 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1262 // manner that resists the length of the compressed data from compromising
1263 // cookie data.
1264 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1265 z_stream* z) const {
1266 unsigned length_length = 4;
1267 if (spdy_version_ < 3)
1268 length_length = 2;
1270 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1272 std::map<std::string, std::string>::const_iterator it;
1273 for (it = headers->begin(); it != headers->end(); ++it) {
1274 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1275 WriteZ(it->first, kZStandardData, z);
1277 if (it->first == "cookie") {
1278 // We require the cookie values (save for the last) to end with a
1279 // semicolon and (save for the first) to start with a space. This is
1280 // typically the format that we are given them in but we reserialize them
1281 // to be sure.
1283 std::vector<base::StringPiece> cookie_values;
1284 size_t cookie_length = 0;
1285 base::StringPiece cookie_data(it->second);
1287 for (;;) {
1288 while (!cookie_data.empty() &&
1289 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1290 cookie_data.remove_prefix(1);
1292 if (cookie_data.empty())
1293 break;
1295 size_t i;
1296 for (i = 0; i < cookie_data.size(); i++) {
1297 if (cookie_data[i] == ';')
1298 break;
1300 if (i < cookie_data.size()) {
1301 if (!IsCookieEmpty(cookie_data.substr(0, i))) {
1302 cookie_values.push_back(cookie_data.substr(0, i));
1303 cookie_length += i + 2 /* semicolon and space */;
1305 cookie_data.remove_prefix(i + 1);
1306 } else {
1307 if (!IsCookieEmpty(cookie_data)) {
1308 cookie_values.push_back(cookie_data);
1309 cookie_length += cookie_data.size();
1310 } else if (cookie_length > 2) {
1311 cookie_length -= 2 /* compensate for previously added length */;
1313 cookie_data.remove_prefix(i);
1317 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1318 for (size_t i = 0; i < cookie_values.size(); i++) {
1319 std::string cookie;
1320 // Since zlib will only back-reference complete cookies, a cookie that
1321 // is currently last (and so doesn't have a trailing semicolon) won't
1322 // match if it's later in a non-final position. The same is true of
1323 // the first cookie.
1324 if (i == 0 && cookie_values.size() == 1) {
1325 cookie = cookie_values[i].as_string();
1326 } else if (i == 0) {
1327 cookie = cookie_values[i].as_string() + ";";
1328 } else if (i < cookie_values.size() - 1) {
1329 cookie = " " + cookie_values[i].as_string() + ";";
1330 } else {
1331 cookie = " " + cookie_values[i].as_string();
1333 WriteZ(cookie, kZCookieData, z);
1335 } else if (it->first == "accept" ||
1336 it->first == "accept-charset" ||
1337 it->first == "accept-encoding" ||
1338 it->first == "accept-language" ||
1339 it->first == "host" ||
1340 it->first == "version" ||
1341 it->first == "method" ||
1342 it->first == "scheme" ||
1343 it->first == ":host" ||
1344 it->first == ":version" ||
1345 it->first == ":method" ||
1346 it->first == ":scheme" ||
1347 it->first == "user-agent") {
1348 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1349 WriteZ(it->second, kZStandardData, z);
1350 } else {
1351 // Non-whitelisted headers are Huffman compressed in their own block, but
1352 // don't match against the window.
1353 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1354 WriteZ(it->second, kZHuffmanOnlyData, z);
1358 z->avail_in = 0;
1359 int rv = deflate(z, Z_SYNC_FLUSH);
1360 DCHECK_EQ(Z_OK, rv);
1361 z->clas = kZStandardData;
1364 #endif // !defined(USE_SYSTEM_ZLIB)
1366 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1367 size_t len) {
1368 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1369 const size_t original_len = len;
1371 if (remaining_control_header_ > 0) {
1372 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1373 remaining_control_header_);
1374 remaining_control_header_ -= bytes_read;
1375 remaining_data_length_ -= bytes_read;
1378 if (remaining_control_header_ == 0) {
1379 SpdyFrameReader reader(current_frame_buffer_.get(),
1380 current_frame_buffer_length_);
1381 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1383 switch (current_frame_type_) {
1384 case SYN_STREAM:
1386 DCHECK_GE(SPDY3, protocol_version());
1387 bool successful_read = true;
1388 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1389 DCHECK(successful_read);
1390 if (current_frame_stream_id_ == 0) {
1391 set_error(SPDY_INVALID_CONTROL_FRAME);
1392 break;
1395 SpdyStreamId associated_to_stream_id = kInvalidStream;
1396 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1397 DCHECK(successful_read);
1399 SpdyPriority priority = 0;
1400 successful_read = reader.ReadUInt8(&priority);
1401 DCHECK(successful_read);
1402 if (protocol_version() <= SPDY2) {
1403 priority = priority >> 6;
1404 } else {
1405 priority = priority >> 5;
1408 // Seek past unused byte; used to be credential slot in SPDY 3.
1409 reader.Seek(1);
1411 DCHECK(reader.IsDoneReading());
1412 if (debug_visitor_) {
1413 debug_visitor_->OnReceiveCompressedFrame(
1414 current_frame_stream_id_,
1415 current_frame_type_,
1416 current_frame_length_);
1418 visitor_->OnSynStream(
1419 current_frame_stream_id_,
1420 associated_to_stream_id,
1421 priority,
1422 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1423 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1425 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1426 break;
1427 case SETTINGS:
1428 if (protocol_version() > SPDY3 &&
1429 current_frame_flags_ & SETTINGS_FLAG_ACK) {
1430 visitor_->OnSettingsAck();
1431 CHANGE_STATE(SPDY_AUTO_RESET);
1432 } else {
1433 visitor_->OnSettings(current_frame_flags_ &
1434 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1435 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1437 break;
1438 case SYN_REPLY:
1439 case HEADERS:
1440 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1442 if (protocol_version() > SPDY3) {
1443 DCHECK_EQ(HEADERS, current_frame_type_);
1445 bool successful_read = true;
1446 if (protocol_version() <= SPDY3) {
1447 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1448 DCHECK(successful_read);
1450 if (current_frame_stream_id_ == 0) {
1451 set_error(SPDY_INVALID_CONTROL_FRAME);
1452 break;
1454 if (protocol_version() <= SPDY2) {
1455 // SPDY 2 had two unused bytes here. Seek past them.
1456 reader.Seek(2);
1458 if (protocol_version() > SPDY3 &&
1459 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1460 current_frame_type_ == HEADERS) {
1461 expect_continuation_ = current_frame_stream_id_;
1462 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1464 const bool has_priority =
1465 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1466 uint32 priority = 0;
1467 if (protocol_version() > SPDY3 && has_priority) {
1468 // TODO(jgraettinger): Process dependency rather than ignoring it.
1469 reader.Seek(kPriorityDependencyPayloadSize);
1470 uint8 weight = 0;
1471 successful_read = reader.ReadUInt8(&weight);
1472 if (successful_read) {
1473 priority = MapWeightToPriority(weight);
1476 DCHECK(reader.IsDoneReading());
1477 if (debug_visitor_) {
1478 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1479 SpdyFrameType reported_type = current_frame_type_;
1480 if (protocol_version() > SPDY3 && has_priority) {
1481 reported_type = SYN_STREAM;
1483 debug_visitor_->OnReceiveCompressedFrame(
1484 current_frame_stream_id_,
1485 reported_type,
1486 current_frame_length_);
1488 if (current_frame_type_ == SYN_REPLY) {
1489 visitor_->OnSynReply(
1490 current_frame_stream_id_,
1491 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1492 } else if (protocol_version() > SPDY3 &&
1493 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1494 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1495 // can be made independent of wire changes.
1496 visitor_->OnSynStream(
1497 current_frame_stream_id_,
1498 0, // associated_to_stream_id
1499 priority,
1500 current_frame_flags_ & CONTROL_FLAG_FIN,
1501 false); // unidirectional
1502 } else {
1503 visitor_->OnHeaders(
1504 current_frame_stream_id_,
1505 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1506 expect_continuation_ == 0);
1509 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1510 break;
1511 case PUSH_PROMISE:
1513 DCHECK_LT(SPDY3, protocol_version());
1514 if (current_frame_stream_id_ == 0) {
1515 set_error(SPDY_INVALID_CONTROL_FRAME);
1516 break;
1518 SpdyStreamId promised_stream_id = kInvalidStream;
1519 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1520 DCHECK(successful_read);
1521 DCHECK(reader.IsDoneReading());
1522 if (promised_stream_id == 0) {
1523 set_error(SPDY_INVALID_CONTROL_FRAME);
1524 break;
1526 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1527 expect_continuation_ = current_frame_stream_id_;
1529 if (debug_visitor_) {
1530 debug_visitor_->OnReceiveCompressedFrame(
1531 current_frame_stream_id_,
1532 current_frame_type_,
1533 current_frame_length_);
1535 visitor_->OnPushPromise(current_frame_stream_id_,
1536 promised_stream_id,
1537 (current_frame_flags_ &
1538 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1540 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1541 break;
1542 case CONTINUATION:
1544 // Check to make sure the stream id of the current frame is
1545 // the same as that of the preceding frame.
1546 // If we're at this point we should already know that
1547 // expect_continuation_ != 0, so this doubles as a check
1548 // that current_frame_stream_id != 0.
1549 if (current_frame_stream_id_ != expect_continuation_) {
1550 set_error(SPDY_INVALID_CONTROL_FRAME);
1551 break;
1553 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1554 expect_continuation_ = 0;
1556 if (debug_visitor_) {
1557 debug_visitor_->OnReceiveCompressedFrame(
1558 current_frame_stream_id_,
1559 current_frame_type_,
1560 current_frame_length_);
1562 visitor_->OnContinuation(current_frame_stream_id_,
1563 (current_frame_flags_ &
1564 HEADERS_FLAG_END_HEADERS) != 0);
1566 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1567 break;
1568 default:
1569 DCHECK(false);
1572 return original_len - len;
1575 // Does not buffer the control payload. Instead, either passes directly to the
1576 // visitor or decompresses and then passes directly to the visitor, via
1577 // IncrementallyDeliverControlFrameHeaderData() or
1578 // IncrementallyDecompressControlFrameHeaderData() respectively.
1579 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1580 size_t data_len,
1581 bool is_hpack_header_block) {
1582 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1584 bool processed_successfully = true;
1585 if (current_frame_type_ != SYN_STREAM &&
1586 current_frame_type_ != SYN_REPLY &&
1587 current_frame_type_ != HEADERS &&
1588 current_frame_type_ != PUSH_PROMISE &&
1589 current_frame_type_ != CONTINUATION) {
1590 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1592 size_t process_bytes = std::min(
1593 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1594 if (is_hpack_header_block) {
1595 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1596 current_frame_stream_id_, data, process_bytes)) {
1597 // TODO(jgraettinger): Finer-grained HPACK error codes.
1598 set_error(SPDY_DECOMPRESS_FAILURE);
1599 processed_successfully = false;
1601 } else if (process_bytes > 0) {
1602 if (enable_compression_ && protocol_version() <= SPDY3) {
1603 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1604 current_frame_stream_id_, data, process_bytes);
1605 } else {
1606 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1607 current_frame_stream_id_, data, process_bytes);
1610 remaining_data_length_ -= process_bytes;
1612 // Handle the case that there is no futher data in this frame.
1613 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1614 processed_successfully) {
1615 if (expect_continuation_ == 0) {
1616 if (is_hpack_header_block) {
1617 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1618 current_frame_stream_id_)) {
1619 set_error(SPDY_DECOMPRESS_FAILURE);
1620 processed_successfully = false;
1621 } else {
1622 // TODO(jgraettinger): To be removed with migration to
1623 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1624 // block, delivered via reentrant call to
1625 // ProcessControlFrameHeaderBlock().
1626 DeliverHpackBlockAsSpdy3Block();
1627 return process_bytes;
1629 } else {
1630 // The complete header block has been delivered. We send a zero-length
1631 // OnControlFrameHeaderData() to indicate this.
1632 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1635 if (processed_successfully) {
1636 CHANGE_STATE(SPDY_CONSUME_PADDING);
1640 // Handle error.
1641 if (!processed_successfully) {
1642 return data_len;
1645 // Return amount processed.
1646 return process_bytes;
1649 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1650 size_t data_len) {
1651 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1652 DCHECK_EQ(SETTINGS, current_frame_type_);
1653 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1654 size_t processed_bytes = 0;
1656 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
1658 // Loop over our incoming data.
1659 while (unprocessed_bytes > 0) {
1660 // Process up to one setting at a time.
1661 size_t processing = std::min(
1662 unprocessed_bytes,
1663 static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
1665 // Check if we have a complete setting in our input.
1666 if (processing == setting_size) {
1667 // Parse the setting directly out of the input without buffering.
1668 if (!ProcessSetting(data + processed_bytes)) {
1669 set_error(SPDY_INVALID_CONTROL_FRAME);
1670 return processed_bytes;
1672 } else {
1673 // Continue updating settings_scratch_.setting_buf.
1674 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1675 data + processed_bytes,
1676 processing);
1677 settings_scratch_.setting_buf_len += processing;
1679 // Check if we have a complete setting buffered.
1680 if (settings_scratch_.setting_buf_len == setting_size) {
1681 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1682 set_error(SPDY_INVALID_CONTROL_FRAME);
1683 return processed_bytes;
1685 // Reset settings_scratch_.setting_buf for our next setting.
1686 settings_scratch_.setting_buf_len = 0;
1690 // Iterate.
1691 unprocessed_bytes -= processing;
1692 processed_bytes += processing;
1695 // Check if we're done handling this SETTINGS frame.
1696 remaining_data_length_ -= processed_bytes;
1697 if (remaining_data_length_ == 0) {
1698 visitor_->OnSettingsEnd();
1699 CHANGE_STATE(SPDY_AUTO_RESET);
1702 return processed_bytes;
1705 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1706 DCHECK_LT(SPDY3, protocol_version());
1707 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1709 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
1710 if (block.empty()) {
1711 // Special-case this to make tests happy.
1712 ProcessControlFrameHeaderBlock(NULL, 0, false);
1713 return;
1715 SpdyFrameBuilder builder(
1716 GetSerializedLength(protocol_version(), &block),
1717 SPDY3);
1719 SerializeNameValueBlockWithoutCompression(&builder, block);
1720 scoped_ptr<SpdyFrame> frame(builder.take());
1722 // Preserve padding length, and reset it after the re-entrant call.
1723 size_t remaining_padding = remaining_padding_payload_length_;
1725 remaining_padding_payload_length_ = 0;
1726 remaining_data_length_ = frame->size();
1728 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1730 remaining_padding_payload_length_ = remaining_padding;
1731 remaining_data_length_ = remaining_padding;
1734 bool SpdyFramer::ProcessSetting(const char* data) {
1735 int id_field;
1736 SpdySettingsIds id;
1737 uint8 flags = 0;
1738 uint32 value;
1740 // Extract fields.
1741 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1742 if (protocol_version() <= SPDY3) {
1743 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1744 SettingsFlagsAndId id_and_flags =
1745 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1746 id_field = id_and_flags.id();
1747 flags = id_and_flags.flags();
1748 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1749 } else {
1750 id_field = ntohs(*(reinterpret_cast<const uint16*>(data)));
1751 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2)));
1754 // Validate id.
1755 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1756 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1757 if (protocol_version() <= SPDY3) {
1758 return false;
1759 } else {
1760 // In HTTP2 we ignore unknown settings for extensibility.
1761 return true;
1764 id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1766 if (protocol_version() <= SPDY3) {
1767 // Detect duplicates.
1768 if (id <= settings_scratch_.last_setting_id) {
1769 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1770 << " in " << display_protocol_ << " SETTINGS frame "
1771 << "(last setting id was "
1772 << settings_scratch_.last_setting_id << ").";
1773 return false;
1775 settings_scratch_.last_setting_id = id;
1777 // Validate flags.
1778 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1779 if ((flags & ~(kFlagsMask)) != 0) {
1780 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1781 << flags;
1782 return false;
1786 // Validation succeeded. Pass on to visitor.
1787 visitor_->OnSetting(id, flags, value);
1788 return true;
1791 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1792 size_t original_len = len;
1793 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1794 remaining_data_length_);
1795 remaining_data_length_ -= bytes_read;
1796 if (remaining_data_length_ == 0) {
1797 SpdyFrameReader reader(current_frame_buffer_.get(),
1798 current_frame_buffer_length_);
1799 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1801 // Use frame-specific handlers.
1802 switch (current_frame_type_) {
1803 case PING: {
1804 SpdyPingId id = 0;
1805 bool is_ack = protocol_version() > SPDY3 &&
1806 (current_frame_flags_ & PING_FLAG_ACK);
1807 bool successful_read = true;
1808 if (protocol_version() <= SPDY3) {
1809 uint32 id32 = 0;
1810 successful_read = reader.ReadUInt32(&id32);
1811 id = id32;
1812 } else {
1813 successful_read = reader.ReadUInt64(&id);
1815 DCHECK(successful_read);
1816 DCHECK(reader.IsDoneReading());
1817 visitor_->OnPing(id, is_ack);
1819 break;
1820 case WINDOW_UPDATE: {
1821 uint32 delta_window_size = 0;
1822 bool successful_read = true;
1823 if (protocol_version() <= SPDY3) {
1824 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1825 DCHECK(successful_read);
1827 successful_read = reader.ReadUInt32(&delta_window_size);
1828 DCHECK(successful_read);
1829 DCHECK(reader.IsDoneReading());
1830 visitor_->OnWindowUpdate(current_frame_stream_id_,
1831 delta_window_size);
1833 break;
1834 case BLOCKED: {
1835 DCHECK_LT(SPDY3, protocol_version());
1836 DCHECK(reader.IsDoneReading());
1837 visitor_->OnBlocked(current_frame_stream_id_);
1839 break;
1840 case PRIORITY: {
1841 DCHECK_LT(SPDY3, protocol_version());
1842 uint32 parent_stream_id;
1843 uint8 weight;
1844 bool exclusive;
1845 bool successful_read = true;
1846 successful_read = reader.ReadUInt32(&parent_stream_id);
1847 DCHECK(successful_read);
1848 // Exclusivity is indicated by a single bit flag.
1849 exclusive = (parent_stream_id >> 31) != 0;
1850 // Zero out the highest-order bit to get the parent stream id.
1851 parent_stream_id &= 0x7fffffff;
1852 successful_read = reader.ReadUInt8(&weight);
1853 DCHECK(successful_read);
1854 DCHECK(reader.IsDoneReading());
1855 visitor_->OnPriority(
1856 current_frame_stream_id_, parent_stream_id, weight, exclusive);
1858 break;
1859 default:
1860 // Unreachable.
1861 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1864 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1866 return original_len - len;
1869 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1870 if (len == 0) {
1871 return 0;
1873 // Clamp to the actual remaining payload.
1874 if (len > remaining_data_length_) {
1875 len = remaining_data_length_;
1877 size_t original_len = len;
1879 // Check if we had already read enough bytes to parse the GOAWAY header.
1880 const size_t header_size = GetGoAwayMinimumSize();
1881 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1882 bool already_parsed_header = (unread_header_bytes == 0);
1883 if (!already_parsed_header) {
1884 // Buffer the new GOAWAY header bytes we got.
1885 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1887 // Do we have enough to parse the constant size GOAWAY header?
1888 if (current_frame_buffer_length_ == header_size) {
1889 // Parse out the last good stream id.
1890 SpdyFrameReader reader(current_frame_buffer_.get(),
1891 current_frame_buffer_length_);
1892 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1893 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1894 DCHECK(successful_read);
1896 // In SPDYv3 and up, frames also specify a status code - parse it out.
1897 SpdyGoAwayStatus status = GOAWAY_OK;
1898 if (protocol_version() >= SPDY3) {
1899 uint32 status_raw = GOAWAY_OK;
1900 successful_read = reader.ReadUInt32(&status_raw);
1901 DCHECK(successful_read);
1902 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1903 status_raw)) {
1904 status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1905 status_raw);
1906 } else {
1907 if (protocol_version() > SPDY3) {
1908 // Treat unrecognized status codes as INTERNAL_ERROR as
1909 // recommended by the HTTP/2 spec.
1910 status = GOAWAY_INTERNAL_ERROR;
1914 // Finished parsing the GOAWAY header, call frame handler.
1915 visitor_->OnGoAway(current_frame_stream_id_, status);
1919 // Handle remaining data as opaque.
1920 bool processed_successfully = true;
1921 if (len > 0) {
1922 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1924 remaining_data_length_ -= original_len;
1925 if (!processed_successfully) {
1926 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1927 } else if (remaining_data_length_ == 0) {
1928 // Signal that there is not more opaque data.
1929 visitor_->OnGoAwayFrameData(NULL, 0);
1930 CHANGE_STATE(SPDY_AUTO_RESET);
1932 return original_len;
1935 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1936 if (len == 0) {
1937 return 0;
1939 // Clamp to the actual remaining payload.
1940 if (len > remaining_data_length_) {
1941 len = remaining_data_length_;
1943 size_t original_len = len;
1945 // Check if we had already read enough bytes to parse the fixed-length portion
1946 // of the RST_STREAM frame.
1947 const size_t header_size = GetRstStreamMinimumSize();
1948 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1949 bool already_parsed_header = (unread_header_bytes == 0);
1950 if (!already_parsed_header) {
1951 // Buffer the new RST_STREAM header bytes we got.
1952 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1954 // Do we have enough to parse the constant size RST_STREAM header?
1955 if (current_frame_buffer_length_ == header_size) {
1956 // Parse out the last good stream id.
1957 SpdyFrameReader reader(current_frame_buffer_.get(),
1958 current_frame_buffer_length_);
1959 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1960 if (protocol_version() <= SPDY3) {
1961 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1962 DCHECK(successful_read);
1965 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1966 uint32 status_raw = status;
1967 bool successful_read = reader.ReadUInt32(&status_raw);
1968 DCHECK(successful_read);
1969 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1970 status_raw)) {
1971 status = static_cast<SpdyRstStreamStatus>(status_raw);
1972 } else {
1973 if (protocol_version() > SPDY3) {
1974 // Treat unrecognized status codes as INTERNAL_ERROR as
1975 // recommended by the HTTP/2 spec.
1976 status = RST_STREAM_INTERNAL_ERROR;
1979 // Finished parsing the RST_STREAM header, call frame handler.
1980 visitor_->OnRstStream(current_frame_stream_id_, status);
1984 // Handle remaining data as opaque.
1985 bool processed_successfully = true;
1986 if (len > 0) {
1987 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
1989 remaining_data_length_ -= original_len;
1990 if (!processed_successfully) {
1991 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
1992 } else if (remaining_data_length_ == 0) {
1993 // Signal that there is not more opaque data.
1994 visitor_->OnRstStreamFrameData(NULL, 0);
1995 CHANGE_STATE(SPDY_AUTO_RESET);
1997 return original_len;
2000 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
2001 if (len == 0) {
2002 return 0;
2005 // Clamp to the actual remaining payload.
2006 len = std::min(len, remaining_data_length_);
2008 size_t processed_bytes = 0;
2009 size_t processing = 0;
2010 size_t bytes_remaining;
2011 char* buffer;
2012 size_t* buffer_len;
2014 while (len > 0) {
2015 if (altsvc_scratch_.pid_len == 0) {
2016 // The size of the frame up to the PID_LEN field.
2017 size_t fixed_len_portion = GetAltSvcMinimumSize() - 1;
2018 bytes_remaining = fixed_len_portion - current_frame_buffer_length_;
2019 processing = std::min(len, bytes_remaining);
2020 // Buffer the new ALTSVC bytes we got.
2021 UpdateCurrentFrameBuffer(&data, &len, processing);
2023 // Do we have enough to parse the length of the protocol id?
2024 if (current_frame_buffer_length_ == fixed_len_portion) {
2025 // Parse out the max age, port, and pid_len.
2026 SpdyFrameReader reader(current_frame_buffer_.get(),
2027 current_frame_buffer_length_);
2028 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2029 bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age);
2030 reader.ReadUInt16(&altsvc_scratch_.port);
2031 reader.Seek(1); // Reserved byte.
2032 successful_read = successful_read &&
2033 reader.ReadUInt8(&altsvc_scratch_.pid_len);
2034 DCHECK(successful_read);
2035 // Sanity check length value.
2036 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >=
2037 current_frame_length_) {
2038 set_error(SPDY_INVALID_CONTROL_FRAME);
2039 return 0;
2041 altsvc_scratch_.protocol_id.reset(
2042 new char[size_t(altsvc_scratch_.pid_len)]);
2044 processed_bytes += processing;
2045 continue;
2046 } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) {
2047 // Buffer protocol id field as in comes in.
2048 buffer = altsvc_scratch_.protocol_id.get();
2049 buffer_len = &altsvc_scratch_.pid_buf_len;
2050 bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len;
2051 } else if (altsvc_scratch_.host_len == 0) {
2052 // Parse out the host length.
2053 processing = 1;
2054 altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data);
2055 // Sanity check length value.
2056 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len +
2057 altsvc_scratch_.host_len > current_frame_length_) {
2058 set_error(SPDY_INVALID_CONTROL_FRAME);
2059 return 0;
2061 altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]);
2062 // Once we have host length, we can also determine the origin length
2063 // by process of elimination.
2064 altsvc_scratch_.origin_len = current_frame_length_ -
2065 GetAltSvcMinimumSize() -
2066 altsvc_scratch_.pid_len -
2067 altsvc_scratch_.host_len;
2068 if (altsvc_scratch_.origin_len > 0) {
2069 altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]);
2071 data += processing;
2072 processed_bytes += processing;
2073 len -= processing;
2074 continue;
2075 } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) {
2076 // Buffer host field as it comes in.
2077 // TODO(mlavan): check formatting for host and origin
2078 buffer = altsvc_scratch_.host.get();
2079 buffer_len = &altsvc_scratch_.host_buf_len;
2080 bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len;
2081 } else {
2082 // Buffer (optional) origin field as it comes in.
2083 if (altsvc_scratch_.origin_len <= 0) {
2084 set_error(SPDY_INVALID_CONTROL_FRAME);
2085 return 0;
2087 buffer = altsvc_scratch_.origin.get();
2088 buffer_len = &altsvc_scratch_.origin_buf_len;
2089 bytes_remaining = remaining_data_length_ -
2090 processed_bytes -
2091 altsvc_scratch_.origin_buf_len;
2092 if (len > bytes_remaining) {
2093 // This is our last field; there shouldn't be any more bytes.
2094 set_error(SPDY_INVALID_CONTROL_FRAME);
2095 return 0;
2099 // Copy data bytes into the appropriate field.
2100 processing = std::min(len, bytes_remaining);
2101 memcpy(buffer + *buffer_len,
2102 data,
2103 processing);
2104 *buffer_len += processing;
2105 data += processing;
2106 processed_bytes += processing;
2107 len -= processing;
2110 remaining_data_length_ -= processed_bytes;
2111 if (remaining_data_length_ == 0) {
2112 visitor_->OnAltSvc(current_frame_stream_id_,
2113 altsvc_scratch_.max_age,
2114 altsvc_scratch_.port,
2115 StringPiece(altsvc_scratch_.protocol_id.get(),
2116 altsvc_scratch_.pid_len),
2117 StringPiece(altsvc_scratch_.host.get(),
2118 altsvc_scratch_.host_len),
2119 StringPiece(altsvc_scratch_.origin.get(),
2120 altsvc_scratch_.origin_len));
2121 CHANGE_STATE(SPDY_AUTO_RESET);
2124 return processed_bytes;
2127 // TODO(raullenchai): ProcessFramePaddingLength should be able to deal with
2128 // HEADERS_FLAG_PADDED and PUSH_PROMISE_FLAG_PADDED as well (see b/15777051).
2129 size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
2130 DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
2131 DCHECK_EQ(remaining_padding_payload_length_, 0u);
2133 size_t original_len = len;
2134 if (current_frame_flags_ & DATA_FLAG_PADDED) {
2135 if (len != 0) {
2136 if (remaining_data_length_ < 1) {
2137 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2138 return 0;
2141 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data);
2142 ++data;
2143 --len;
2144 --remaining_data_length_;
2145 } else {
2146 // We don't have the data available for parsing the pad length field. Keep
2147 // waiting.
2148 return 0;
2152 if (remaining_padding_payload_length_ > remaining_data_length_) {
2153 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2154 return 0;
2156 if (current_frame_type_ == DATA) {
2157 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2158 } else {
2159 DCHECK(current_frame_type_ == HEADERS ||
2160 current_frame_type_ == PUSH_PROMISE ||
2161 current_frame_type_ == SYN_STREAM ||
2162 current_frame_type_ == SYN_REPLY)
2163 << current_frame_type_;
2164 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
2166 return original_len - len;
2169 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2170 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2172 size_t original_len = len;
2173 if (remaining_padding_payload_length_ > 0) {
2174 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2175 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2176 if (current_frame_type_ == DATA && amount_to_discard > 0) {
2177 // The visitor needs to know about padding so it can send window updates.
2178 // Communicate the padding to the visitor through a NULL data pointer,
2179 // with a nonzero size.
2180 visitor_->OnStreamFrameData(
2181 current_frame_stream_id_, NULL, amount_to_discard, false);
2183 data += amount_to_discard;
2184 len -= amount_to_discard;
2185 remaining_padding_payload_length_ -= amount_to_discard;
2186 remaining_data_length_ -= amount_to_discard;
2189 if (remaining_data_length_ == 0) {
2190 // If the FIN flag is set, or this ends a header block which set FIN,
2191 // inform the visitor of EOF via a 0-length data frame.
2192 if (expect_continuation_ == 0 &&
2193 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2194 end_stream_when_done_)) {
2195 end_stream_when_done_ = false;
2196 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2198 CHANGE_STATE(SPDY_AUTO_RESET);
2200 return original_len - len;
2203 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2204 size_t original_len = len;
2205 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2206 size_t amount_to_forward = std::min(
2207 remaining_data_length_ - remaining_padding_payload_length_, len);
2208 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2209 // Only inform the visitor if there is data.
2210 if (amount_to_forward) {
2211 visitor_->OnStreamFrameData(
2212 current_frame_stream_id_, data, amount_to_forward, false);
2215 data += amount_to_forward;
2216 len -= amount_to_forward;
2217 remaining_data_length_ -= amount_to_forward;
2220 if (remaining_data_length_ == remaining_padding_payload_length_) {
2221 CHANGE_STATE(SPDY_CONSUME_PADDING);
2223 return original_len - len;
2226 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2227 size_t len) {
2228 size_t original_len = len;
2229 if (remaining_data_length_ > 0) {
2230 size_t amount_to_ignore = std::min(remaining_data_length_, len);
2231 len -= amount_to_ignore;
2232 remaining_data_length_ -= amount_to_ignore;
2235 if (remaining_data_length_ == 0) {
2236 CHANGE_STATE(SPDY_AUTO_RESET);
2238 return original_len - len;
2241 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2242 size_t header_length,
2243 SpdyHeaderBlock* block) const {
2244 SpdyFrameReader reader(header_data, header_length);
2246 // Read number of headers.
2247 uint32 num_headers;
2248 if (protocol_version() <= SPDY2) {
2249 uint16 temp;
2250 if (!reader.ReadUInt16(&temp)) {
2251 DVLOG(1) << "Unable to read number of headers.";
2252 return 0;
2254 num_headers = temp;
2255 } else {
2256 if (!reader.ReadUInt32(&num_headers)) {
2257 DVLOG(1) << "Unable to read number of headers.";
2258 return 0;
2262 // Read each header.
2263 for (uint32 index = 0; index < num_headers; ++index) {
2264 base::StringPiece temp;
2266 // Read header name.
2267 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2268 : !reader.ReadStringPiece32(&temp)) {
2269 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2270 << num_headers << ").";
2271 return 0;
2273 std::string name = temp.as_string();
2275 // Read header value.
2276 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2277 : !reader.ReadStringPiece32(&temp)) {
2278 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2279 << num_headers << ").";
2280 return 0;
2282 std::string value = temp.as_string();
2284 // Ensure no duplicates.
2285 if (block->find(name) != block->end()) {
2286 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2287 << num_headers << ").";
2288 return 0;
2291 // Store header.
2292 (*block)[name] = value;
2294 return reader.GetBytesConsumed();
2297 SpdySerializedFrame* SpdyFramer::SerializeData(
2298 const SpdyDataIR& data_ir) const {
2299 uint8 flags = DATA_FLAG_NONE;
2300 if (data_ir.fin()) {
2301 flags = DATA_FLAG_FIN;
2304 if (protocol_version() > SPDY3) {
2305 int num_padding_fields = 0;
2306 if (data_ir.padded()) {
2307 flags |= DATA_FLAG_PADDED;
2308 ++num_padding_fields;
2311 const size_t size_with_padding = num_padding_fields +
2312 data_ir.data().length() + data_ir.padding_payload_len() +
2313 GetDataFrameMinimumSize();
2314 SpdyFrameBuilder builder(size_with_padding, protocol_version());
2315 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2316 if (data_ir.padded()) {
2317 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2319 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2320 if (data_ir.padding_payload_len() > 0) {
2321 string padding = string(data_ir.padding_payload_len(), '0');
2322 builder.WriteBytes(padding.data(), padding.length());
2324 DCHECK_EQ(size_with_padding, builder.length());
2325 return builder.take();
2326 } else {
2327 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2328 SpdyFrameBuilder builder(size, protocol_version());
2329 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2330 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2331 DCHECK_EQ(size, builder.length());
2332 return builder.take();
2336 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2337 const SpdyDataIR& data_ir) const {
2338 uint8 flags = DATA_FLAG_NONE;
2339 if (data_ir.fin()) {
2340 flags = DATA_FLAG_FIN;
2343 size_t frame_size = GetDataFrameMinimumSize();
2344 size_t num_padding_fields = 0;
2345 if (protocol_version() > SPDY3) {
2346 if (data_ir.padded()) {
2347 flags |= DATA_FLAG_PADDED;
2348 ++num_padding_fields;
2350 frame_size += num_padding_fields;
2353 SpdyFrameBuilder builder(frame_size, protocol_version());
2354 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2355 if (protocol_version() > SPDY3) {
2356 if (data_ir.padded()) {
2357 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2359 builder.OverwriteLength(*this, num_padding_fields +
2360 data_ir.data().length() + data_ir.padding_payload_len());
2361 } else {
2362 builder.OverwriteLength(*this, data_ir.data().length());
2364 DCHECK_EQ(frame_size, builder.length());
2365 return builder.take();
2368 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2369 const SpdySynStreamIR& syn_stream) {
2370 DCHECK_GE(SPDY3, protocol_version());
2371 uint8 flags = 0;
2372 if (syn_stream.fin()) {
2373 flags |= CONTROL_FLAG_FIN;
2375 if (syn_stream.unidirectional()) {
2376 // TODO(hkhalil): invalid for HTTP2.
2377 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2380 // Sanitize priority.
2381 uint8 priority = syn_stream.priority();
2382 if (priority > GetLowestPriority()) {
2383 DLOG(DFATAL) << "Priority out-of-bounds.";
2384 priority = GetLowestPriority();
2387 // The size of this frame, including variable-length name-value block.
2388 size_t size = GetSynStreamMinimumSize() +
2389 GetSerializedLength(syn_stream.name_value_block());
2391 SpdyFrameBuilder builder(size, protocol_version());
2392 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2393 builder.WriteUInt32(syn_stream.stream_id());
2394 builder.WriteUInt32(syn_stream.associated_to_stream_id());
2395 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2396 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
2397 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2398 SerializeNameValueBlock(&builder, syn_stream);
2400 if (debug_visitor_) {
2401 const size_t payload_len =
2402 GetSerializedLength(protocol_version(),
2403 &(syn_stream.name_value_block()));
2404 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2405 SYN_STREAM,
2406 payload_len,
2407 builder.length());
2410 return builder.take();
2413 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2414 const SpdySynReplyIR& syn_reply) {
2415 DCHECK_GE(SPDY3, protocol_version());
2416 uint8 flags = 0;
2417 if (syn_reply.fin()) {
2418 flags |= CONTROL_FLAG_FIN;
2421 // The size of this frame, including variable-length name-value block.
2422 const size_t size = GetSynReplyMinimumSize() +
2423 GetSerializedLength(syn_reply.name_value_block());
2425 SpdyFrameBuilder builder(size, protocol_version());
2426 if (protocol_version() <= SPDY3) {
2427 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2428 builder.WriteUInt32(syn_reply.stream_id());
2429 } else {
2430 builder.BeginNewFrame(*this,
2431 HEADERS,
2432 flags,
2433 syn_reply.stream_id());
2435 if (protocol_version() < SPDY3) {
2436 builder.WriteUInt16(0); // Unused.
2438 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2439 SerializeNameValueBlock(&builder, syn_reply);
2441 if (debug_visitor_) {
2442 const size_t payload_len = GetSerializedLength(
2443 protocol_version(), &(syn_reply.name_value_block()));
2444 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2445 SYN_REPLY,
2446 payload_len,
2447 builder.length());
2450 return builder.take();
2453 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2454 const SpdyRstStreamIR& rst_stream) const {
2455 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2456 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2457 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2458 // commented but left in place to simplify future patching.
2459 // Compute the output buffer size, taking opaque data into account.
2460 uint16 expected_length = GetRstStreamMinimumSize();
2461 if (protocol_version() > SPDY3) {
2462 expected_length += rst_stream.description().size();
2464 SpdyFrameBuilder builder(expected_length, protocol_version());
2466 // Serialize the RST_STREAM frame.
2467 if (protocol_version() <= SPDY3) {
2468 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2469 builder.WriteUInt32(rst_stream.stream_id());
2470 } else {
2471 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2474 builder.WriteUInt32(rst_stream.status());
2476 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2477 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2478 builder.WriteBytes(rst_stream.description().data(),
2479 rst_stream.description().size());
2482 DCHECK_EQ(expected_length, builder.length());
2483 return builder.take();
2486 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2487 const SpdySettingsIR& settings) const {
2488 uint8 flags = 0;
2490 if (protocol_version() <= SPDY3) {
2491 if (settings.clear_settings()) {
2492 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2494 } else {
2495 if (settings.is_ack()) {
2496 flags |= SETTINGS_FLAG_ACK;
2499 const SpdySettingsIR::ValueMap* values = &(settings.values());
2501 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
2502 // Size, in bytes, of this SETTINGS frame.
2503 const size_t size = GetSettingsMinimumSize() +
2504 (values->size() * setting_size);
2505 SpdyFrameBuilder builder(size, protocol_version());
2506 if (protocol_version() <= SPDY3) {
2507 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2508 } else {
2509 builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2512 // If this is an ACK, payload should be empty.
2513 if (protocol_version() > SPDY3 && settings.is_ack()) {
2514 return builder.take();
2517 if (protocol_version() <= SPDY3) {
2518 builder.WriteUInt32(values->size());
2520 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2521 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2522 it != values->end();
2523 ++it) {
2524 if (protocol_version() <= SPDY3) {
2525 uint8 setting_flags = 0;
2526 if (it->second.persist_value) {
2527 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2529 if (it->second.persisted) {
2530 setting_flags |= SETTINGS_FLAG_PERSISTED;
2532 SettingsFlagsAndId flags_and_id(
2533 setting_flags,
2534 SpdyConstants::SerializeSettingId(protocol_version(), it->first));
2535 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2536 builder.WriteBytes(&id_and_flags_wire, 4);
2537 } else {
2538 builder.WriteUInt16(SpdyConstants::SerializeSettingId(protocol_version(),
2539 it->first));
2541 builder.WriteUInt32(it->second.value);
2543 DCHECK_EQ(size, builder.length());
2544 return builder.take();
2547 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2548 SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2549 if (protocol_version() <= SPDY3) {
2550 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2551 builder.WriteUInt32(static_cast<uint32>(ping.id()));
2552 } else {
2553 uint8 flags = 0;
2554 if (ping.is_ack()) {
2555 flags |= PING_FLAG_ACK;
2557 builder.BeginNewFrame(*this, PING, flags, 0);
2558 builder.WriteUInt64(ping.id());
2560 DCHECK_EQ(GetPingSize(), builder.length());
2561 return builder.take();
2564 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2565 const SpdyGoAwayIR& goaway) const {
2567 // Compute the output buffer size, take opaque data into account.
2568 uint16 expected_length = GetGoAwayMinimumSize();
2569 if (protocol_version() > SPDY3) {
2570 expected_length += goaway.description().size();
2572 SpdyFrameBuilder builder(expected_length, protocol_version());
2574 // Serialize the GOAWAY frame.
2575 if (protocol_version() <= SPDY3) {
2576 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2577 } else {
2578 builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2581 // GOAWAY frames specify the last good stream id for all SPDY versions.
2582 builder.WriteUInt32(goaway.last_good_stream_id());
2584 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2585 if (protocol_version() >= SPDY3) {
2586 // TODO(jgraettinger): Merge back to server-side.
2587 builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2588 goaway.status()));
2591 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2592 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2593 builder.WriteBytes(goaway.description().data(),
2594 goaway.description().size());
2597 DCHECK_EQ(expected_length, builder.length());
2598 return builder.take();
2601 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2602 const SpdyHeadersIR& headers) {
2603 uint8 flags = 0;
2604 if (headers.fin()) {
2605 flags |= CONTROL_FLAG_FIN;
2607 if (protocol_version() > SPDY3) {
2608 // This will get overwritten if we overflow into a CONTINUATION frame.
2609 flags |= HEADERS_FLAG_END_HEADERS;
2610 if (headers.has_priority()) {
2611 flags |= HEADERS_FLAG_PRIORITY;
2615 // The size of this frame, including variable-length name-value block.
2616 size_t size = GetHeadersMinimumSize();
2618 uint32 priority = headers.priority();
2619 if (headers.has_priority()) {
2620 if (priority > GetLowestPriority()) {
2621 DLOG(DFATAL) << "Priority out-of-bounds.";
2622 priority = GetLowestPriority();
2624 size += 5;
2627 string hpack_encoding;
2628 if (protocol_version() > SPDY3) {
2629 if (enable_compression_) {
2630 GetHpackEncoder()->EncodeHeaderSet(
2631 headers.name_value_block(), &hpack_encoding);
2632 } else {
2633 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2634 headers.name_value_block(), &hpack_encoding);
2636 size += hpack_encoding.size();
2637 if (size > GetHeaderFragmentMaxSize()) {
2638 size += GetNumberRequiredContinuationFrames(size) *
2639 GetContinuationMinimumSize();
2640 flags &= ~HEADERS_FLAG_END_HEADERS;
2642 } else {
2643 size += GetSerializedLength(headers.name_value_block());
2646 SpdyFrameBuilder builder(size, protocol_version());
2647 if (protocol_version() <= SPDY3) {
2648 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2649 builder.WriteUInt32(headers.stream_id());
2650 } else {
2651 builder.BeginNewFrame(*this,
2652 HEADERS,
2653 flags,
2654 headers.stream_id());
2656 if (protocol_version() <= SPDY2) {
2657 builder.WriteUInt16(0); // Unused.
2659 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2661 if (protocol_version() > SPDY3) {
2662 if (headers.has_priority()) {
2663 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2664 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2665 builder.WriteUInt8(MapPriorityToWeight(priority));
2667 WritePayloadWithContinuation(&builder,
2668 hpack_encoding,
2669 headers.stream_id(),
2670 HEADERS);
2671 } else {
2672 SerializeNameValueBlock(&builder, headers);
2675 if (debug_visitor_) {
2676 // SPDY4 uses HPACK for header compression. However, continue to
2677 // use GetSerializedLength() for an apples-to-apples comparision of
2678 // compression performance between HPACK and SPDY w/ deflate.
2679 const size_t payload_len =
2680 GetSerializedLength(protocol_version(),
2681 &(headers.name_value_block()));
2682 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2683 HEADERS,
2684 payload_len,
2685 builder.length());
2688 return builder.take();
2691 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2692 const SpdyWindowUpdateIR& window_update) const {
2693 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2694 if (protocol_version() <= SPDY3) {
2695 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2696 builder.WriteUInt32(window_update.stream_id());
2697 } else {
2698 builder.BeginNewFrame(*this,
2699 WINDOW_UPDATE,
2700 kNoFlags,
2701 window_update.stream_id());
2703 builder.WriteUInt32(window_update.delta());
2704 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2705 return builder.take();
2708 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2709 DCHECK_LT(SPDY3, protocol_version());
2710 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2711 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2712 return builder.take();
2715 SpdyFrame* SpdyFramer::SerializePushPromise(
2716 const SpdyPushPromiseIR& push_promise) {
2717 DCHECK_LT(SPDY3, protocol_version());
2718 uint8 flags = 0;
2719 // This will get overwritten if we overflow into a CONTINUATION frame.
2720 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2721 // The size of this frame, including variable-length name-value block.
2722 size_t size = GetPushPromiseMinimumSize();
2724 string hpack_encoding;
2725 if (enable_compression_) {
2726 GetHpackEncoder()->EncodeHeaderSet(
2727 push_promise.name_value_block(), &hpack_encoding);
2728 } else {
2729 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2730 push_promise.name_value_block(), &hpack_encoding);
2732 size += hpack_encoding.size();
2733 if (size > GetHeaderFragmentMaxSize()) {
2734 size += GetNumberRequiredContinuationFrames(size) *
2735 GetContinuationMinimumSize();
2736 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2739 SpdyFrameBuilder builder(size, protocol_version());
2740 builder.BeginNewFrame(*this,
2741 PUSH_PROMISE,
2742 flags,
2743 push_promise.stream_id());
2744 builder.WriteUInt32(push_promise.promised_stream_id());
2745 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2747 WritePayloadWithContinuation(&builder,
2748 hpack_encoding,
2749 push_promise.stream_id(),
2750 PUSH_PROMISE);
2752 if (debug_visitor_) {
2753 // SPDY4 uses HPACK for header compression. However, continue to
2754 // use GetSerializedLength() for an apples-to-apples comparision of
2755 // compression performance between HPACK and SPDY w/ deflate.
2756 const size_t payload_len =
2757 GetSerializedLength(protocol_version(),
2758 &(push_promise.name_value_block()));
2759 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2760 PUSH_PROMISE,
2761 payload_len,
2762 builder.length());
2765 return builder.take();
2768 // TODO(jgraettinger): This implementation is incorrect. The continuation
2769 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2770 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2771 SpdyFrame* SpdyFramer::SerializeContinuation(
2772 const SpdyContinuationIR& continuation) {
2773 CHECK_LT(SPDY3, protocol_version());
2774 uint8 flags = 0;
2775 if (continuation.end_headers()) {
2776 flags |= HEADERS_FLAG_END_HEADERS;
2779 // The size of this frame, including variable-length name-value block.
2780 size_t size = GetContinuationMinimumSize();
2781 string hpack_encoding;
2782 if (enable_compression_) {
2783 GetHpackEncoder()->EncodeHeaderSet(
2784 continuation.name_value_block(), &hpack_encoding);
2785 } else {
2786 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2787 continuation.name_value_block(), &hpack_encoding);
2789 size += hpack_encoding.size();
2791 SpdyFrameBuilder builder(size, protocol_version());
2792 builder.BeginNewFrame(*this, CONTINUATION, flags,
2793 continuation.stream_id());
2794 DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2796 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2797 return builder.take();
2800 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
2801 DCHECK_LT(SPDY3, protocol_version());
2802 size_t size = GetAltSvcMinimumSize();
2803 size += altsvc.protocol_id().length();
2804 size += altsvc.host().length();
2805 size += altsvc.origin().length();
2807 SpdyFrameBuilder builder(size, protocol_version());
2808 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
2810 builder.WriteUInt32(altsvc.max_age());
2811 builder.WriteUInt16(altsvc.port());
2812 builder.WriteUInt8(0); // Reserved.
2813 builder.WriteUInt8(altsvc.protocol_id().length());
2814 builder.WriteBytes(altsvc.protocol_id().data(),
2815 altsvc.protocol_id().length());
2816 builder.WriteUInt8(altsvc.host().length());
2817 builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
2818 builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
2819 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2820 return builder.take();
2823 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) {
2824 DCHECK_LT(SPDY3, protocol_version());
2825 size_t size = GetPrioritySize();
2827 SpdyFrameBuilder builder(size, protocol_version());
2828 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
2830 // Make sure the highest-order bit in the parent stream id is zeroed out.
2831 uint32 parent_stream_id = priority.parent_stream_id() & 0x7fffffff;
2832 uint32 exclusive = priority.exclusive() ? 0x80000000 : 0;
2833 // Set the one-bit exclusivity flag.
2834 uint32 flag_and_parent_id = parent_stream_id | exclusive;
2835 builder.WriteUInt32(flag_and_parent_id);
2836 builder.WriteUInt8(priority.weight());
2837 DCHECK_EQ(GetPrioritySize(), builder.length());
2838 return builder.take();
2841 namespace {
2843 class FrameSerializationVisitor : public SpdyFrameVisitor {
2844 public:
2845 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2846 virtual ~FrameSerializationVisitor() {}
2848 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2850 virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2851 frame_.reset(framer_->SerializeData(data));
2853 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2854 frame_.reset(framer_->SerializeSynStream(syn_stream));
2856 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2857 frame_.reset(framer_->SerializeSynReply(syn_reply));
2859 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2860 frame_.reset(framer_->SerializeRstStream(rst_stream));
2862 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2863 frame_.reset(framer_->SerializeSettings(settings));
2865 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2866 frame_.reset(framer_->SerializePing(ping));
2868 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2869 frame_.reset(framer_->SerializeGoAway(goaway));
2871 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2872 frame_.reset(framer_->SerializeHeaders(headers));
2874 virtual void VisitWindowUpdate(
2875 const SpdyWindowUpdateIR& window_update) OVERRIDE {
2876 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2878 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2879 frame_.reset(framer_->SerializeBlocked(blocked));
2881 virtual void VisitPushPromise(
2882 const SpdyPushPromiseIR& push_promise) OVERRIDE {
2883 frame_.reset(framer_->SerializePushPromise(push_promise));
2885 virtual void VisitContinuation(
2886 const SpdyContinuationIR& continuation) OVERRIDE {
2887 frame_.reset(framer_->SerializeContinuation(continuation));
2889 virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) OVERRIDE {
2890 frame_.reset(framer_->SerializeAltSvc(altsvc));
2892 virtual void VisitPriority(const SpdyPriorityIR& priority) OVERRIDE {
2893 frame_.reset(framer_->SerializePriority(priority));
2896 private:
2897 SpdyFramer* framer_;
2898 scoped_ptr<SpdySerializedFrame> frame_;
2901 } // namespace
2903 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2904 FrameSerializationVisitor visitor(this);
2905 frame.Visit(&visitor);
2906 return visitor.ReleaseSerializedFrame();
2909 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2910 CHECK_GE(SPDY3, protocol_version());
2911 const size_t uncompressed_length =
2912 GetSerializedLength(protocol_version(), &headers);
2913 if (!enable_compression_) {
2914 return uncompressed_length;
2916 z_stream* compressor = GetHeaderCompressor();
2917 // Since we'll be performing lots of flushes when compressing the data,
2918 // zlib's lower bounds may be insufficient.
2919 return 2 * deflateBound(compressor, uncompressed_length);
2922 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2923 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
2924 DCHECK_GT(protocol_version(), SPDY3);
2925 DCHECK_GT(size, kMaxControlFrameSize);
2926 size_t overflow = size - kMaxControlFrameSize;
2927 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1;
2930 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2931 const string& hpack_encoding,
2932 SpdyStreamId stream_id,
2933 SpdyFrameType type) {
2934 const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
2936 // In addition to the prefix, fixed_field_size includes the size of
2937 // any fields that come before the variable-length name/value block.
2938 size_t fixed_field_size = 0;
2939 uint8 end_flag = 0;
2940 uint8 flags = 0;
2941 if (type == HEADERS) {
2942 fixed_field_size = GetHeadersMinimumSize();
2943 end_flag = HEADERS_FLAG_END_HEADERS;
2944 } else if (type == PUSH_PROMISE) {
2945 fixed_field_size = GetPushPromiseMinimumSize();
2946 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2947 } else {
2948 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2949 << FrameTypeToString(type);
2952 // Write as much of the payload as possible into the initial frame.
2953 size_t bytes_remaining = hpack_encoding.size() -
2954 std::min(hpack_encoding.size(),
2955 kMaxControlFrameSize - fixed_field_size);
2956 builder->WriteBytes(&hpack_encoding[0],
2957 hpack_encoding.size() - bytes_remaining);
2959 if (bytes_remaining > 0) {
2960 builder->OverwriteLength(*this,
2961 kMaxControlFrameSize - GetControlFrameHeaderSize());
2964 // Tack on CONTINUATION frames for the overflow.
2965 while (bytes_remaining > 0) {
2966 size_t bytes_to_write = std::min(bytes_remaining,
2967 kMaxControlFrameSize -
2968 GetContinuationMinimumSize());
2969 // Write CONTINUATION frame prefix.
2970 if (bytes_remaining == bytes_to_write) {
2971 flags |= end_flag;
2973 builder->BeginNewFrame(*this,
2974 CONTINUATION,
2975 flags,
2976 stream_id);
2977 // Write payload fragment.
2978 builder->WriteBytes(&hpack_encoding[hpack_encoding.size() -
2979 bytes_remaining],
2980 bytes_to_write);
2981 bytes_remaining -= bytes_to_write;
2985 // The following compression setting are based on Brian Olson's analysis. See
2986 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2987 // for more details.
2988 #if defined(USE_SYSTEM_ZLIB)
2989 // System zlib is not expected to have workaround for http://crbug.com/139744,
2990 // so disable compression in that case.
2991 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2992 static const int kCompressorLevel = 0;
2993 #else // !defined(USE_SYSTEM_ZLIB)
2994 static const int kCompressorLevel = 9;
2995 #endif // !defined(USE_SYSTEM_ZLIB)
2996 static const int kCompressorWindowSizeInBits = 11;
2997 static const int kCompressorMemLevel = 1;
2999 z_stream* SpdyFramer::GetHeaderCompressor() {
3000 if (header_compressor_.get())
3001 return header_compressor_.get(); // Already initialized.
3003 header_compressor_.reset(new z_stream);
3004 memset(header_compressor_.get(), 0, sizeof(z_stream));
3006 int success = deflateInit2(header_compressor_.get(),
3007 kCompressorLevel,
3008 Z_DEFLATED,
3009 kCompressorWindowSizeInBits,
3010 kCompressorMemLevel,
3011 Z_DEFAULT_STRATEGY);
3012 if (success == Z_OK) {
3013 const char* dictionary = (protocol_version() <= SPDY2) ?
3014 kV2Dictionary : kV3Dictionary;
3015 const int dictionary_size = (protocol_version() <= SPDY2) ?
3016 kV2DictionarySize : kV3DictionarySize;
3017 success = deflateSetDictionary(header_compressor_.get(),
3018 reinterpret_cast<const Bytef*>(dictionary),
3019 dictionary_size);
3021 if (success != Z_OK) {
3022 LOG(WARNING) << "deflateSetDictionary failure: " << success;
3023 header_compressor_.reset(NULL);
3024 return NULL;
3026 return header_compressor_.get();
3029 z_stream* SpdyFramer::GetHeaderDecompressor() {
3030 if (header_decompressor_.get())
3031 return header_decompressor_.get(); // Already initialized.
3033 header_decompressor_.reset(new z_stream);
3034 memset(header_decompressor_.get(), 0, sizeof(z_stream));
3036 int success = inflateInit(header_decompressor_.get());
3037 if (success != Z_OK) {
3038 LOG(WARNING) << "inflateInit failure: " << success;
3039 header_decompressor_.reset(NULL);
3040 return NULL;
3042 return header_decompressor_.get();
3045 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3046 DCHECK_LT(SPDY3, spdy_version_);
3047 if (hpack_encoder_.get() == NULL) {
3048 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3050 return hpack_encoder_.get();
3053 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3054 DCHECK_LT(SPDY3, spdy_version_);
3055 if (hpack_decoder_.get() == NULL) {
3056 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3058 return hpack_decoder_.get();
3061 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3062 const float kSteps = 255.9f / 7.f;
3063 return static_cast<uint8>(kSteps * (7.f - priority));
3066 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3067 const float kSteps = 255.9f / 7.f;
3068 return static_cast<SpdyPriority>(7.f - weight / kSteps);
3071 // Incrementally decompress the control frame's header block, feeding the
3072 // result to the visitor in chunks. Continue this until the visitor
3073 // indicates that it cannot process any more data, or (more commonly) we
3074 // run out of data to deliver.
3075 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3076 SpdyStreamId stream_id,
3077 const char* data,
3078 size_t len) {
3079 // Get a decompressor or set error.
3080 z_stream* decomp = GetHeaderDecompressor();
3081 if (decomp == NULL) {
3082 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3083 set_error(SPDY_DECOMPRESS_FAILURE);
3084 return false;
3087 bool processed_successfully = true;
3088 char buffer[kHeaderDataChunkMaxSize];
3090 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3091 decomp->avail_in = len;
3092 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3093 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3094 // reached this method successfully, stream_id should be nonzero.
3095 DCHECK_LT(0u, stream_id);
3096 while (decomp->avail_in > 0 && processed_successfully) {
3097 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3098 decomp->avail_out = arraysize(buffer);
3100 int rv = inflate(decomp, Z_SYNC_FLUSH);
3101 if (rv == Z_NEED_DICT) {
3102 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3103 : kV3Dictionary;
3104 const int dictionary_size = (protocol_version() <= SPDY2) ?
3105 kV2DictionarySize : kV3DictionarySize;
3106 const DictionaryIds& ids = g_dictionary_ids.Get();
3107 const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3108 ids.v2_dictionary_id : ids.v3_dictionary_id;
3109 // Need to try again with the right dictionary.
3110 if (decomp->adler == dictionary_id) {
3111 rv = inflateSetDictionary(decomp,
3112 reinterpret_cast<const Bytef*>(dictionary),
3113 dictionary_size);
3114 if (rv == Z_OK)
3115 rv = inflate(decomp, Z_SYNC_FLUSH);
3119 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3120 // without producing any output. The input is consumed and
3121 // buffered internally by zlib so we can detect this condition by
3122 // checking if avail_in is 0 after the call to inflate.
3123 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3124 if ((rv == Z_OK) || input_exhausted) {
3125 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3126 if (decompressed_len > 0) {
3127 processed_successfully = visitor_->OnControlFrameHeaderData(
3128 stream_id, buffer, decompressed_len);
3130 if (!processed_successfully) {
3131 // Assume that the problem was the header block was too large for the
3132 // visitor.
3133 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3135 } else {
3136 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3137 set_error(SPDY_DECOMPRESS_FAILURE);
3138 processed_successfully = false;
3141 return processed_successfully;
3144 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3145 SpdyStreamId stream_id, const char* data, size_t len) {
3146 bool read_successfully = true;
3147 while (read_successfully && len > 0) {
3148 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3149 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3150 bytes_to_deliver);
3151 data += bytes_to_deliver;
3152 len -= bytes_to_deliver;
3153 if (!read_successfully) {
3154 // Assume that the problem was the header block was too large for the
3155 // visitor.
3156 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3159 return read_successfully;
3162 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3163 SpdyFrameBuilder* builder,
3164 const SpdyNameValueBlock& name_value_block) const {
3165 // Serialize number of headers.
3166 if (protocol_version() <= SPDY2) {
3167 builder->WriteUInt16(name_value_block.size());
3168 } else {
3169 builder->WriteUInt32(name_value_block.size());
3172 // Serialize each header.
3173 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3174 it != name_value_block.end();
3175 ++it) {
3176 if (protocol_version() <= SPDY2) {
3177 builder->WriteString(it->first);
3178 builder->WriteString(it->second);
3179 } else {
3180 builder->WriteStringPiece32(it->first);
3181 builder->WriteStringPiece32(it->second);
3186 void SpdyFramer::SerializeNameValueBlock(
3187 SpdyFrameBuilder* builder,
3188 const SpdyFrameWithNameValueBlockIR& frame) {
3189 CHECK_GE(SPDY3, protocol_version());
3190 if (!enable_compression_) {
3191 return SerializeNameValueBlockWithoutCompression(builder,
3192 frame.name_value_block());
3195 // First build an uncompressed version to be fed into the compressor.
3196 const size_t uncompressed_len = GetSerializedLength(
3197 protocol_version(), &(frame.name_value_block()));
3198 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3199 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
3200 frame.name_value_block());
3201 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3203 z_stream* compressor = GetHeaderCompressor();
3204 if (!compressor) {
3205 LOG(DFATAL) << "Could not obtain compressor.";
3206 return;
3209 base::StatsCounter compressed_frames("spdy.CompressedFrames");
3210 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
3211 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
3213 // Create an output frame.
3214 // Since we'll be performing lots of flushes when compressing the data,
3215 // zlib's lower bounds may be insufficient.
3217 // TODO(akalin): Avoid the duplicate calculation with
3218 // GetSerializedLength(const SpdyHeaderBlock&).
3219 const int compressed_max_size =
3220 2 * deflateBound(compressor, uncompressed_len);
3222 // TODO(phajdan.jr): Clean up after we no longer need
3223 // to workaround http://crbug.com/139744.
3224 #if defined(USE_SYSTEM_ZLIB)
3225 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3226 compressor->avail_in = uncompressed_len;
3227 #endif // defined(USE_SYSTEM_ZLIB)
3228 compressor->next_out = reinterpret_cast<Bytef*>(
3229 builder->GetWritableBuffer(compressed_max_size));
3230 compressor->avail_out = compressed_max_size;
3232 // TODO(phajdan.jr): Clean up after we no longer need
3233 // to workaround http://crbug.com/139744.
3234 #if defined(USE_SYSTEM_ZLIB)
3235 int rv = deflate(compressor, Z_SYNC_FLUSH);
3236 if (rv != Z_OK) { // How can we know that it compressed everything?
3237 // This shouldn't happen, right?
3238 LOG(WARNING) << "deflate failure: " << rv;
3239 // TODO(akalin): Upstream this return.
3240 return;
3242 #else
3243 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
3244 #endif // defined(USE_SYSTEM_ZLIB)
3246 int compressed_size = compressed_max_size - compressor->avail_out;
3247 builder->Seek(compressed_size);
3248 builder->RewriteLength(*this);
3250 pre_compress_bytes.Add(uncompressed_len);
3251 post_compress_bytes.Add(compressed_size);
3253 compressed_frames.Increment();
3256 } // namespace net