spdy_framer.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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. 4 5#include "net/spdy/spdy_framer.h" 6 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" 15 16using std::string; 17using std::vector; 18 19namespace net { 20 21namespace { 22 23// Compute the id of our dictionary so that we know we're using the 24// right one when asked for it. 25uLong CalculateDictionaryId(const char* dictionary, 26 const size_t dictionary_size) { 27 uLong initial_value = adler32(0L, Z_NULL, 0); 28 return adler32(initial_value, 29 reinterpret_cast<const Bytef*>(dictionary), 30 dictionary_size); 31} 32 33struct DictionaryIds { 34 DictionaryIds() 35 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)), 36 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize)) 37 {} 38 const uLong v2_dictionary_id; 39 const uLong v3_dictionary_id; 40}; 41 42// Adler ID for the SPDY header compressor dictionaries. Note that they are 43// initialized lazily to avoid static initializers. 44base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; 45 46// Used to indicate no flags in a SPDY flags field. 47const uint8 kNoFlags = 0; 48 49} // namespace 50 51const SpdyStreamId SpdyFramer::kInvalidStream = -1; 52const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; 53// The size of the control frame buffer. Must be >= the minimum size of the 54// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for 55// calculation details. 56const size_t SpdyFramer::kControlFrameBufferSize = 18; 57 58#ifdef DEBUG_SPDY_STATE_CHANGES 59#define CHANGE_STATE(newstate) \ 60 do { \ 61 DVLOG(1) << "Changing state from: " \ 62 << StateToString(state_) \ 63 << " to " << StateToString(newstate) << "\n"; \ 64 DCHECK(state_ != SPDY_ERROR); \ 65 DCHECK_EQ(previous_state_, state_); \ 66 previous_state_ = state_; \ 67 state_ = newstate; \ 68 } while (false) 69#else 70#define CHANGE_STATE(newstate) \ 71 do { \ 72 DCHECK(state_ != SPDY_ERROR); \ 73 DCHECK_EQ(previous_state_, state_); \ 74 previous_state_ = state_; \ 75 state_ = newstate; \ 76 } while (false) 77#endif 78 79SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat( 80 SpdyMajorVersion version, uint32 wire) { 81 if (version < SPDY3) { 82 ConvertFlagsAndIdForSpdy2(&wire); 83 } 84 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); 85} 86 87SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) 88 : flags_(flags), id_(id & 0x00ffffff) { 89 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id; 90} 91 92uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version) 93 const { 94 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); 95 if (version < SPDY3) { 96 ConvertFlagsAndIdForSpdy2(&wire); 97 } 98 return wire; 99} 100 101// SPDY 2 had a bug in it with respect to byte ordering of id/flags field. 102// This method is used to preserve buggy behavior and works on both 103// little-endian and big-endian hosts. 104// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 105// as well as vice versa). 106void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) { 107 uint8* wire_array = reinterpret_cast<uint8*>(val); 108 std::swap(wire_array[0], wire_array[3]); 109 std::swap(wire_array[1], wire_array[2]); 110} 111 112bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data, 113 size_t len) { 114 return true; 115} 116 117bool SpdyFramerVisitorInterface::OnRstStreamFrameData( 118 const char* rst_stream_data, 119 size_t len) { 120 return true; 121} 122 123SpdyFramer::SpdyFramer(SpdyMajorVersion version) 124 : current_frame_buffer_(new char[kControlFrameBufferSize]), 125 enable_compression_(true), 126 hpack_encoder_(ObtainHpackHuffmanTable()), 127 hpack_decoder_(ObtainHpackHuffmanTable()), 128 visitor_(NULL), 129 debug_visitor_(NULL), 130 display_protocol_("SPDY"), 131 spdy_version_(version), 132 syn_frame_processed_(false), 133 probable_http_response_(false), 134 expect_continuation_(0), 135 end_stream_when_done_(false) { 136 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); 137 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); 138 Reset(); 139} 140 141SpdyFramer::~SpdyFramer() { 142 if (header_compressor_.get()) { 143 deflateEnd(header_compressor_.get()); 144 } 145 if (header_decompressor_.get()) { 146 inflateEnd(header_decompressor_.get()); 147 } 148} 149 150void SpdyFramer::Reset() { 151 state_ = SPDY_RESET; 152 previous_state_ = SPDY_RESET; 153 error_code_ = SPDY_NO_ERROR; 154 remaining_data_length_ = 0; 155 remaining_control_header_ = 0; 156 current_frame_buffer_length_ = 0; 157 current_frame_type_ = DATA; 158 current_frame_flags_ = 0; 159 current_frame_length_ = 0; 160 current_frame_stream_id_ = kInvalidStream; 161 settings_scratch_.Reset(); 162 remaining_padding_payload_length_ = 0; 163 remaining_padding_length_fields_ = 0; 164} 165 166size_t SpdyFramer::GetDataFrameMinimumSize() const { 167 return SpdyConstants::GetDataFrameMinimumSize(); 168} 169 170// Size, in bytes, of the control frame header. 171size_t SpdyFramer::GetControlFrameHeaderSize() const { 172 return SpdyConstants::GetControlFrameHeaderSize(protocol_version()); 173} 174 175size_t SpdyFramer::GetSynStreamMinimumSize() const { 176 // Size, in bytes, of a SYN_STREAM frame not including the variable-length 177 // name-value block. 178 if (protocol_version() <= SPDY3) { 179 // Calculated as: 180 // control frame header + 2 * 4 (stream IDs) + 1 (priority) 181 // + 1 (unused, was credential slot) 182 return GetControlFrameHeaderSize() + 10; 183 } else { 184 // Calculated as: 185 // frame prefix + 4 (priority) 186 return GetControlFrameHeaderSize() + 4; 187 } 188} 189 190size_t SpdyFramer::GetSynReplyMinimumSize() const { 191 // Size, in bytes, of a SYN_REPLY frame not including the variable-length 192 // name-value block. 193 size_t size = GetControlFrameHeaderSize(); 194 if (protocol_version() <= SPDY3) { 195 // Calculated as: 196 // control frame header + 4 (stream IDs) 197 size += 4; 198 } 199 200 // In SPDY 2, there were 2 unused bytes before payload. 201 if (protocol_version() < SPDY3) { 202 size += 2; 203 } 204 205 return size; 206} 207 208size_t SpdyFramer::GetRstStreamMinimumSize() const { 209 // Size, in bytes, of a RST_STREAM frame. 210 if (protocol_version() <= SPDY3) { 211 // Calculated as: 212 // control frame header + 4 (stream id) + 4 (status code) 213 return GetControlFrameHeaderSize() + 8; 214 } else { 215 // Calculated as: 216 // frame prefix + 4 (status code) 217 return GetControlFrameHeaderSize() + 4; 218 } 219} 220 221size_t SpdyFramer::GetSettingsMinimumSize() const { 222 // Size, in bytes, of a SETTINGS frame not including the IDs and values 223 // from the variable-length value block. Calculated as: 224 // control frame header + 4 (number of ID/value pairs) 225 if (protocol_version() <= SPDY3) { 226 return GetControlFrameHeaderSize() + 4; 227 } else { 228 return GetControlFrameHeaderSize(); 229 } 230} 231 232size_t SpdyFramer::GetPingSize() const { 233 // Size, in bytes, of this PING frame. 234 if (protocol_version() <= SPDY3) { 235 // Calculated as: 236 // control frame header + 4 (id) 237 return GetControlFrameHeaderSize() + 4; 238 } else { 239 // Calculated as: 240 // control frame header + 8 (id) 241 return GetControlFrameHeaderSize() + 8; 242 } 243} 244 245size_t SpdyFramer::GetGoAwayMinimumSize() const { 246 // Size, in bytes, of this GOAWAY frame. Calculated as: 247 // 1. Control frame header size 248 size_t size = GetControlFrameHeaderSize(); 249 250 // 2. Last good stream id (4 bytes) 251 size += 4; 252 253 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes) 254 if (protocol_version() >= SPDY3) { 255 size += 4; 256 } 257 258 return size; 259} 260 261size_t SpdyFramer::GetHeadersMinimumSize() const { 262 // Size, in bytes, of a HEADERS frame not including the variable-length 263 // name-value block. 264 size_t size = GetControlFrameHeaderSize(); 265 if (protocol_version() <= SPDY3) { 266 // Calculated as: 267 // control frame header + 4 (stream IDs) 268 size += 4; 269 } 270 271 // In SPDY 2, there were 2 unused bytes before payload. 272 if (protocol_version() <= SPDY2) { 273 size += 2; 274 } 275 276 return size; 277} 278 279size_t SpdyFramer::GetWindowUpdateSize() const { 280 // Size, in bytes, of a WINDOW_UPDATE frame. 281 if (protocol_version() <= SPDY3) { 282 // Calculated as: 283 // control frame header + 4 (stream id) + 4 (delta) 284 return GetControlFrameHeaderSize() + 8; 285 } else { 286 // Calculated as: 287 // frame prefix + 4 (delta) 288 return GetControlFrameHeaderSize() + 4; 289 } 290} 291 292size_t SpdyFramer::GetBlockedSize() const { 293 DCHECK_LT(SPDY3, protocol_version()); 294 // Size, in bytes, of a BLOCKED frame. 295 // The BLOCKED frame has no payload beyond the control frame header. 296 return GetControlFrameHeaderSize(); 297} 298 299size_t SpdyFramer::GetPushPromiseMinimumSize() const { 300 DCHECK_LT(SPDY3, protocol_version()); 301 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block. 302 // Calculated as frame prefix + 4 (promised stream id). 303 return GetControlFrameHeaderSize() + 4; 304} 305 306size_t SpdyFramer::GetContinuationMinimumSize() const { 307 // Size, in bytes, of a CONTINUATION frame not including the variable-length 308 // headers fragments. 309 return GetControlFrameHeaderSize(); 310} 311 312size_t SpdyFramer::GetFrameMinimumSize() const { 313 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); 314} 315 316size_t SpdyFramer::GetFrameMaximumSize() const { 317 return SpdyConstants::GetFrameMaximumSize(protocol_version()); 318} 319 320size_t SpdyFramer::GetDataFrameMaximumPayload() const { 321 return GetFrameMaximumSize() - GetDataFrameMinimumSize(); 322} 323 324size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const { 325 return SpdyConstants::GetPrefixLength(type, protocol_version()); 326} 327 328const char* SpdyFramer::StateToString(int state) { 329 switch (state) { 330 case SPDY_ERROR: 331 return "ERROR"; 332 case SPDY_AUTO_RESET: 333 return "AUTO_RESET"; 334 case SPDY_RESET: 335 return "RESET"; 336 case SPDY_READING_COMMON_HEADER: 337 return "READING_COMMON_HEADER"; 338 case SPDY_CONTROL_FRAME_PAYLOAD: 339 return "CONTROL_FRAME_PAYLOAD"; 340 case SPDY_READ_PADDING_LENGTH: 341 return "SPDY_READ_PADDING_LENGTH"; 342 case SPDY_CONSUME_PADDING: 343 return "SPDY_CONSUME_PADDING"; 344 case SPDY_IGNORE_REMAINING_PAYLOAD: 345 return "IGNORE_REMAINING_PAYLOAD"; 346 case SPDY_FORWARD_STREAM_FRAME: 347 return "FORWARD_STREAM_FRAME"; 348 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 349 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; 350 case SPDY_CONTROL_FRAME_HEADER_BLOCK: 351 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; 352 case SPDY_GOAWAY_FRAME_PAYLOAD: 353 return "SPDY_GOAWAY_FRAME_PAYLOAD"; 354 case SPDY_RST_STREAM_FRAME_PAYLOAD: 355 return "SPDY_RST_STREAM_FRAME_PAYLOAD"; 356 case SPDY_SETTINGS_FRAME_PAYLOAD: 357 return "SPDY_SETTINGS_FRAME_PAYLOAD"; 358 } 359 return "UNKNOWN_STATE"; 360} 361 362void SpdyFramer::set_error(SpdyError error) { 363 DCHECK(visitor_); 364 error_code_ = error; 365 // These values will usually get reset once we come to the end 366 // of a header block, but if we run into an error that 367 // might not happen, so reset them here. 368 expect_continuation_ = 0; 369 end_stream_when_done_ = false; 370 371 CHANGE_STATE(SPDY_ERROR); 372 visitor_->OnError(this); 373} 374 375const char* SpdyFramer::ErrorCodeToString(int error_code) { 376 switch (error_code) { 377 case SPDY_NO_ERROR: 378 return "NO_ERROR"; 379 case SPDY_INVALID_CONTROL_FRAME: 380 return "INVALID_CONTROL_FRAME"; 381 case SPDY_CONTROL_PAYLOAD_TOO_LARGE: 382 return "CONTROL_PAYLOAD_TOO_LARGE"; 383 case SPDY_ZLIB_INIT_FAILURE: 384 return "ZLIB_INIT_FAILURE"; 385 case SPDY_UNSUPPORTED_VERSION: 386 return "UNSUPPORTED_VERSION"; 387 case SPDY_DECOMPRESS_FAILURE: 388 return "DECOMPRESS_FAILURE"; 389 case SPDY_COMPRESS_FAILURE: 390 return "COMPRESS_FAILURE"; 391 case SPDY_INVALID_DATA_FRAME_FLAGS: 392 return "SPDY_INVALID_DATA_FRAME_FLAGS"; 393 case SPDY_INVALID_CONTROL_FRAME_FLAGS: 394 return "SPDY_INVALID_CONTROL_FRAME_FLAGS"; 395 case SPDY_UNEXPECTED_FRAME: 396 return "UNEXPECTED_FRAME"; 397 } 398 return "UNKNOWN_ERROR"; 399} 400 401const char* SpdyFramer::StatusCodeToString(int status_code) { 402 switch (status_code) { 403 case RST_STREAM_INVALID: 404 return "INVALID"; 405 case RST_STREAM_PROTOCOL_ERROR: 406 return "PROTOCOL_ERROR"; 407 case RST_STREAM_INVALID_STREAM: 408 return "INVALID_STREAM"; 409 case RST_STREAM_REFUSED_STREAM: 410 return "REFUSED_STREAM"; 411 case RST_STREAM_UNSUPPORTED_VERSION: 412 return "UNSUPPORTED_VERSION"; 413 case RST_STREAM_CANCEL: 414 return "CANCEL"; 415 case RST_STREAM_INTERNAL_ERROR: 416 return "INTERNAL_ERROR"; 417 case RST_STREAM_FLOW_CONTROL_ERROR: 418 return "FLOW_CONTROL_ERROR"; 419 case RST_STREAM_STREAM_IN_USE: 420 return "STREAM_IN_USE"; 421 case RST_STREAM_STREAM_ALREADY_CLOSED: 422 return "STREAM_ALREADY_CLOSED"; 423 case RST_STREAM_INVALID_CREDENTIALS: 424 return "INVALID_CREDENTIALS"; 425 case RST_STREAM_FRAME_TOO_LARGE: 426 return "FRAME_TOO_LARGE"; 427 case RST_STREAM_CONNECT_ERROR: 428 return "CONNECT_ERROR"; 429 case RST_STREAM_ENHANCE_YOUR_CALM: 430 return "ENHANCE_YOUR_CALM"; 431 } 432 return "UNKNOWN_STATUS"; 433} 434 435const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { 436 switch (type) { 437 case DATA: 438 return "DATA"; 439 case SYN_STREAM: 440 return "SYN_STREAM"; 441 case SYN_REPLY: 442 return "SYN_REPLY"; 443 case RST_STREAM: 444 return "RST_STREAM"; 445 case SETTINGS: 446 return "SETTINGS"; 447 case NOOP: 448 return "NOOP"; 449 case PING: 450 return "PING"; 451 case GOAWAY: 452 return "GOAWAY"; 453 case HEADERS: 454 return "HEADERS"; 455 case WINDOW_UPDATE: 456 return "WINDOW_UPDATE"; 457 case CREDENTIAL: 458 return "CREDENTIAL"; 459 case BLOCKED: 460 return "BLOCKED"; 461 case PUSH_PROMISE: 462 return "PUSH_PROMISE"; 463 case CONTINUATION: 464 return "CONTINUATION"; 465 } 466 return "UNKNOWN_CONTROL_TYPE"; 467} 468 469size_t SpdyFramer::ProcessInput(const char* data, size_t len) { 470 DCHECK(visitor_); 471 DCHECK(data); 472 473 size_t original_len = len; 474 do { 475 previous_state_ = state_; 476 switch (state_) { 477 case SPDY_ERROR: 478 goto bottom; 479 480 case SPDY_AUTO_RESET: 481 case SPDY_RESET: 482 Reset(); 483 if (len > 0) { 484 CHANGE_STATE(SPDY_READING_COMMON_HEADER); 485 } 486 break; 487 488 case SPDY_READING_COMMON_HEADER: { 489 size_t bytes_read = ProcessCommonHeader(data, len); 490 len -= bytes_read; 491 data += bytes_read; 492 break; 493 } 494 495 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { 496 // Control frames that contain header blocks 497 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION) 498 // take a different path through the state machine - they 499 // will go: 500 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 501 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK 502 // 503 // SETTINGS frames take a slightly modified route: 504 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 505 // 2. SPDY_SETTINGS_FRAME_PAYLOAD 506 // 507 // All other control frames will use the alternate route directly to 508 // SPDY_CONTROL_FRAME_PAYLOAD 509 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); 510 len -= bytes_read; 511 data += bytes_read; 512 break; 513 } 514 515 case SPDY_SETTINGS_FRAME_PAYLOAD: { 516 int bytes_read = ProcessSettingsFramePayload(data, len); 517 len -= bytes_read; 518 data += bytes_read; 519 break; 520 } 521 522 case SPDY_CONTROL_FRAME_HEADER_BLOCK: { 523 int bytes_read = ProcessControlFrameHeaderBlock( 524 data, len, protocol_version() > SPDY3); 525 len -= bytes_read; 526 data += bytes_read; 527 break; 528 } 529 530 case SPDY_RST_STREAM_FRAME_PAYLOAD: { 531 size_t bytes_read = ProcessRstStreamFramePayload(data, len); 532 len -= bytes_read; 533 data += bytes_read; 534 break; 535 } 536 537 case SPDY_GOAWAY_FRAME_PAYLOAD: { 538 size_t bytes_read = ProcessGoAwayFramePayload(data, len); 539 len -= bytes_read; 540 data += bytes_read; 541 break; 542 } 543 544 case SPDY_CONTROL_FRAME_PAYLOAD: { 545 size_t bytes_read = ProcessControlFramePayload(data, len); 546 len -= bytes_read; 547 data += bytes_read; 548 break; 549 } 550 551 case SPDY_READ_PADDING_LENGTH: { 552 size_t bytes_read = ProcessFramePaddingLength(data, len); 553 len -= bytes_read; 554 data += bytes_read; 555 break; 556 } 557 558 case SPDY_CONSUME_PADDING: { 559 size_t bytes_read = ProcessFramePadding(data, len); 560 len -= bytes_read; 561 data += bytes_read; 562 break; 563 } 564 565 case SPDY_IGNORE_REMAINING_PAYLOAD: { 566 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len); 567 len -= bytes_read; 568 data += bytes_read; 569 break; 570 } 571 572 case SPDY_FORWARD_STREAM_FRAME: { 573 size_t bytes_read = ProcessDataFramePayload(data, len); 574 len -= bytes_read; 575 data += bytes_read; 576 break; 577 } 578 579 default: 580 LOG(DFATAL) << "Invalid value for " << display_protocol_ 581 << " framer state: " << state_; 582 // This ensures that we don't infinite-loop if state_ gets an 583 // invalid value somehow, such as due to a SpdyFramer getting deleted 584 // from a callback it calls. 585 goto bottom; 586 } 587 } while (state_ != previous_state_); 588 bottom: 589 DCHECK(len == 0 || state_ == SPDY_ERROR); 590 if (current_frame_buffer_length_ == 0 && 591 remaining_data_length_ == 0 && 592 remaining_control_header_ == 0) { 593 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR) 594 << "State: " << StateToString(state_); 595 } 596 597 return original_len - len; 598} 599 600size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { 601 // This should only be called when we're in the SPDY_READING_COMMON_HEADER 602 // state. 603 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); 604 605 size_t original_len = len; 606 607 // Update current frame buffer as needed. 608 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 609 size_t bytes_desired = 610 GetControlFrameHeaderSize() - current_frame_buffer_length_; 611 UpdateCurrentFrameBuffer(&data, &len, bytes_desired); 612 } 613 614 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 615 // Not enough information to do anything meaningful. 616 return original_len - len; 617 } 618 619 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader 620 // when processing DATA frames below. 621 scoped_ptr<SpdyFrameReader> reader( 622 new SpdyFrameReader(current_frame_buffer_.get(), 623 current_frame_buffer_length_)); 624 625 uint16 version = 0; 626 bool is_control_frame = false; 627 628 uint16 control_frame_type_field = DATA; 629 // ProcessControlFrameHeader() will set current_frame_type_ to the 630 // correct value if this is a valid control frame. 631 current_frame_type_ = DATA; 632 if (protocol_version() <= SPDY3) { 633 bool successful_read = reader->ReadUInt16(&version); 634 DCHECK(successful_read); 635 is_control_frame = (version & kControlFlagMask) != 0; 636 version &= ~kControlFlagMask; // Only valid for control frames. 637 if (is_control_frame) { 638 // We check version before we check validity: version can never be 639 // 'invalid', it can only be unsupported. 640 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) || 641 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) || 642 SpdyConstants::ParseMajorVersion(version) != protocol_version()) { 643 // Version does not match the version the framer was initialized with. 644 DVLOG(1) << "Unsupported SPDY version " 645 << version 646 << " (expected " << protocol_version() << ")"; 647 set_error(SPDY_UNSUPPORTED_VERSION); 648 return 0; 649 } else { 650 // Convert version from wire format to SpdyMajorVersion. 651 version = SpdyConstants::ParseMajorVersion(version); 652 } 653 // We check control_frame_type_field's validity in 654 // ProcessControlFrameHeader(). 655 successful_read = reader->ReadUInt16(&control_frame_type_field); 656 } else { 657 reader->Rewind(); 658 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 659 } 660 DCHECK(successful_read); 661 662 successful_read = reader->ReadUInt8(¤t_frame_flags_); 663 DCHECK(successful_read); 664 665 uint32 length_field = 0; 666 successful_read = reader->ReadUInt24(&length_field); 667 DCHECK(successful_read); 668 remaining_data_length_ = length_field; 669 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); 670 } else { 671 version = protocol_version(); 672 uint16 length_field = 0; 673 bool successful_read = reader->ReadUInt16(&length_field); 674 DCHECK(successful_read); 675 676 uint8 control_frame_type_field_uint8 = DATA; 677 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); 678 DCHECK(successful_read); 679 // We check control_frame_type_field's validity in 680 // ProcessControlFrameHeader(). 681 control_frame_type_field = control_frame_type_field_uint8; 682 is_control_frame = (control_frame_type_field != DATA); 683 684 if (is_control_frame) { 685 current_frame_length_ = length_field + GetControlFrameHeaderSize(); 686 } else { 687 current_frame_length_ = length_field + GetDataFrameMinimumSize(); 688 } 689 690 successful_read = reader->ReadUInt8(¤t_frame_flags_); 691 DCHECK(successful_read); 692 693 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 694 DCHECK(successful_read); 695 696 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed(); 697 698 // Before we accept a DATA frame, we need to make sure we're not in the 699 // middle of processing a header block. 700 const bool is_continuation_frame = (control_frame_type_field == 701 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION)); 702 if ((expect_continuation_ != 0) != is_continuation_frame) { 703 if (expect_continuation_ != 0) { 704 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION " 705 << "frame, but instead received frame type " 706 << control_frame_type_field; 707 } else { 708 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame."; 709 } 710 set_error(SPDY_UNEXPECTED_FRAME); 711 return original_len - len; 712 } 713 } 714 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() 715 : GetDataFrameMinimumSize(), 716 reader->GetBytesConsumed()); 717 DCHECK_EQ(current_frame_length_, 718 remaining_data_length_ + reader->GetBytesConsumed()); 719 720 // This is just a sanity check for help debugging early frame errors. 721 if (remaining_data_length_ > 1000000u) { 722 // The strncmp for 5 is safe because we only hit this point if we 723 // have kMinCommonHeader (8) bytes 724 if (!syn_frame_processed_ && 725 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) { 726 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_ 727 << " request"; 728 probable_http_response_ = true; 729 } else { 730 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ 731 << " session is likely corrupt."; 732 } 733 } 734 735 // if we're here, then we have the common header all received. 736 if (!is_control_frame) { 737 if (protocol_version() > SPDY3) { 738 // Catch bogus tests sending oversized DATA frames. 739 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_) 740 << "DATA frame too large for SPDY >= 4."; 741 } 742 743 uint8 valid_data_flags = 0; 744 if (protocol_version() > SPDY3) { 745 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | 746 DATA_FLAG_PAD_LOW | DATA_FLAG_PAD_HIGH; 747 } else { 748 valid_data_flags = DATA_FLAG_FIN; 749 } 750 751 if (current_frame_flags_ & ~valid_data_flags) { 752 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 753 } else { 754 visitor_->OnDataFrameHeader(current_frame_stream_id_, 755 remaining_data_length_, 756 current_frame_flags_ & DATA_FLAG_FIN); 757 if (remaining_data_length_ > 0) { 758 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); 759 } else { 760 // Empty data frame. 761 if (current_frame_flags_ & DATA_FLAG_FIN) { 762 visitor_->OnStreamFrameData( 763 current_frame_stream_id_, NULL, 0, true); 764 } 765 CHANGE_STATE(SPDY_AUTO_RESET); 766 } 767 } 768 } else { 769 ProcessControlFrameHeader(control_frame_type_field); 770 } 771 772 return original_len - len; 773} 774 775void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { 776 DCHECK_EQ(SPDY_NO_ERROR, error_code_); 777 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); 778 779 // Early detection of deprecated frames that we ignore. 780 if (protocol_version() <= SPDY3) { 781 if (control_frame_type_field == NOOP) { 782 current_frame_type_ = NOOP; 783 DVLOG(1) << "NOOP control frame found. Ignoring."; 784 CHANGE_STATE(SPDY_AUTO_RESET); 785 return; 786 } 787 788 if (control_frame_type_field == CREDENTIAL) { 789 current_frame_type_ = CREDENTIAL; 790 DCHECK_EQ(SPDY3, protocol_version()); 791 DVLOG(1) << "CREDENTIAL control frame found. Ignoring."; 792 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 793 return; 794 } 795 } 796 797 if (!SpdyConstants::IsValidFrameType(protocol_version(), 798 control_frame_type_field)) { 799 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field 800 << " (protocol version: " << protocol_version() << ")"; 801 set_error(SPDY_INVALID_CONTROL_FRAME); 802 return; 803 } 804 805 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(), 806 control_frame_type_field); 807 808 // Do some sanity checking on the control frame sizes and flags. 809 switch (current_frame_type_) { 810 case SYN_STREAM: 811 if (current_frame_length_ < GetSynStreamMinimumSize()) { 812 set_error(SPDY_INVALID_CONTROL_FRAME); 813 } else if (current_frame_flags_ & 814 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { 815 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 816 } 817 break; 818 case SYN_REPLY: 819 if (current_frame_length_ < GetSynReplyMinimumSize()) { 820 set_error(SPDY_INVALID_CONTROL_FRAME); 821 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { 822 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 823 } 824 break; 825 case RST_STREAM: 826 // For SPDY versions < 4, the header has a fixed length. 827 // For SPDY version 4 and up, the RST_STREAM frame may include optional 828 // opaque data, so we only have a lower limit on the frame size. 829 if ((current_frame_length_ != GetRstStreamMinimumSize() && 830 protocol_version() <= SPDY3) || 831 (current_frame_length_ < GetRstStreamMinimumSize() && 832 protocol_version() > SPDY3)) { 833 set_error(SPDY_INVALID_CONTROL_FRAME); 834 } else if (current_frame_flags_ != 0) { 835 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 836 } 837 break; 838 case SETTINGS: 839 { 840 // Make sure that we have an integral number of 8-byte key/value pairs, 841 // plus a 4-byte length field in SPDY3 and below. 842 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0); 843 // Size of each key/value pair in bytes. 844 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5); 845 if (current_frame_length_ < GetSettingsMinimumSize() || 846 (current_frame_length_ - GetControlFrameHeaderSize()) 847 % setting_size != values_prefix_size) { 848 DLOG(WARNING) << "Invalid length for SETTINGS frame: " 849 << current_frame_length_; 850 set_error(SPDY_INVALID_CONTROL_FRAME); 851 } else if (protocol_version() <= SPDY3 && 852 current_frame_flags_ & 853 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { 854 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 855 } else if (protocol_version() > SPDY3 && 856 current_frame_flags_ & ~SETTINGS_FLAG_ACK) { 857 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 858 } else if (protocol_version() > SPDY3 && 859 current_frame_flags_ & SETTINGS_FLAG_ACK && 860 current_frame_length_ > GetSettingsMinimumSize()) { 861 set_error(SPDY_INVALID_CONTROL_FRAME); 862 } 863 break; 864 } 865 case PING: 866 if (current_frame_length_ != GetPingSize()) { 867 set_error(SPDY_INVALID_CONTROL_FRAME); 868 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) || 869 (current_frame_flags_ & ~PING_FLAG_ACK)) { 870 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 871 } 872 break; 873 case GOAWAY: 874 { 875 // For SPDY version < 4, there are only mandatory fields and the header 876 // has a fixed length. For SPDY version >= 4, optional opaque data may 877 // be appended to the GOAWAY frame, thus there is only a minimal length 878 // restriction. 879 if ((current_frame_length_ != GetGoAwayMinimumSize() && 880 protocol_version() <= SPDY3) || 881 (current_frame_length_ < GetGoAwayMinimumSize() && 882 protocol_version() > SPDY3)) { 883 set_error(SPDY_INVALID_CONTROL_FRAME); 884 } else if (current_frame_flags_ != 0) { 885 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 886 } 887 break; 888 } 889 case HEADERS: 890 { 891 size_t min_size = GetHeadersMinimumSize(); 892 if (protocol_version() > SPDY3 && 893 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) { 894 min_size += 4; 895 } 896 if (current_frame_length_ < min_size) { 897 set_error(SPDY_INVALID_CONTROL_FRAME); 898 } else if (protocol_version() <= SPDY3 && 899 current_frame_flags_ & ~CONTROL_FLAG_FIN) { 900 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 901 } else if (protocol_version() > SPDY3 && current_frame_flags_ & 902 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | 903 HEADERS_FLAG_END_HEADERS)) { 904 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 905 } 906 } 907 break; 908 case WINDOW_UPDATE: 909 if (current_frame_length_ != GetWindowUpdateSize()) { 910 set_error(SPDY_INVALID_CONTROL_FRAME); 911 } else if (current_frame_flags_ != 0) { 912 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 913 } 914 break; 915 case BLOCKED: 916 if (current_frame_length_ != GetBlockedSize()) { 917 set_error(SPDY_INVALID_CONTROL_FRAME); 918 } else if (current_frame_flags_ != 0) { 919 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 920 } 921 break; 922 case PUSH_PROMISE: 923 if (current_frame_length_ < GetPushPromiseMinimumSize()) { 924 set_error(SPDY_INVALID_CONTROL_FRAME); 925 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { 926 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 927 } else if (protocol_version() > SPDY3 && current_frame_flags_ & 928 ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) { 929 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 930 } 931 break; 932 case CONTINUATION: 933 if (current_frame_length_ < GetContinuationMinimumSize() || 934 protocol_version() <= SPDY3) { 935 set_error(SPDY_INVALID_CONTROL_FRAME); 936 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) { 937 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 938 } 939 break; 940 default: 941 LOG(WARNING) << "Valid " << display_protocol_ 942 << " control frame with unhandled type: " 943 << current_frame_type_; 944 // This branch should be unreachable because of the frame type bounds 945 // check above. However, we DLOG(FATAL) here in an effort to painfully 946 // club the head of the developer who failed to keep this file in sync 947 // with spdy_protocol.h. 948 DLOG(FATAL); 949 set_error(SPDY_INVALID_CONTROL_FRAME); 950 break; 951 } 952 953 if (state_ == SPDY_ERROR) { 954 return; 955 } 956 957 if (current_frame_length_ > GetControlFrameBufferMaxSize()) { 958 DLOG(WARNING) << "Received control frame with way too big of a payload: " 959 << current_frame_length_; 960 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 961 return; 962 } 963 964 if (current_frame_type_ == GOAWAY) { 965 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD); 966 return; 967 } 968 969 if (current_frame_type_ == RST_STREAM) { 970 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD); 971 return; 972 } 973 974 // Determine the frame size without variable-length data. 975 int32 frame_size_without_variable_data; 976 switch (current_frame_type_) { 977 case SYN_STREAM: 978 syn_frame_processed_ = true; 979 frame_size_without_variable_data = GetSynStreamMinimumSize(); 980 break; 981 case SYN_REPLY: 982 syn_frame_processed_ = true; 983 frame_size_without_variable_data = GetSynReplyMinimumSize(); 984 break; 985 case SETTINGS: 986 frame_size_without_variable_data = GetSettingsMinimumSize(); 987 break; 988 case HEADERS: 989 frame_size_without_variable_data = GetHeadersMinimumSize(); 990 if (protocol_version() > SPDY3 && 991 current_frame_flags_ & HEADERS_FLAG_PRIORITY) { 992 frame_size_without_variable_data += 4; // priority 993 } 994 break; 995 case PUSH_PROMISE: 996 frame_size_without_variable_data = GetPushPromiseMinimumSize(); 997 break; 998 case CONTINUATION: 999 frame_size_without_variable_data = GetContinuationMinimumSize(); 1000 break; 1001 default: 1002 frame_size_without_variable_data = -1; 1003 break; 1004 } 1005 1006 if ((frame_size_without_variable_data == -1) && 1007 (current_frame_length_ > kControlFrameBufferSize)) { 1008 // We should already be in an error state. Double-check. 1009 DCHECK_EQ(SPDY_ERROR, state_); 1010 if (state_ != SPDY_ERROR) { 1011 LOG(DFATAL) << display_protocol_ 1012 << " control frame buffer too small for fixed-length frame."; 1013 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 1014 } 1015 return; 1016 } 1017 1018 if (frame_size_without_variable_data > 0) { 1019 // We have a control frame with a header block. We need to parse the 1020 // remainder of the control frame's header before we can parse the header 1021 // block. The start of the header block varies with the control type. 1022 DCHECK_GE(frame_size_without_variable_data, 1023 static_cast<int32>(current_frame_buffer_length_)); 1024 remaining_control_header_ = frame_size_without_variable_data - 1025 current_frame_buffer_length_; 1026 1027 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); 1028 return; 1029 } 1030 1031 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 1032} 1033 1034size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 1035 size_t max_bytes) { 1036 size_t bytes_to_read = std::min(*len, max_bytes); 1037 if (bytes_to_read > 0) { 1038 DCHECK_GE(kControlFrameBufferSize, 1039 current_frame_buffer_length_ + bytes_to_read); 1040 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, 1041 *data, 1042 bytes_to_read); 1043 current_frame_buffer_length_ += bytes_to_read; 1044 *data += bytes_to_read; 1045 *len -= bytes_to_read; 1046 } 1047 return bytes_to_read; 1048} 1049 1050size_t SpdyFramer::GetSerializedLength( 1051 const SpdyMajorVersion spdy_version, 1052 const SpdyHeaderBlock* headers) { 1053 const size_t num_name_value_pairs_size 1054 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32); 1055 const size_t length_of_name_size = num_name_value_pairs_size; 1056 const size_t length_of_value_size = num_name_value_pairs_size; 1057 1058 size_t total_length = num_name_value_pairs_size; 1059 for (SpdyHeaderBlock::const_iterator it = headers->begin(); 1060 it != headers->end(); 1061 ++it) { 1062 // We add space for the length of the name and the length of the value as 1063 // well as the length of the name and the length of the value. 1064 total_length += length_of_name_size + it->first.size() + 1065 length_of_value_size + it->second.size(); 1066 } 1067 return total_length; 1068} 1069 1070void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, 1071 const SpdyMajorVersion spdy_version, 1072 const SpdyHeaderBlock* headers) { 1073 if (spdy_version < SPDY3) { 1074 frame->WriteUInt16(headers->size()); // Number of headers. 1075 } else { 1076 frame->WriteUInt32(headers->size()); // Number of headers. 1077 } 1078 SpdyHeaderBlock::const_iterator it; 1079 for (it = headers->begin(); it != headers->end(); ++it) { 1080 if (spdy_version < SPDY3) { 1081 frame->WriteString(it->first); 1082 frame->WriteString(it->second); 1083 } else { 1084 frame->WriteStringPiece32(it->first); 1085 frame->WriteStringPiece32(it->second); 1086 } 1087 } 1088} 1089 1090// TODO(phajdan.jr): Clean up after we no longer need 1091// to workaround http://crbug.com/139744. 1092#if !defined(USE_SYSTEM_ZLIB) 1093 1094// These constants are used by zlib to differentiate between normal data and 1095// cookie data. Cookie data is handled specially by zlib when compressing. 1096enum ZDataClass { 1097 // kZStandardData is compressed normally, save that it will never match 1098 // against any other class of data in the window. 1099 kZStandardData = Z_CLASS_STANDARD, 1100 // kZCookieData is compressed in its own Huffman blocks and only matches in 1101 // its entirety and only against other kZCookieData blocks. Any matches must 1102 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching 1103 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent 1104 // prefix matches. 1105 kZCookieData = Z_CLASS_COOKIE, 1106 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed 1107 // against the window. 1108 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY, 1109}; 1110 1111// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as 1112// needed when switching between classes of data. 1113static void WriteZ(const base::StringPiece& data, 1114 ZDataClass clas, 1115 z_stream* out) { 1116 int rv; 1117 1118 // If we are switching from standard to non-standard data then we need to end 1119 // the current Huffman context to avoid it leaking between them. 1120 if (out->clas == kZStandardData && 1121 clas != kZStandardData) { 1122 out->avail_in = 0; 1123 rv = deflate(out, Z_PARTIAL_FLUSH); 1124 DCHECK_EQ(Z_OK, rv); 1125 DCHECK_EQ(0u, out->avail_in); 1126 DCHECK_LT(0u, out->avail_out); 1127 } 1128 1129 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data())); 1130 out->avail_in = data.size(); 1131 out->clas = clas; 1132 if (clas == kZStandardData) { 1133 rv = deflate(out, Z_NO_FLUSH); 1134 } else { 1135 rv = deflate(out, Z_PARTIAL_FLUSH); 1136 } 1137 if (!data.empty()) { 1138 // If we didn't provide any data then zlib will return Z_BUF_ERROR. 1139 DCHECK_EQ(Z_OK, rv); 1140 } 1141 DCHECK_EQ(0u, out->avail_in); 1142 DCHECK_LT(0u, out->avail_out); 1143} 1144 1145// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|. 1146static void WriteLengthZ(size_t n, 1147 unsigned length, 1148 ZDataClass clas, 1149 z_stream* out) { 1150 char buf[4]; 1151 DCHECK_LE(length, sizeof(buf)); 1152 for (unsigned i = 1; i <= length; i++) { 1153 buf[length - i] = n; 1154 n >>= 8; 1155 } 1156 WriteZ(base::StringPiece(buf, length), clas, out); 1157} 1158 1159// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a 1160// manner that resists the length of the compressed data from compromising 1161// cookie data. 1162void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, 1163 z_stream* z) const { 1164 unsigned length_length = 4; 1165 if (spdy_version_ < 3) 1166 length_length = 2; 1167 1168 WriteLengthZ(headers->size(), length_length, kZStandardData, z); 1169 1170 std::map<std::string, std::string>::const_iterator it; 1171 for (it = headers->begin(); it != headers->end(); ++it) { 1172 WriteLengthZ(it->first.size(), length_length, kZStandardData, z); 1173 WriteZ(it->first, kZStandardData, z); 1174 1175 if (it->first == "cookie") { 1176 // We require the cookie values (save for the last) to end with a 1177 // semicolon and (save for the first) to start with a space. This is 1178 // typically the format that we are given them in but we reserialize them 1179 // to be sure. 1180 1181 std::vector<base::StringPiece> cookie_values; 1182 size_t cookie_length = 0; 1183 base::StringPiece cookie_data(it->second); 1184 1185 for (;;) { 1186 while (!cookie_data.empty() && 1187 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) { 1188 cookie_data.remove_prefix(1); 1189 } 1190 if (cookie_data.empty()) 1191 break; 1192 1193 size_t i; 1194 for (i = 0; i < cookie_data.size(); i++) { 1195 if (cookie_data[i] == ';') 1196 break; 1197 } 1198 if (i < cookie_data.size()) { 1199 cookie_values.push_back(cookie_data.substr(0, i)); 1200 cookie_length += i + 2 /* semicolon and space */; 1201 cookie_data.remove_prefix(i + 1); 1202 } else { 1203 cookie_values.push_back(cookie_data); 1204 cookie_length += cookie_data.size(); 1205 cookie_data.remove_prefix(i); 1206 } 1207 } 1208 1209 WriteLengthZ(cookie_length, length_length, kZStandardData, z); 1210 for (size_t i = 0; i < cookie_values.size(); i++) { 1211 std::string cookie; 1212 // Since zlib will only back-reference complete cookies, a cookie that 1213 // is currently last (and so doesn't have a trailing semicolon) won't 1214 // match if it's later in a non-final position. The same is true of 1215 // the first cookie. 1216 if (i == 0 && cookie_values.size() == 1) { 1217 cookie = cookie_values[i].as_string(); 1218 } else if (i == 0) { 1219 cookie = cookie_values[i].as_string() + ";"; 1220 } else if (i < cookie_values.size() - 1) { 1221 cookie = " " + cookie_values[i].as_string() + ";"; 1222 } else { 1223 cookie = " " + cookie_values[i].as_string(); 1224 } 1225 WriteZ(cookie, kZCookieData, z); 1226 } 1227 } else if (it->first == "accept" || 1228 it->first == "accept-charset" || 1229 it->first == "accept-encoding" || 1230 it->first == "accept-language" || 1231 it->first == "host" || 1232 it->first == "version" || 1233 it->first == "method" || 1234 it->first == "scheme" || 1235 it->first == ":host" || 1236 it->first == ":version" || 1237 it->first == ":method" || 1238 it->first == ":scheme" || 1239 it->first == "user-agent") { 1240 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 1241 WriteZ(it->second, kZStandardData, z); 1242 } else { 1243 // Non-whitelisted headers are Huffman compressed in their own block, but 1244 // don't match against the window. 1245 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 1246 WriteZ(it->second, kZHuffmanOnlyData, z); 1247 } 1248 } 1249 1250 z->avail_in = 0; 1251 int rv = deflate(z, Z_SYNC_FLUSH); 1252 DCHECK_EQ(Z_OK, rv); 1253 z->clas = kZStandardData; 1254} 1255#endif // !defined(USE_SYSTEM_ZLIB) 1256 1257size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 1258 size_t len) { 1259 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 1260 const size_t original_len = len; 1261 1262 if (remaining_control_header_ > 0) { 1263 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 1264 remaining_control_header_); 1265 remaining_control_header_ -= bytes_read; 1266 remaining_data_length_ -= bytes_read; 1267 } 1268 1269 if (remaining_control_header_ == 0) { 1270 SpdyFrameReader reader(current_frame_buffer_.get(), 1271 current_frame_buffer_length_); 1272 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 1273 1274 switch (current_frame_type_) { 1275 case SYN_STREAM: 1276 { 1277 DCHECK_GE(SPDY3, protocol_version()); 1278 bool successful_read = true; 1279 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1280 DCHECK(successful_read); 1281 if (current_frame_stream_id_ == 0) { 1282 set_error(SPDY_INVALID_CONTROL_FRAME); 1283 break; 1284 } 1285 1286 SpdyStreamId associated_to_stream_id = kInvalidStream; 1287 successful_read = reader.ReadUInt31(&associated_to_stream_id); 1288 DCHECK(successful_read); 1289 1290 SpdyPriority priority = 0; 1291 successful_read = reader.ReadUInt8(&priority); 1292 DCHECK(successful_read); 1293 if (protocol_version() <= SPDY2) { 1294 priority = priority >> 6; 1295 } else { 1296 priority = priority >> 5; 1297 } 1298 1299 // Seek past unused byte; used to be credential slot in SPDY 3. 1300 reader.Seek(1); 1301 1302 DCHECK(reader.IsDoneReading()); 1303 if (debug_visitor_) { 1304 debug_visitor_->OnReceiveCompressedFrame( 1305 current_frame_stream_id_, 1306 current_frame_type_, 1307 current_frame_length_); 1308 } 1309 visitor_->OnSynStream( 1310 current_frame_stream_id_, 1311 associated_to_stream_id, 1312 priority, 1313 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 1314 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 1315 } 1316 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1317 break; 1318 case SETTINGS: 1319 if (protocol_version() > SPDY3 && 1320 current_frame_flags_ & SETTINGS_FLAG_ACK) { 1321 visitor_->OnSettingsAck(); 1322 CHANGE_STATE(SPDY_AUTO_RESET); 1323 } else { 1324 visitor_->OnSettings(current_frame_flags_ & 1325 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS); 1326 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); 1327 } 1328 break; 1329 case SYN_REPLY: 1330 case HEADERS: 1331 // SYN_REPLY and HEADERS are the same, save for the visitor call. 1332 { 1333 if (protocol_version() > SPDY3) { 1334 DCHECK_EQ(HEADERS, current_frame_type_); 1335 } 1336 bool successful_read = true; 1337 if (protocol_version() <= SPDY3) { 1338 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1339 DCHECK(successful_read); 1340 } 1341 if (current_frame_stream_id_ == 0) { 1342 set_error(SPDY_INVALID_CONTROL_FRAME); 1343 break; 1344 } 1345 if (protocol_version() <= SPDY2) { 1346 // SPDY 2 had two unused bytes here. Seek past them. 1347 reader.Seek(2); 1348 } 1349 if (protocol_version() > SPDY3 && 1350 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) && 1351 current_frame_type_ == HEADERS) { 1352 expect_continuation_ = current_frame_stream_id_; 1353 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; 1354 } 1355 const bool has_priority = 1356 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; 1357 uint32 priority = 0; 1358 if (protocol_version() > SPDY3 && has_priority) { 1359 successful_read = reader.ReadUInt31(&priority); 1360 DCHECK(successful_read); 1361 } 1362 DCHECK(reader.IsDoneReading()); 1363 if (debug_visitor_) { 1364 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM. 1365 SpdyFrameType reported_type = current_frame_type_; 1366 if (protocol_version() > SPDY3 && has_priority) { 1367 reported_type = SYN_STREAM; 1368 } 1369 debug_visitor_->OnReceiveCompressedFrame( 1370 current_frame_stream_id_, 1371 reported_type, 1372 current_frame_length_); 1373 } 1374 if (current_frame_type_ == SYN_REPLY) { 1375 visitor_->OnSynReply( 1376 current_frame_stream_id_, 1377 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 1378 } else if (protocol_version() > SPDY3 && 1379 current_frame_flags_ & HEADERS_FLAG_PRIORITY) { 1380 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes 1381 // can be made independent of wire changes. 1382 visitor_->OnSynStream( 1383 current_frame_stream_id_, 1384 0, // associated_to_stream_id 1385 priority, 1386 current_frame_flags_ & CONTROL_FLAG_FIN, 1387 false); // unidirectional 1388 } else { 1389 visitor_->OnHeaders( 1390 current_frame_stream_id_, 1391 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 1392 expect_continuation_ == 0); 1393 } 1394 } 1395 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1396 break; 1397 case PUSH_PROMISE: 1398 { 1399 DCHECK_LT(SPDY3, protocol_version()); 1400 if (current_frame_stream_id_ == 0) { 1401 set_error(SPDY_INVALID_CONTROL_FRAME); 1402 break; 1403 } 1404 SpdyStreamId promised_stream_id = kInvalidStream; 1405 bool successful_read = reader.ReadUInt31(&promised_stream_id); 1406 DCHECK(successful_read); 1407 DCHECK(reader.IsDoneReading()); 1408 if (promised_stream_id == 0) { 1409 set_error(SPDY_INVALID_CONTROL_FRAME); 1410 break; 1411 } 1412 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) { 1413 expect_continuation_ = current_frame_stream_id_; 1414 } 1415 if (debug_visitor_) { 1416 debug_visitor_->OnReceiveCompressedFrame( 1417 current_frame_stream_id_, 1418 current_frame_type_, 1419 current_frame_length_); 1420 } 1421 visitor_->OnPushPromise(current_frame_stream_id_, 1422 promised_stream_id, 1423 (current_frame_flags_ & 1424 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); 1425 } 1426 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1427 break; 1428 case CONTINUATION: 1429 { 1430 // Check to make sure the stream id of the current frame is 1431 // the same as that of the preceding frame. 1432 // If we're at this point we should already know that 1433 // expect_continuation_ != 0, so this doubles as a check 1434 // that current_frame_stream_id != 0. 1435 if (current_frame_stream_id_ != expect_continuation_) { 1436 set_error(SPDY_INVALID_CONTROL_FRAME); 1437 break; 1438 } 1439 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) { 1440 expect_continuation_ = 0; 1441 } 1442 if (debug_visitor_) { 1443 debug_visitor_->OnReceiveCompressedFrame( 1444 current_frame_stream_id_, 1445 current_frame_type_, 1446 current_frame_length_); 1447 } 1448 visitor_->OnContinuation(current_frame_stream_id_, 1449 (current_frame_flags_ & 1450 HEADERS_FLAG_END_HEADERS) != 0); 1451 } 1452 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1453 break; 1454 default: 1455 DCHECK(false); 1456 } 1457 } 1458 return original_len - len; 1459} 1460 1461// Does not buffer the control payload. Instead, either passes directly to the 1462// visitor or decompresses and then passes directly to the visitor, via 1463// IncrementallyDeliverControlFrameHeaderData() or 1464// IncrementallyDecompressControlFrameHeaderData() respectively. 1465size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 1466 size_t data_len, 1467 bool is_hpack_header_block) { 1468 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 1469 1470 bool processed_successfully = true; 1471 if (current_frame_type_ != SYN_STREAM && 1472 current_frame_type_ != SYN_REPLY && 1473 current_frame_type_ != HEADERS && 1474 current_frame_type_ != PUSH_PROMISE && 1475 current_frame_type_ != CONTINUATION) { 1476 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; 1477 } 1478 size_t process_bytes = std::min(data_len, remaining_data_length_); 1479 if (is_hpack_header_block) { 1480 if (!hpack_decoder_.HandleControlFrameHeadersData(current_frame_stream_id_, 1481 data, 1482 process_bytes)) { 1483 // TODO(jgraettinger): Finer-grained HPACK error codes. 1484 set_error(SPDY_DECOMPRESS_FAILURE); 1485 processed_successfully = false; 1486 } 1487 } else if (process_bytes > 0) { 1488 if (enable_compression_ && protocol_version() <= SPDY3) { 1489 processed_successfully = IncrementallyDecompressControlFrameHeaderData( 1490 current_frame_stream_id_, data, process_bytes); 1491 } else { 1492 processed_successfully = IncrementallyDeliverControlFrameHeaderData( 1493 current_frame_stream_id_, data, process_bytes); 1494 } 1495 } 1496 remaining_data_length_ -= process_bytes; 1497 1498 // Handle the case that there is no futher data in this frame. 1499 if (remaining_data_length_ == 0 && processed_successfully) { 1500 if (expect_continuation_ == 0) { 1501 if (is_hpack_header_block) { 1502 if (!hpack_decoder_.HandleControlFrameHeadersComplete( 1503 current_frame_stream_id_)) { 1504 set_error(SPDY_DECOMPRESS_FAILURE); 1505 processed_successfully = false; 1506 } else { 1507 // TODO(jgraettinger): To be removed with migration to 1508 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3 1509 // block, delivered via reentrant call to 1510 // ProcessControlFrameHeaderBlock(). 1511 DeliverHpackBlockAsSpdy3Block(); 1512 return process_bytes; 1513 } 1514 } else { 1515 // The complete header block has been delivered. We send a zero-length 1516 // OnControlFrameHeaderData() to indicate this. 1517 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); 1518 } 1519 // If this is a FIN, tell the caller. 1520 if ((current_frame_flags_ & CONTROL_FLAG_FIN) || end_stream_when_done_) { 1521 end_stream_when_done_ = false; 1522 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 1523 } 1524 } 1525 if (processed_successfully) 1526 CHANGE_STATE(SPDY_AUTO_RESET); 1527 } 1528 1529 // Handle error. 1530 if (!processed_successfully) { 1531 return data_len; 1532 } 1533 1534 // Return amount processed. 1535 return process_bytes; 1536} 1537 1538size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, 1539 size_t data_len) { 1540 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); 1541 DCHECK_EQ(SETTINGS, current_frame_type_); 1542 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); 1543 size_t processed_bytes = 0; 1544 1545 size_t setting_size = protocol_version() <= SPDY3 ? 8 : 5; 1546 1547 // Loop over our incoming data. 1548 while (unprocessed_bytes > 0) { 1549 // Process up to one setting at a time. 1550 size_t processing = std::min( 1551 unprocessed_bytes, 1552 static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len)); 1553 1554 // Check if we have a complete setting in our input. 1555 if (processing == setting_size) { 1556 // Parse the setting directly out of the input without buffering. 1557 if (!ProcessSetting(data + processed_bytes)) { 1558 set_error(SPDY_INVALID_CONTROL_FRAME); 1559 return processed_bytes; 1560 } 1561 } else { 1562 // Continue updating settings_scratch_.setting_buf. 1563 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len, 1564 data + processed_bytes, 1565 processing); 1566 settings_scratch_.setting_buf_len += processing; 1567 1568 // Check if we have a complete setting buffered. 1569 if (settings_scratch_.setting_buf_len == setting_size) { 1570 if (!ProcessSetting(settings_scratch_.setting_buf)) { 1571 set_error(SPDY_INVALID_CONTROL_FRAME); 1572 return processed_bytes; 1573 } 1574 // Reset settings_scratch_.setting_buf for our next setting. 1575 settings_scratch_.setting_buf_len = 0; 1576 } 1577 } 1578 1579 // Iterate. 1580 unprocessed_bytes -= processing; 1581 processed_bytes += processing; 1582 } 1583 1584 // Check if we're done handling this SETTINGS frame. 1585 remaining_data_length_ -= processed_bytes; 1586 if (remaining_data_length_ == 0) { 1587 visitor_->OnSettingsEnd(); 1588 CHANGE_STATE(SPDY_AUTO_RESET); 1589 } 1590 1591 return processed_bytes; 1592} 1593 1594void SpdyFramer::DeliverHpackBlockAsSpdy3Block() { 1595 DCHECK_LT(SPDY3, protocol_version()); 1596 DCHECK_EQ(0u, remaining_data_length_); 1597 1598 const SpdyNameValueBlock& block = hpack_decoder_.decoded_block(); 1599 if (block.empty()) { 1600 // Special-case this to make tests happy. 1601 ProcessControlFrameHeaderBlock(NULL, 0, false); 1602 return; 1603 } 1604 SpdyFrameBuilder builder( 1605 GetSerializedLength(protocol_version(), &block), 1606 SPDY3); 1607 1608 SerializeNameValueBlockWithoutCompression(&builder, block); 1609 scoped_ptr<SpdyFrame> frame(builder.take()); 1610 1611 remaining_data_length_ = frame->size(); 1612 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); 1613} 1614 1615bool SpdyFramer::ProcessSetting(const char* data) { 1616 int id_field; 1617 SpdySettingsIds id; 1618 uint8 flags = 0; 1619 uint32 value; 1620 1621 // Extract fields. 1622 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. 1623 if (protocol_version() <= SPDY3) { 1624 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data)); 1625 SettingsFlagsAndId id_and_flags = 1626 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire); 1627 id_field = id_and_flags.id(); 1628 flags = id_and_flags.flags(); 1629 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); 1630 } else { 1631 id_field = *(reinterpret_cast<const uint8*>(data)); 1632 value = ntohl(*(reinterpret_cast<const uint32*>(data + 1))); 1633 } 1634 1635 // Validate id. 1636 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) { 1637 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field; 1638 return false; 1639 } 1640 id = SpdyConstants::ParseSettingId(protocol_version(), id_field); 1641 1642 if (protocol_version() <= SPDY3) { 1643 // Detect duplicates. 1644 if (id <= settings_scratch_.last_setting_id) { 1645 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id 1646 << " in " << display_protocol_ << " SETTINGS frame " 1647 << "(last setting id was " 1648 << settings_scratch_.last_setting_id << ")."; 1649 return false; 1650 } 1651 settings_scratch_.last_setting_id = id; 1652 1653 // Validate flags. 1654 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED; 1655 if ((flags & ~(kFlagsMask)) != 0) { 1656 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": " 1657 << flags; 1658 return false; 1659 } 1660 } 1661 1662 // Validation succeeded. Pass on to visitor. 1663 visitor_->OnSetting(id, flags, value); 1664 return true; 1665} 1666 1667size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 1668 size_t original_len = len; 1669 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 1670 remaining_data_length_); 1671 remaining_data_length_ -= bytes_read; 1672 if (remaining_data_length_ == 0) { 1673 SpdyFrameReader reader(current_frame_buffer_.get(), 1674 current_frame_buffer_length_); 1675 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header. 1676 1677 // Use frame-specific handlers. 1678 switch (current_frame_type_) { 1679 case PING: { 1680 SpdyPingId id = 0; 1681 bool is_ack = protocol_version() > SPDY3 && 1682 (current_frame_flags_ & PING_FLAG_ACK); 1683 bool successful_read = true; 1684 if (protocol_version() <= SPDY3) { 1685 uint32 id32 = 0; 1686 successful_read = reader.ReadUInt32(&id32); 1687 id = id32; 1688 } else { 1689 successful_read = reader.ReadUInt64(&id); 1690 } 1691 DCHECK(successful_read); 1692 DCHECK(reader.IsDoneReading()); 1693 visitor_->OnPing(id, is_ack); 1694 } 1695 break; 1696 case WINDOW_UPDATE: { 1697 uint32 delta_window_size = 0; 1698 bool successful_read = true; 1699 if (protocol_version() <= SPDY3) { 1700 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1701 DCHECK(successful_read); 1702 } 1703 successful_read = reader.ReadUInt32(&delta_window_size); 1704 DCHECK(successful_read); 1705 DCHECK(reader.IsDoneReading()); 1706 visitor_->OnWindowUpdate(current_frame_stream_id_, 1707 delta_window_size); 1708 } 1709 break; 1710 case BLOCKED: { 1711 DCHECK_LT(SPDY3, protocol_version()); 1712 DCHECK(reader.IsDoneReading()); 1713 visitor_->OnBlocked(current_frame_stream_id_); 1714 } 1715 break; 1716 default: 1717 // Unreachable. 1718 LOG(FATAL) << "Unhandled control frame " << current_frame_type_; 1719 } 1720 1721 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 1722 } 1723 return original_len - len; 1724} 1725 1726size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) { 1727 if (len == 0) { 1728 return 0; 1729 } 1730 // Clamp to the actual remaining payload. 1731 if (len > remaining_data_length_) { 1732 len = remaining_data_length_; 1733 } 1734 size_t original_len = len; 1735 1736 // Check if we had already read enough bytes to parse the GOAWAY header. 1737 const size_t header_size = GetGoAwayMinimumSize(); 1738 size_t unread_header_bytes = header_size - current_frame_buffer_length_; 1739 bool already_parsed_header = (unread_header_bytes == 0); 1740 if (!already_parsed_header) { 1741 // Buffer the new GOAWAY header bytes we got. 1742 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes); 1743 1744 // Do we have enough to parse the constant size GOAWAY header? 1745 if (current_frame_buffer_length_ == header_size) { 1746 // Parse out the last good stream id. 1747 SpdyFrameReader reader(current_frame_buffer_.get(), 1748 current_frame_buffer_length_); 1749 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 1750 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1751 DCHECK(successful_read); 1752 1753 // In SPDYv3 and up, frames also specify a status code - parse it out. 1754 SpdyGoAwayStatus status = GOAWAY_OK; 1755 if (protocol_version() >= SPDY3) { 1756 uint32 status_raw = GOAWAY_OK; 1757 successful_read = reader.ReadUInt32(&status_raw); 1758 DCHECK(successful_read); 1759 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(), 1760 status_raw)) { 1761 status = SpdyConstants::ParseGoAwayStatus(protocol_version(), 1762 status_raw); 1763 } else { 1764 DCHECK(false); 1765 // Throw an error for SPDY4+, keep liberal behavior 1766 // for earlier versions. 1767 if (protocol_version() > SPDY3) { 1768 DLOG(WARNING) << "Invalid GO_AWAY status " << status_raw; 1769 set_error(SPDY_INVALID_CONTROL_FRAME); 1770 return 0; 1771 } 1772 } 1773 } 1774 // Finished parsing the GOAWAY header, call frame handler. 1775 visitor_->OnGoAway(current_frame_stream_id_, status); 1776 } 1777 } 1778 1779 // Handle remaining data as opaque. 1780 bool processed_successfully = true; 1781 if (len > 0) { 1782 processed_successfully = visitor_->OnGoAwayFrameData(data, len); 1783 } 1784 remaining_data_length_ -= original_len; 1785 if (!processed_successfully) { 1786 set_error(SPDY_GOAWAY_FRAME_CORRUPT); 1787 } else if (remaining_data_length_ == 0) { 1788 // Signal that there is not more opaque data. 1789 visitor_->OnGoAwayFrameData(NULL, 0); 1790 CHANGE_STATE(SPDY_AUTO_RESET); 1791 } 1792 return original_len; 1793} 1794 1795size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) { 1796 if (len == 0) { 1797 return 0; 1798 } 1799 // Clamp to the actual remaining payload. 1800 if (len > remaining_data_length_) { 1801 len = remaining_data_length_; 1802 } 1803 size_t original_len = len; 1804 1805 // Check if we had already read enough bytes to parse the fixed-length portion 1806 // of the RST_STREAM frame. 1807 const size_t header_size = GetRstStreamMinimumSize(); 1808 size_t unread_header_bytes = header_size - current_frame_buffer_length_; 1809 bool already_parsed_header = (unread_header_bytes == 0); 1810 if (!already_parsed_header) { 1811 // Buffer the new RST_STREAM header bytes we got. 1812 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes); 1813 1814 // Do we have enough to parse the constant size RST_STREAM header? 1815 if (current_frame_buffer_length_ == header_size) { 1816 // Parse out the last good stream id. 1817 SpdyFrameReader reader(current_frame_buffer_.get(), 1818 current_frame_buffer_length_); 1819 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 1820 if (protocol_version() <= SPDY3) { 1821 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1822 DCHECK(successful_read); 1823 } 1824 1825 SpdyRstStreamStatus status = RST_STREAM_INVALID; 1826 uint32 status_raw = status; 1827 bool successful_read = reader.ReadUInt32(&status_raw); 1828 DCHECK(successful_read); 1829 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(), 1830 status_raw)) { 1831 status = static_cast<SpdyRstStreamStatus>(status_raw); 1832 } else { 1833 // Throw an error for SPDY4+, keep liberal behavior 1834 // for earlier versions. 1835 if (protocol_version() > SPDY3) { 1836 DLOG(WARNING) << "Invalid RST_STREAM status " << status_raw; 1837 set_error(SPDY_INVALID_CONTROL_FRAME); 1838 return 0; 1839 } 1840 } 1841 // Finished parsing the RST_STREAM header, call frame handler. 1842 visitor_->OnRstStream(current_frame_stream_id_, status); 1843 } 1844 } 1845 1846 // Handle remaining data as opaque. 1847 bool processed_successfully = true; 1848 if (len > 0) { 1849 processed_successfully = visitor_->OnRstStreamFrameData(data, len); 1850 } 1851 remaining_data_length_ -= original_len; 1852 if (!processed_successfully) { 1853 set_error(SPDY_RST_STREAM_FRAME_CORRUPT); 1854 } else if (remaining_data_length_ == 0) { 1855 // Signal that there is not more opaque data. 1856 visitor_->OnRstStreamFrameData(NULL, 0); 1857 CHANGE_STATE(SPDY_AUTO_RESET); 1858 } 1859 return original_len; 1860} 1861 1862size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) { 1863 DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_); 1864 1865 size_t original_len = len; 1866 if (remaining_padding_length_fields_ == 0) { 1867 DCHECK_EQ(remaining_padding_payload_length_, 0u); 1868 bool pad_low = false; 1869 bool pad_high = false; 1870 if (current_frame_flags_ & DATA_FLAG_PAD_LOW) { 1871 pad_low = true; 1872 ++remaining_padding_length_fields_; 1873 } 1874 if (current_frame_flags_ & DATA_FLAG_PAD_HIGH) { 1875 pad_high = true; 1876 ++remaining_padding_length_fields_; 1877 } 1878 if ((pad_high && !pad_low) || 1879 remaining_data_length_ < remaining_padding_length_fields_) { 1880 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 1881 return 0; 1882 } 1883 } 1884 1885 // Parse the padding length. 1886 while (len != 0 && remaining_padding_length_fields_ != 0) { 1887 remaining_padding_payload_length_ = 1888 (remaining_padding_payload_length_ << 8) + 1889 *reinterpret_cast<const uint8*>(data); 1890 ++data; 1891 --len; 1892 --remaining_padding_length_fields_; 1893 --remaining_data_length_; 1894 } 1895 1896 if (remaining_padding_length_fields_ == 0) { 1897 if (remaining_padding_payload_length_ > remaining_data_length_) { 1898 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 1899 return 0; 1900 } 1901 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); 1902 } 1903 return original_len - len; 1904} 1905 1906size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { 1907 DCHECK_EQ(SPDY_CONSUME_PADDING, state_); 1908 1909 size_t original_len = len; 1910 if (remaining_padding_payload_length_ > 0) { 1911 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); 1912 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len); 1913 // The visitor needs to know about padding so it can send window updates. 1914 // Communicate the padding to the visitor through a NULL data pointer, with 1915 // a nonzero size. 1916 if (amount_to_discard) { 1917 visitor_->OnStreamFrameData( 1918 current_frame_stream_id_, NULL, amount_to_discard, false); 1919 } 1920 data += amount_to_discard; 1921 len -= amount_to_discard; 1922 remaining_padding_payload_length_ -= amount_to_discard; 1923 remaining_data_length_ -= amount_to_discard; 1924 } 1925 1926 if (remaining_data_length_ == 0) { 1927 // If the FIN flag is set, and there is no more data in this data frame, 1928 // inform the visitor of EOF via a 0-length data frame. 1929 if (current_frame_flags_ & DATA_FLAG_FIN) { 1930 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 1931 } 1932 1933 CHANGE_STATE(SPDY_AUTO_RESET); 1934 } 1935 return original_len - len; 1936} 1937 1938size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { 1939 size_t original_len = len; 1940 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) { 1941 size_t amount_to_forward = std::min( 1942 remaining_data_length_ - remaining_padding_payload_length_, len); 1943 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { 1944 // Only inform the visitor if there is data. 1945 if (amount_to_forward) { 1946 visitor_->OnStreamFrameData( 1947 current_frame_stream_id_, data, amount_to_forward, false); 1948 } 1949 } 1950 data += amount_to_forward; 1951 len -= amount_to_forward; 1952 remaining_data_length_ -= amount_to_forward; 1953 } 1954 1955 if (remaining_data_length_ == remaining_padding_payload_length_) { 1956 CHANGE_STATE(SPDY_CONSUME_PADDING); 1957 } 1958 return original_len - len; 1959} 1960 1961size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/ 1962 size_t len) { 1963 size_t original_len = len; 1964 if (remaining_data_length_ > 0) { 1965 size_t amount_to_ignore = std::min(remaining_data_length_, len); 1966 len -= amount_to_ignore; 1967 remaining_data_length_ -= amount_to_ignore; 1968 } 1969 1970 if (remaining_data_length_ == 0) { 1971 CHANGE_STATE(SPDY_AUTO_RESET); 1972 } 1973 return original_len - len; 1974} 1975 1976size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 1977 size_t header_length, 1978 SpdyHeaderBlock* block) const { 1979 SpdyFrameReader reader(header_data, header_length); 1980 1981 // Read number of headers. 1982 uint32 num_headers; 1983 if (protocol_version() <= SPDY2) { 1984 uint16 temp; 1985 if (!reader.ReadUInt16(&temp)) { 1986 DVLOG(1) << "Unable to read number of headers."; 1987 return 0; 1988 } 1989 num_headers = temp; 1990 } else { 1991 if (!reader.ReadUInt32(&num_headers)) { 1992 DVLOG(1) << "Unable to read number of headers."; 1993 return 0; 1994 } 1995 } 1996 1997 // Read each header. 1998 for (uint32 index = 0; index < num_headers; ++index) { 1999 base::StringPiece temp; 2000 2001 // Read header name. 2002 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp) 2003 : !reader.ReadStringPiece32(&temp)) { 2004 DVLOG(1) << "Unable to read header name (" << index + 1 << " of " 2005 << num_headers << ")."; 2006 return 0; 2007 } 2008 std::string name = temp.as_string(); 2009 2010 // Read header value. 2011 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp) 2012 : !reader.ReadStringPiece32(&temp)) { 2013 DVLOG(1) << "Unable to read header value (" << index + 1 << " of " 2014 << num_headers << ")."; 2015 return 0; 2016 } 2017 std::string value = temp.as_string(); 2018 2019 // Ensure no duplicates. 2020 if (block->find(name) != block->end()) { 2021 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of " 2022 << num_headers << ")."; 2023 return 0; 2024 } 2025 2026 // Store header. 2027 (*block)[name] = value; 2028 } 2029 return reader.GetBytesConsumed(); 2030} 2031 2032SpdySerializedFrame* SpdyFramer::SerializeData( 2033 const SpdyDataIR& data_ir) const { 2034 uint8 flags = DATA_FLAG_NONE; 2035 if (data_ir.fin()) { 2036 flags = DATA_FLAG_FIN; 2037 } 2038 2039 if (protocol_version() > SPDY3) { 2040 int num_padding_fields = 0; 2041 if (data_ir.pad_low()) { 2042 flags |= DATA_FLAG_PAD_LOW; 2043 ++num_padding_fields; 2044 } 2045 if (data_ir.pad_high()) { 2046 flags |= DATA_FLAG_PAD_HIGH; 2047 ++num_padding_fields; 2048 } 2049 2050 const size_t size_with_padding = num_padding_fields + 2051 data_ir.data().length() + data_ir.padding_payload_len() + 2052 GetDataFrameMinimumSize(); 2053 SpdyFrameBuilder builder(size_with_padding, protocol_version()); 2054 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); 2055 if (data_ir.pad_high()) { 2056 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); 2057 } 2058 if (data_ir.pad_low()) { 2059 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); 2060 } 2061 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); 2062 if (data_ir.padding_payload_len() > 0) { 2063 string padding = string(data_ir.padding_payload_len(), '0'); 2064 builder.WriteBytes(padding.data(), padding.length()); 2065 } 2066 DCHECK_EQ(size_with_padding, builder.length()); 2067 return builder.take(); 2068 } else { 2069 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); 2070 SpdyFrameBuilder builder(size, protocol_version()); 2071 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); 2072 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); 2073 DCHECK_EQ(size, builder.length()); 2074 return builder.take(); 2075 } 2076} 2077 2078SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( 2079 const SpdyDataIR& data_ir) const { 2080 uint8 flags = DATA_FLAG_NONE; 2081 if (data_ir.fin()) { 2082 flags = DATA_FLAG_FIN; 2083 } 2084 2085 size_t frame_size = GetDataFrameMinimumSize(); 2086 size_t num_padding_fields = 0; 2087 if (protocol_version() > SPDY3) { 2088 if (data_ir.pad_low()) { 2089 flags |= DATA_FLAG_PAD_LOW; 2090 ++num_padding_fields; 2091 } 2092 if (data_ir.pad_high()) { 2093 flags |= DATA_FLAG_PAD_HIGH; 2094 ++num_padding_fields; 2095 } 2096 frame_size += num_padding_fields; 2097 } 2098 2099 SpdyFrameBuilder builder(frame_size, protocol_version()); 2100 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); 2101 if (protocol_version() > SPDY3) { 2102 if (data_ir.pad_high()) { 2103 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); 2104 } 2105 if (data_ir.pad_low()) { 2106 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); 2107 } 2108 builder.OverwriteLength(*this, num_padding_fields + 2109 data_ir.data().length() + data_ir.padding_payload_len()); 2110 } else { 2111 builder.OverwriteLength(*this, data_ir.data().length()); 2112 } 2113 DCHECK_EQ(frame_size, builder.length()); 2114 return builder.take(); 2115} 2116 2117SpdySerializedFrame* SpdyFramer::SerializeSynStream( 2118 const SpdySynStreamIR& syn_stream) { 2119 uint8 flags = 0; 2120 if (syn_stream.fin()) { 2121 flags |= CONTROL_FLAG_FIN; 2122 } 2123 if (syn_stream.unidirectional()) { 2124 // TODO(hkhalil): invalid for HTTP2. 2125 flags |= CONTROL_FLAG_UNIDIRECTIONAL; 2126 } 2127 // In SPDY >= 4, SYN_STREAM frames are HEADERS frames, but for now 2128 // we never expect to have to overflow into a CONTINUATION frame. 2129 if (protocol_version() > SPDY3) { 2130 flags |= HEADERS_FLAG_PRIORITY; 2131 flags |= HEADERS_FLAG_END_HEADERS; 2132 } 2133 2134 // Sanitize priority. 2135 uint8 priority = syn_stream.priority(); 2136 if (priority > GetLowestPriority()) { 2137 DLOG(DFATAL) << "Priority out-of-bounds."; 2138 priority = GetLowestPriority(); 2139 } 2140 2141 // The size of this frame, including variable-length name-value block. 2142 size_t size = GetSynStreamMinimumSize(); 2143 2144 string hpack_encoding; 2145 if (protocol_version() > SPDY3) { 2146 if (enable_compression_) { 2147 hpack_encoder_.EncodeHeaderSet( 2148 syn_stream.name_value_block(), &hpack_encoding); 2149 } else { 2150 hpack_encoder_.EncodeHeaderSetWithoutCompression( 2151 syn_stream.name_value_block(), &hpack_encoding); 2152 } 2153 size += hpack_encoding.size(); 2154 } else { 2155 size += GetSerializedLength(syn_stream.name_value_block()); 2156 } 2157 2158 SpdyFrameBuilder builder(size, protocol_version()); 2159 if (protocol_version() <= SPDY3) { 2160 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); 2161 builder.WriteUInt32(syn_stream.stream_id()); 2162 builder.WriteUInt32(syn_stream.associated_to_stream_id()); 2163 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); 2164 builder.WriteUInt8(0); // Unused byte where credential slot used to be. 2165 } else { 2166 builder.BeginNewFrame(*this, 2167 HEADERS, 2168 flags, 2169 syn_stream.stream_id()); 2170 builder.WriteUInt32(priority); 2171 } 2172 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); 2173 if (protocol_version() > SPDY3) { 2174 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); 2175 } else { 2176 SerializeNameValueBlock(&builder, syn_stream); 2177 } 2178 2179 if (debug_visitor_) { 2180 const size_t payload_len = protocol_version() > SPDY3 ? 2181 hpack_encoding.size() : 2182 GetSerializedLength(protocol_version(), 2183 &(syn_stream.name_value_block())); 2184 // SPDY 4 reports this compression as a SYN_STREAM compression. 2185 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), 2186 SYN_STREAM, 2187 payload_len, 2188 builder.length()); 2189 } 2190 2191 return builder.take(); 2192} 2193 2194SpdySerializedFrame* SpdyFramer::SerializeSynReply( 2195 const SpdySynReplyIR& syn_reply) { 2196 uint8 flags = 0; 2197 if (syn_reply.fin()) { 2198 flags |= CONTROL_FLAG_FIN; 2199 } 2200 // In SPDY >= 4, SYN_REPLY frames are HEADERS frames, but for now 2201 // we never expect to have to overflow into a CONTINUATION frame. 2202 if (protocol_version() > SPDY3) { 2203 flags |= HEADERS_FLAG_END_HEADERS; 2204 } 2205 2206 // The size of this frame, including variable-length name-value block. 2207 size_t size = GetSynReplyMinimumSize(); 2208 2209 string hpack_encoding; 2210 if (protocol_version() > SPDY3) { 2211 if (enable_compression_) { 2212 hpack_encoder_.EncodeHeaderSet( 2213 syn_reply.name_value_block(), &hpack_encoding); 2214 } else { 2215 hpack_encoder_.EncodeHeaderSetWithoutCompression( 2216 syn_reply.name_value_block(), &hpack_encoding); 2217 } 2218 size += hpack_encoding.size(); 2219 } else { 2220 size += GetSerializedLength(syn_reply.name_value_block()); 2221 } 2222 2223 SpdyFrameBuilder builder(size, protocol_version()); 2224 if (protocol_version() <= SPDY3) { 2225 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); 2226 builder.WriteUInt32(syn_reply.stream_id()); 2227 } else { 2228 builder.BeginNewFrame(*this, 2229 HEADERS, 2230 flags, 2231 syn_reply.stream_id()); 2232 } 2233 if (protocol_version() < SPDY3) { 2234 builder.WriteUInt16(0); // Unused. 2235 } 2236 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); 2237 if (protocol_version() > SPDY3) { 2238 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); 2239 } else { 2240 SerializeNameValueBlock(&builder, syn_reply); 2241 } 2242 2243 if (debug_visitor_) { 2244 const size_t payload_len = protocol_version() > SPDY3 ? 2245 hpack_encoding.size() : 2246 GetSerializedLength(protocol_version(), 2247 &(syn_reply.name_value_block())); 2248 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(), 2249 SYN_REPLY, 2250 payload_len, 2251 builder.length()); 2252 } 2253 2254 return builder.take(); 2255} 2256 2257SpdySerializedFrame* SpdyFramer::SerializeRstStream( 2258 const SpdyRstStreamIR& rst_stream) const { 2259 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM 2260 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, 2261 // which doesn't currently include RST_STREAM payloads. GFE flags have been 2262 // commented but left in place to simplify future patching. 2263 // Compute the output buffer size, taking opaque data into account. 2264 uint16 expected_length = GetRstStreamMinimumSize(); 2265 if (protocol_version() > SPDY3) { 2266 expected_length += rst_stream.description().size(); 2267 } 2268 SpdyFrameBuilder builder(expected_length, protocol_version()); 2269 2270 // Serialize the RST_STREAM frame. 2271 if (protocol_version() <= SPDY3) { 2272 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); 2273 builder.WriteUInt32(rst_stream.stream_id()); 2274 } else { 2275 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); 2276 } 2277 2278 builder.WriteUInt32(rst_stream.status()); 2279 2280 // In SPDY4 and up, RST_STREAM frames may also specify opaque data. 2281 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) { 2282 builder.WriteBytes(rst_stream.description().data(), 2283 rst_stream.description().size()); 2284 } 2285 2286 DCHECK_EQ(expected_length, builder.length()); 2287 return builder.take(); 2288} 2289 2290SpdySerializedFrame* SpdyFramer::SerializeSettings( 2291 const SpdySettingsIR& settings) const { 2292 uint8 flags = 0; 2293 2294 if (protocol_version() <= SPDY3) { 2295 if (settings.clear_settings()) { 2296 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 2297 } 2298 } else { 2299 if (settings.is_ack()) { 2300 flags |= SETTINGS_FLAG_ACK; 2301 } 2302 } 2303 const SpdySettingsIR::ValueMap* values = &(settings.values()); 2304 2305 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5); 2306 // Size, in bytes, of this SETTINGS frame. 2307 const size_t size = GetSettingsMinimumSize() + 2308 (values->size() * setting_size); 2309 SpdyFrameBuilder builder(size, protocol_version()); 2310 if (protocol_version() <= SPDY3) { 2311 builder.WriteControlFrameHeader(*this, SETTINGS, flags); 2312 } else { 2313 builder.BeginNewFrame(*this, SETTINGS, flags, 0); 2314 } 2315 2316 // If this is an ACK, payload should be empty. 2317 if (protocol_version() > SPDY3 && settings.is_ack()) { 2318 return builder.take(); 2319 } 2320 2321 if (protocol_version() <= SPDY3) { 2322 builder.WriteUInt32(values->size()); 2323 } 2324 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); 2325 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); 2326 it != values->end(); 2327 ++it) { 2328 if (protocol_version() <= SPDY3) { 2329 uint8 setting_flags = 0; 2330 if (it->second.persist_value) { 2331 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; 2332 } 2333 if (it->second.persisted) { 2334 setting_flags |= SETTINGS_FLAG_PERSISTED; 2335 } 2336 SettingsFlagsAndId flags_and_id( 2337 setting_flags, 2338 SpdyConstants::SerializeSettingId(protocol_version(), it->first)); 2339 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); 2340 builder.WriteBytes(&id_and_flags_wire, 4); 2341 } else { 2342 builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(), 2343 it->first)); 2344 } 2345 builder.WriteUInt32(it->second.value); 2346 } 2347 DCHECK_EQ(size, builder.length()); 2348 return builder.take(); 2349} 2350 2351SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { 2352 SpdyFrameBuilder builder(GetPingSize(), protocol_version()); 2353 if (protocol_version() <= SPDY3) { 2354 builder.WriteControlFrameHeader(*this, PING, kNoFlags); 2355 builder.WriteUInt32(static_cast<uint32>(ping.id())); 2356 } else { 2357 uint8 flags = 0; 2358 if (ping.is_ack()) { 2359 flags |= PING_FLAG_ACK; 2360 } 2361 builder.BeginNewFrame(*this, PING, flags, 0); 2362 builder.WriteUInt64(ping.id()); 2363 } 2364 DCHECK_EQ(GetPingSize(), builder.length()); 2365 return builder.take(); 2366} 2367 2368SpdySerializedFrame* SpdyFramer::SerializeGoAway( 2369 const SpdyGoAwayIR& goaway) const { 2370 2371 // Compute the output buffer size, take opaque data into account. 2372 uint16 expected_length = GetGoAwayMinimumSize(); 2373 if (protocol_version() > SPDY3) { 2374 expected_length += goaway.description().size(); 2375 } 2376 SpdyFrameBuilder builder(expected_length, protocol_version()); 2377 2378 // Serialize the GOAWAY frame. 2379 if (protocol_version() <= SPDY3) { 2380 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); 2381 } else { 2382 builder.BeginNewFrame(*this, GOAWAY, 0, 0); 2383 } 2384 2385 // GOAWAY frames specify the last good stream id for all SPDY versions. 2386 builder.WriteUInt32(goaway.last_good_stream_id()); 2387 2388 // In SPDY3 and up, GOAWAY frames also specify the error status code. 2389 if (protocol_version() >= SPDY3) { 2390 builder.WriteUInt32(goaway.status()); 2391 } 2392 2393 // In SPDY4 and up, GOAWAY frames may also specify opaque data. 2394 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) { 2395 builder.WriteBytes(goaway.description().data(), 2396 goaway.description().size()); 2397 } 2398 2399 DCHECK_EQ(expected_length, builder.length()); 2400 return builder.take(); 2401} 2402 2403SpdySerializedFrame* SpdyFramer::SerializeHeaders( 2404 const SpdyHeadersIR& headers) { 2405 uint8 flags = 0; 2406 if (headers.fin()) { 2407 flags |= CONTROL_FLAG_FIN; 2408 } 2409 if (protocol_version() > SPDY3) { 2410 // TODO(mlavan): If we overflow into a CONTINUATION frame, this will 2411 // get overwritten below, so we should probably just get rid of the 2412 // end_headers field. 2413 if (headers.end_headers()) { 2414 flags |= HEADERS_FLAG_END_HEADERS; 2415 } 2416 if (headers.has_priority()) { 2417 flags |= HEADERS_FLAG_PRIORITY; 2418 } 2419 } 2420 2421 // The size of this frame, including variable-length name-value block. 2422 size_t size = GetHeadersMinimumSize(); 2423 2424 uint32 priority = headers.priority(); 2425 if (headers.has_priority()) { 2426 if (priority > GetLowestPriority()) { 2427 DLOG(DFATAL) << "Priority out-of-bounds."; 2428 priority = GetLowestPriority(); 2429 } 2430 size += 4; 2431 } 2432 2433 string hpack_encoding; 2434 if (protocol_version() > SPDY3) { 2435 if (enable_compression_) { 2436 hpack_encoder_.EncodeHeaderSet( 2437 headers.name_value_block(), &hpack_encoding); 2438 } else { 2439 hpack_encoder_.EncodeHeaderSetWithoutCompression( 2440 headers.name_value_block(), &hpack_encoding); 2441 } 2442 size += hpack_encoding.size(); 2443 if (size > GetControlFrameBufferMaxSize()) { 2444 size += GetNumberRequiredContinuationFrames(size) * 2445 GetContinuationMinimumSize(); 2446 flags &= ~HEADERS_FLAG_END_HEADERS; 2447 } 2448 } else { 2449 size += GetSerializedLength(headers.name_value_block()); 2450 } 2451 2452 SpdyFrameBuilder builder(size, protocol_version()); 2453 if (protocol_version() <= SPDY3) { 2454 builder.WriteControlFrameHeader(*this, HEADERS, flags); 2455 builder.WriteUInt32(headers.stream_id()); 2456 } else { 2457 builder.BeginNewFrame(*this, 2458 HEADERS, 2459 flags, 2460 headers.stream_id()); 2461 if (headers.has_priority()) { 2462 builder.WriteUInt32(priority); 2463 } 2464 } 2465 if (protocol_version() <= SPDY2) { 2466 builder.WriteUInt16(0); // Unused. 2467 } 2468 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); 2469 2470 if (protocol_version() > SPDY3) { 2471 WritePayloadWithContinuation(&builder, 2472 hpack_encoding, 2473 headers.stream_id(), 2474 HEADERS); 2475 } else { 2476 SerializeNameValueBlock(&builder, headers); 2477 } 2478 2479 if (debug_visitor_) { 2480 const size_t payload_len = protocol_version() > SPDY3 ? 2481 hpack_encoding.size() : 2482 GetSerializedLength(protocol_version(), 2483 &(headers.name_value_block())); 2484 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), 2485 HEADERS, 2486 payload_len, 2487 builder.length()); 2488 } 2489 2490 return builder.take(); 2491} 2492 2493SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( 2494 const SpdyWindowUpdateIR& window_update) const { 2495 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version()); 2496 if (protocol_version() <= SPDY3) { 2497 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); 2498 builder.WriteUInt32(window_update.stream_id()); 2499 } else { 2500 builder.BeginNewFrame(*this, 2501 WINDOW_UPDATE, 2502 kNoFlags, 2503 window_update.stream_id()); 2504 } 2505 builder.WriteUInt32(window_update.delta()); 2506 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); 2507 return builder.take(); 2508} 2509 2510SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { 2511 DCHECK_LT(SPDY3, protocol_version()); 2512 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version()); 2513 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); 2514 return builder.take(); 2515} 2516 2517SpdyFrame* SpdyFramer::SerializePushPromise( 2518 const SpdyPushPromiseIR& push_promise) { 2519 DCHECK_LT(SPDY3, protocol_version()); 2520 uint8 flags = 0; 2521 // TODO(mlavan): If we overflow into a CONTINUATION frame, this will 2522 // get overwritten below, so we should probably just get rid of the 2523 // end_push_promise field. 2524 if (push_promise.end_push_promise()) { 2525 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; 2526 } 2527 // The size of this frame, including variable-length name-value block. 2528 size_t size = GetPushPromiseMinimumSize(); 2529 2530 string hpack_encoding; 2531 if (protocol_version() > SPDY3) { 2532 if (enable_compression_) { 2533 hpack_encoder_.EncodeHeaderSet( 2534 push_promise.name_value_block(), &hpack_encoding); 2535 } else { 2536 hpack_encoder_.EncodeHeaderSetWithoutCompression( 2537 push_promise.name_value_block(), &hpack_encoding); 2538 } 2539 size += hpack_encoding.size(); 2540 if (size > GetControlFrameBufferMaxSize()) { 2541 size += GetNumberRequiredContinuationFrames(size) * 2542 GetContinuationMinimumSize(); 2543 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; 2544 } 2545 } else { 2546 size += GetSerializedLength(push_promise.name_value_block()); 2547 } 2548 2549 SpdyFrameBuilder builder(size, protocol_version()); 2550 builder.BeginNewFrame(*this, 2551 PUSH_PROMISE, 2552 flags, 2553 push_promise.stream_id()); 2554 builder.WriteUInt32(push_promise.promised_stream_id()); 2555 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); 2556 2557 if (protocol_version() > SPDY3) { 2558 WritePayloadWithContinuation(&builder, 2559 hpack_encoding, 2560 push_promise.stream_id(), 2561 PUSH_PROMISE); 2562 } else { 2563 SerializeNameValueBlock(&builder, push_promise); 2564 } 2565 2566 if (debug_visitor_) { 2567 const size_t payload_len = protocol_version() > SPDY3 ? 2568 hpack_encoding.size() : 2569 GetSerializedLength(protocol_version(), 2570 &(push_promise.name_value_block())); 2571 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), 2572 PUSH_PROMISE, payload_len, builder.length()); 2573 } 2574 2575 return builder.take(); 2576} 2577 2578// TODO(jgraettinger): This implementation is incorrect. The continuation 2579// frame continues a previously-begun HPACK encoding; it doesn't begin a 2580// new one. Figure out whether it makes sense to keep SerializeContinuation(). 2581SpdyFrame* SpdyFramer::SerializeContinuation( 2582 const SpdyContinuationIR& continuation) { 2583 CHECK_LT(SPDY3, protocol_version()); 2584 uint8 flags = 0; 2585 if (continuation.end_headers()) { 2586 flags |= HEADERS_FLAG_END_HEADERS; 2587 } 2588 2589 // The size of this frame, including variable-length name-value block. 2590 size_t size = GetContinuationMinimumSize(); 2591 string hpack_encoding; 2592 if (enable_compression_) { 2593 hpack_encoder_.EncodeHeaderSet( 2594 continuation.name_value_block(), &hpack_encoding); 2595 } else { 2596 hpack_encoder_.EncodeHeaderSetWithoutCompression( 2597 continuation.name_value_block(), &hpack_encoding); 2598 } 2599 size += hpack_encoding.size(); 2600 2601 SpdyFrameBuilder builder(size, protocol_version()); 2602 builder.BeginNewFrame(*this, CONTINUATION, flags, 2603 continuation.stream_id()); 2604 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); 2605 2606 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); 2607 2608 if (debug_visitor_) { 2609 const size_t payload_len = hpack_encoding.size(); 2610 debug_visitor_->OnSendCompressedFrame(continuation.stream_id(), 2611 CONTINUATION, payload_len, builder.length()); 2612 } 2613 2614 return builder.take(); 2615} 2616 2617namespace { 2618 2619class FrameSerializationVisitor : public SpdyFrameVisitor { 2620 public: 2621 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {} 2622 virtual ~FrameSerializationVisitor() {} 2623 2624 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); } 2625 2626 virtual void VisitData(const SpdyDataIR& data) OVERRIDE { 2627 frame_.reset(framer_->SerializeData(data)); 2628 } 2629 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE { 2630 frame_.reset(framer_->SerializeSynStream(syn_stream)); 2631 } 2632 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE { 2633 frame_.reset(framer_->SerializeSynReply(syn_reply)); 2634 } 2635 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE { 2636 frame_.reset(framer_->SerializeRstStream(rst_stream)); 2637 } 2638 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE { 2639 frame_.reset(framer_->SerializeSettings(settings)); 2640 } 2641 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE { 2642 frame_.reset(framer_->SerializePing(ping)); 2643 } 2644 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE { 2645 frame_.reset(framer_->SerializeGoAway(goaway)); 2646 } 2647 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE { 2648 frame_.reset(framer_->SerializeHeaders(headers)); 2649 } 2650 virtual void VisitWindowUpdate( 2651 const SpdyWindowUpdateIR& window_update) OVERRIDE { 2652 frame_.reset(framer_->SerializeWindowUpdate(window_update)); 2653 } 2654 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE { 2655 frame_.reset(framer_->SerializeBlocked(blocked)); 2656 } 2657 virtual void VisitPushPromise( 2658 const SpdyPushPromiseIR& push_promise) OVERRIDE { 2659 frame_.reset(framer_->SerializePushPromise(push_promise)); 2660 } 2661 virtual void VisitContinuation( 2662 const SpdyContinuationIR& continuation) OVERRIDE { 2663 frame_.reset(framer_->SerializeContinuation(continuation)); 2664 } 2665 2666 private: 2667 SpdyFramer* framer_; 2668 scoped_ptr<SpdySerializedFrame> frame_; 2669}; 2670 2671} // namespace 2672 2673SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) { 2674 FrameSerializationVisitor visitor(this); 2675 frame.Visit(&visitor); 2676 return visitor.ReleaseSerializedFrame(); 2677} 2678 2679size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { 2680 CHECK_GE(SPDY3, protocol_version()); 2681 const size_t uncompressed_length = 2682 GetSerializedLength(protocol_version(), &headers); 2683 if (!enable_compression_) { 2684 return uncompressed_length; 2685 } 2686 z_stream* compressor = GetHeaderCompressor(); 2687 // Since we'll be performing lots of flushes when compressing the data, 2688 // zlib's lower bounds may be insufficient. 2689 return 2 * deflateBound(compressor, uncompressed_length); 2690} 2691 2692size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { 2693 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize(); 2694 DCHECK_GT(protocol_version(), SPDY3); 2695 DCHECK_GT(size, kMaxControlFrameSize); 2696 size_t overflow = size - kMaxControlFrameSize; 2697 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; 2698} 2699 2700void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, 2701 const string& hpack_encoding, 2702 SpdyStreamId stream_id, 2703 SpdyFrameType type) { 2704 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize(); 2705 2706 // In addition to the prefix, fixed_field_size includes the size of 2707 // any fields that come before the variable-length name/value block. 2708 size_t fixed_field_size = 0; 2709 uint8 end_flag = 0; 2710 uint8 flags = 0; 2711 if (type == HEADERS) { 2712 fixed_field_size = GetHeadersMinimumSize(); 2713 end_flag = HEADERS_FLAG_END_HEADERS; 2714 } else if (type == PUSH_PROMISE) { 2715 fixed_field_size = GetPushPromiseMinimumSize(); 2716 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; 2717 } else { 2718 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " 2719 << FrameTypeToString(type); 2720 } 2721 2722 // Write as much of the payload as possible into the initial frame. 2723 size_t bytes_remaining = hpack_encoding.size() - 2724 std::min(hpack_encoding.size(), 2725 kMaxControlFrameSize - fixed_field_size); 2726 builder->WriteBytes(&hpack_encoding[0], 2727 hpack_encoding.size() - bytes_remaining); 2728 2729 if (bytes_remaining > 0) { 2730 builder->OverwriteLength(*this, 2731 kMaxControlFrameSize - GetControlFrameHeaderSize()); 2732 } 2733 2734 // Tack on CONTINUATION frames for the overflow. 2735 while (bytes_remaining > 0) { 2736 size_t bytes_to_write = std::min(bytes_remaining, 2737 kMaxControlFrameSize - 2738 GetContinuationMinimumSize()); 2739 // Write CONTINUATION frame prefix. 2740 if (bytes_remaining == bytes_to_write) { 2741 flags |= end_flag; 2742 } 2743 builder->BeginNewFrame(*this, 2744 CONTINUATION, 2745 flags, 2746 stream_id); 2747 // Write payload fragment. 2748 builder->WriteBytes(&hpack_encoding[hpack_encoding.size() - 2749 bytes_remaining], 2750 bytes_to_write); 2751 bytes_remaining -= bytes_to_write; 2752 } 2753} 2754 2755// The following compression setting are based on Brian Olson's analysis. See 2756// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792 2757// for more details. 2758#if defined(USE_SYSTEM_ZLIB) 2759// System zlib is not expected to have workaround for http://crbug.com/139744, 2760// so disable compression in that case. 2761// TODO(phajdan.jr): Remove the special case when it's no longer necessary. 2762static const int kCompressorLevel = 0; 2763#else // !defined(USE_SYSTEM_ZLIB) 2764static const int kCompressorLevel = 9; 2765#endif // !defined(USE_SYSTEM_ZLIB) 2766static const int kCompressorWindowSizeInBits = 11; 2767static const int kCompressorMemLevel = 1; 2768 2769z_stream* SpdyFramer::GetHeaderCompressor() { 2770 if (header_compressor_.get()) 2771 return header_compressor_.get(); // Already initialized. 2772 2773 header_compressor_.reset(new z_stream); 2774 memset(header_compressor_.get(), 0, sizeof(z_stream)); 2775 2776 int success = deflateInit2(header_compressor_.get(), 2777 kCompressorLevel, 2778 Z_DEFLATED, 2779 kCompressorWindowSizeInBits, 2780 kCompressorMemLevel, 2781 Z_DEFAULT_STRATEGY); 2782 if (success == Z_OK) { 2783 const char* dictionary = (protocol_version() <= SPDY2) ? 2784 kV2Dictionary : kV3Dictionary; 2785 const int dictionary_size = (protocol_version() <= SPDY2) ? 2786 kV2DictionarySize : kV3DictionarySize; 2787 success = deflateSetDictionary(header_compressor_.get(), 2788 reinterpret_cast<const Bytef*>(dictionary), 2789 dictionary_size); 2790 } 2791 if (success != Z_OK) { 2792 LOG(WARNING) << "deflateSetDictionary failure: " << success; 2793 header_compressor_.reset(NULL); 2794 return NULL; 2795 } 2796 return header_compressor_.get(); 2797} 2798 2799z_stream* SpdyFramer::GetHeaderDecompressor() { 2800 if (header_decompressor_.get()) 2801 return header_decompressor_.get(); // Already initialized. 2802 2803 header_decompressor_.reset(new z_stream); 2804 memset(header_decompressor_.get(), 0, sizeof(z_stream)); 2805 2806 int success = inflateInit(header_decompressor_.get()); 2807 if (success != Z_OK) { 2808 LOG(WARNING) << "inflateInit failure: " << success; 2809 header_decompressor_.reset(NULL); 2810 return NULL; 2811 } 2812 return header_decompressor_.get(); 2813} 2814 2815// Incrementally decompress the control frame's header block, feeding the 2816// result to the visitor in chunks. Continue this until the visitor 2817// indicates that it cannot process any more data, or (more commonly) we 2818// run out of data to deliver. 2819bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 2820 SpdyStreamId stream_id, 2821 const char* data, 2822 size_t len) { 2823 // Get a decompressor or set error. 2824 z_stream* decomp = GetHeaderDecompressor(); 2825 if (decomp == NULL) { 2826 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 2827 set_error(SPDY_DECOMPRESS_FAILURE); 2828 return false; 2829 } 2830 2831 bool processed_successfully = true; 2832 char buffer[kHeaderDataChunkMaxSize]; 2833 2834 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 2835 decomp->avail_in = len; 2836 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we 2837 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've 2838 // reached this method successfully, stream_id should be nonzero. 2839 DCHECK_LT(0u, stream_id); 2840 while (decomp->avail_in > 0 && processed_successfully) { 2841 decomp->next_out = reinterpret_cast<Bytef*>(buffer); 2842 decomp->avail_out = arraysize(buffer); 2843 2844 int rv = inflate(decomp, Z_SYNC_FLUSH); 2845 if (rv == Z_NEED_DICT) { 2846 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary 2847 : kV3Dictionary; 2848 const int dictionary_size = (protocol_version() <= SPDY2) ? 2849 kV2DictionarySize : kV3DictionarySize; 2850 const DictionaryIds& ids = g_dictionary_ids.Get(); 2851 const uLong dictionary_id = (protocol_version() <= SPDY2) ? 2852 ids.v2_dictionary_id : ids.v3_dictionary_id; 2853 // Need to try again with the right dictionary. 2854 if (decomp->adler == dictionary_id) { 2855 rv = inflateSetDictionary(decomp, 2856 reinterpret_cast<const Bytef*>(dictionary), 2857 dictionary_size); 2858 if (rv == Z_OK) 2859 rv = inflate(decomp, Z_SYNC_FLUSH); 2860 } 2861 } 2862 2863 // Inflate will generate a Z_BUF_ERROR if it runs out of input 2864 // without producing any output. The input is consumed and 2865 // buffered internally by zlib so we can detect this condition by 2866 // checking if avail_in is 0 after the call to inflate. 2867 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); 2868 if ((rv == Z_OK) || input_exhausted) { 2869 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 2870 if (decompressed_len > 0) { 2871 processed_successfully = visitor_->OnControlFrameHeaderData( 2872 stream_id, buffer, decompressed_len); 2873 } 2874 if (!processed_successfully) { 2875 // Assume that the problem was the header block was too large for the 2876 // visitor. 2877 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 2878 } 2879 } else { 2880 DLOG(WARNING) << "inflate failure: " << rv << " " << len; 2881 set_error(SPDY_DECOMPRESS_FAILURE); 2882 processed_successfully = false; 2883 } 2884 } 2885 return processed_successfully; 2886} 2887 2888bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 2889 SpdyStreamId stream_id, const char* data, size_t len) { 2890 bool read_successfully = true; 2891 while (read_successfully && len > 0) { 2892 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 2893 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 2894 bytes_to_deliver); 2895 data += bytes_to_deliver; 2896 len -= bytes_to_deliver; 2897 if (!read_successfully) { 2898 // Assume that the problem was the header block was too large for the 2899 // visitor. 2900 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 2901 } 2902 } 2903 return read_successfully; 2904} 2905 2906void SpdyFramer::SerializeNameValueBlockWithoutCompression( 2907 SpdyFrameBuilder* builder, 2908 const SpdyNameValueBlock& name_value_block) const { 2909 // Serialize number of headers. 2910 if (protocol_version() <= SPDY2) { 2911 builder->WriteUInt16(name_value_block.size()); 2912 } else { 2913 builder->WriteUInt32(name_value_block.size()); 2914 } 2915 2916 // Serialize each header. 2917 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin(); 2918 it != name_value_block.end(); 2919 ++it) { 2920 if (protocol_version() <= SPDY2) { 2921 builder->WriteString(it->first); 2922 builder->WriteString(it->second); 2923 } else { 2924 builder->WriteStringPiece32(it->first); 2925 builder->WriteStringPiece32(it->second); 2926 } 2927 } 2928} 2929 2930void SpdyFramer::SerializeNameValueBlock( 2931 SpdyFrameBuilder* builder, 2932 const SpdyFrameWithNameValueBlockIR& frame) { 2933 CHECK_GE(SPDY3, protocol_version()); 2934 if (!enable_compression_) { 2935 return SerializeNameValueBlockWithoutCompression(builder, 2936 frame.name_value_block()); 2937 } 2938 2939 // First build an uncompressed version to be fed into the compressor. 2940 const size_t uncompressed_len = GetSerializedLength( 2941 protocol_version(), &(frame.name_value_block())); 2942 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version()); 2943 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, 2944 frame.name_value_block()); 2945 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); 2946 2947 z_stream* compressor = GetHeaderCompressor(); 2948 if (!compressor) { 2949 LOG(DFATAL) << "Could not obtain compressor."; 2950 return; 2951 } 2952 2953 base::StatsCounter compressed_frames("spdy.CompressedFrames"); 2954 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 2955 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 2956 2957 // Create an output frame. 2958 // Since we'll be performing lots of flushes when compressing the data, 2959 // zlib's lower bounds may be insufficient. 2960 // 2961 // TODO(akalin): Avoid the duplicate calculation with 2962 // GetSerializedLength(const SpdyHeaderBlock&). 2963 const int compressed_max_size = 2964 2 * deflateBound(compressor, uncompressed_len); 2965 2966 // TODO(phajdan.jr): Clean up after we no longer need 2967 // to workaround http://crbug.com/139744. 2968#if defined(USE_SYSTEM_ZLIB) 2969 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); 2970 compressor->avail_in = uncompressed_len; 2971#endif // defined(USE_SYSTEM_ZLIB) 2972 compressor->next_out = reinterpret_cast<Bytef*>( 2973 builder->GetWritableBuffer(compressed_max_size)); 2974 compressor->avail_out = compressed_max_size; 2975 2976 // TODO(phajdan.jr): Clean up after we no longer need 2977 // to workaround http://crbug.com/139744. 2978#if defined(USE_SYSTEM_ZLIB) 2979 int rv = deflate(compressor, Z_SYNC_FLUSH); 2980 if (rv != Z_OK) { // How can we know that it compressed everything? 2981 // This shouldn't happen, right? 2982 LOG(WARNING) << "deflate failure: " << rv; 2983 // TODO(akalin): Upstream this return. 2984 return; 2985 } 2986#else 2987 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); 2988#endif // defined(USE_SYSTEM_ZLIB) 2989 2990 int compressed_size = compressed_max_size - compressor->avail_out; 2991 builder->Seek(compressed_size); 2992 builder->RewriteLength(*this); 2993 2994 pre_compress_bytes.Add(uncompressed_len); 2995 post_compress_bytes.Add(compressed_size); 2996 2997 compressed_frames.Increment(); 2998} 2999 3000} // namespace net 3001