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