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