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