spdy_framer.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); 826 return; 827 } 828 829 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 830} 831 832size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 833 size_t max_bytes) { 834 size_t bytes_to_read = std::min(*len, max_bytes); 835 if (bytes_to_read > 0) { 836 DCHECK_GE(kControlFrameBufferSize, 837 current_frame_buffer_length_ + bytes_to_read); 838 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, 839 *data, 840 bytes_to_read); 841 current_frame_buffer_length_ += bytes_to_read; 842 *data += bytes_to_read; 843 *len -= bytes_to_read; 844 } 845 return bytes_to_read; 846} 847 848size_t SpdyFramer::GetSerializedLength(const int spdy_version, 849 const SpdyHeaderBlock* headers) { 850 const size_t num_name_value_pairs_size 851 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32); 852 const size_t length_of_name_size = num_name_value_pairs_size; 853 const size_t length_of_value_size = num_name_value_pairs_size; 854 855 size_t total_length = num_name_value_pairs_size; 856 for (SpdyHeaderBlock::const_iterator it = headers->begin(); 857 it != headers->end(); 858 ++it) { 859 // We add space for the length of the name and the length of the value as 860 // well as the length of the name and the length of the value. 861 total_length += length_of_name_size + it->first.size() + 862 length_of_value_size + it->second.size(); 863 } 864 return total_length; 865} 866 867void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, 868 const int spdy_version, 869 const SpdyHeaderBlock* headers) { 870 if (spdy_version < 3) { 871 frame->WriteUInt16(headers->size()); // Number of headers. 872 } else { 873 frame->WriteUInt32(headers->size()); // Number of headers. 874 } 875 SpdyHeaderBlock::const_iterator it; 876 for (it = headers->begin(); it != headers->end(); ++it) { 877 if (spdy_version < 3) { 878 frame->WriteString(it->first); 879 frame->WriteString(it->second); 880 } else { 881 frame->WriteStringPiece32(it->first); 882 frame->WriteStringPiece32(it->second); 883 } 884 } 885} 886 887// TODO(phajdan.jr): Clean up after we no longer need 888// to workaround http://crbug.com/139744. 889#if !defined(USE_SYSTEM_ZLIB) 890 891// These constants are used by zlib to differentiate between normal data and 892// cookie data. Cookie data is handled specially by zlib when compressing. 893enum ZDataClass { 894 // kZStandardData is compressed normally, save that it will never match 895 // against any other class of data in the window. 896 kZStandardData = Z_CLASS_STANDARD, 897 // kZCookieData is compressed in its own Huffman blocks and only matches in 898 // its entirety and only against other kZCookieData blocks. Any matches must 899 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching 900 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent 901 // prefix matches. 902 kZCookieData = Z_CLASS_COOKIE, 903 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed 904 // against the window. 905 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY, 906}; 907 908// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as 909// needed when switching between classes of data. 910static void WriteZ(const base::StringPiece& data, 911 ZDataClass clas, 912 z_stream* out) { 913 int rv; 914 915 // If we are switching from standard to non-standard data then we need to end 916 // the current Huffman context to avoid it leaking between them. 917 if (out->clas == kZStandardData && 918 clas != kZStandardData) { 919 out->avail_in = 0; 920 rv = deflate(out, Z_PARTIAL_FLUSH); 921 DCHECK_EQ(Z_OK, rv); 922 DCHECK_EQ(0u, out->avail_in); 923 DCHECK_LT(0u, out->avail_out); 924 } 925 926 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data())); 927 out->avail_in = data.size(); 928 out->clas = clas; 929 if (clas == kZStandardData) { 930 rv = deflate(out, Z_NO_FLUSH); 931 } else { 932 rv = deflate(out, Z_PARTIAL_FLUSH); 933 } 934 if (!data.empty()) { 935 // If we didn't provide any data then zlib will return Z_BUF_ERROR. 936 DCHECK_EQ(Z_OK, rv); 937 } 938 DCHECK_EQ(0u, out->avail_in); 939 DCHECK_LT(0u, out->avail_out); 940} 941 942// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|. 943static void WriteLengthZ(size_t n, 944 unsigned length, 945 ZDataClass clas, 946 z_stream* out) { 947 char buf[4]; 948 DCHECK_LE(length, sizeof(buf)); 949 for (unsigned i = 1; i <= length; i++) { 950 buf[length - i] = n; 951 n >>= 8; 952 } 953 WriteZ(base::StringPiece(buf, length), clas, out); 954} 955 956// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a 957// manner that resists the length of the compressed data from compromising 958// cookie data. 959void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, 960 z_stream* z) const { 961 unsigned length_length = 4; 962 if (spdy_version_ < 3) 963 length_length = 2; 964 965 WriteLengthZ(headers->size(), length_length, kZStandardData, z); 966 967 std::map<std::string, std::string>::const_iterator it; 968 for (it = headers->begin(); it != headers->end(); ++it) { 969 WriteLengthZ(it->first.size(), length_length, kZStandardData, z); 970 WriteZ(it->first, kZStandardData, z); 971 972 if (it->first == "cookie") { 973 // We require the cookie values (save for the last) to end with a 974 // semicolon and (save for the first) to start with a space. This is 975 // typically the format that we are given them in but we reserialize them 976 // to be sure. 977 978 std::vector<base::StringPiece> cookie_values; 979 size_t cookie_length = 0; 980 base::StringPiece cookie_data(it->second); 981 982 for (;;) { 983 while (!cookie_data.empty() && 984 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) { 985 cookie_data.remove_prefix(1); 986 } 987 if (cookie_data.empty()) 988 break; 989 990 size_t i; 991 for (i = 0; i < cookie_data.size(); i++) { 992 if (cookie_data[i] == ';') 993 break; 994 } 995 if (i < cookie_data.size()) { 996 cookie_values.push_back(cookie_data.substr(0, i)); 997 cookie_length += i + 2 /* semicolon and space */; 998 cookie_data.remove_prefix(i + 1); 999 } else { 1000 cookie_values.push_back(cookie_data); 1001 cookie_length += cookie_data.size(); 1002 cookie_data.remove_prefix(i); 1003 } 1004 } 1005 1006 WriteLengthZ(cookie_length, length_length, kZStandardData, z); 1007 for (size_t i = 0; i < cookie_values.size(); i++) { 1008 std::string cookie; 1009 // Since zlib will only back-reference complete cookies, a cookie that 1010 // is currently last (and so doesn't have a trailing semicolon) won't 1011 // match if it's later in a non-final position. The same is true of 1012 // the first cookie. 1013 if (i == 0 && cookie_values.size() == 1) { 1014 cookie = cookie_values[i].as_string(); 1015 } else if (i == 0) { 1016 cookie = cookie_values[i].as_string() + ";"; 1017 } else if (i < cookie_values.size() - 1) { 1018 cookie = " " + cookie_values[i].as_string() + ";"; 1019 } else { 1020 cookie = " " + cookie_values[i].as_string(); 1021 } 1022 WriteZ(cookie, kZCookieData, z); 1023 } 1024 } else if (it->first == "accept" || 1025 it->first == "accept-charset" || 1026 it->first == "accept-encoding" || 1027 it->first == "accept-language" || 1028 it->first == "host" || 1029 it->first == "version" || 1030 it->first == "method" || 1031 it->first == "scheme" || 1032 it->first == ":host" || 1033 it->first == ":version" || 1034 it->first == ":method" || 1035 it->first == ":scheme" || 1036 it->first == "user-agent") { 1037 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 1038 WriteZ(it->second, kZStandardData, z); 1039 } else { 1040 // Non-whitelisted headers are Huffman compressed in their own block, but 1041 // don't match against the window. 1042 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 1043 WriteZ(it->second, kZHuffmanOnlyData, z); 1044 } 1045 } 1046 1047 z->avail_in = 0; 1048 int rv = deflate(z, Z_SYNC_FLUSH); 1049 DCHECK_EQ(Z_OK, rv); 1050 z->clas = kZStandardData; 1051} 1052#endif // !defined(USE_SYSTEM_ZLIB) 1053 1054size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 1055 size_t len) { 1056 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 1057 size_t original_len = len; 1058 1059 if (remaining_control_header_ > 0) { 1060 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 1061 remaining_control_header_); 1062 remaining_control_header_ -= bytes_read; 1063 remaining_data_length_ -= bytes_read; 1064 } 1065 1066 if (remaining_control_header_ == 0) { 1067 SpdyFrameReader reader(current_frame_buffer_.get(), 1068 current_frame_buffer_length_); 1069 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 1070 1071 switch (current_frame_type_) { 1072 case SYN_STREAM: 1073 { 1074 bool successful_read = true; 1075 if (spdy_version_ < 4) { 1076 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1077 DCHECK(successful_read); 1078 } 1079 1080 SpdyStreamId associated_to_stream_id = kInvalidStream; 1081 successful_read = reader.ReadUInt31(&associated_to_stream_id); 1082 DCHECK(successful_read); 1083 1084 SpdyPriority priority = 0; 1085 successful_read = reader.ReadUInt8(&priority); 1086 DCHECK(successful_read); 1087 if (protocol_version() < 3) { 1088 priority = priority >> 6; 1089 } else { 1090 priority = priority >> 5; 1091 } 1092 1093 uint8 slot = 0; 1094 if (protocol_version() < 3) { 1095 // SPDY 2 had an unused byte here. Seek past it. 1096 reader.Seek(1); 1097 } else { 1098 successful_read = reader.ReadUInt8(&slot); 1099 DCHECK(successful_read); 1100 } 1101 1102 DCHECK(reader.IsDoneReading()); 1103 visitor_->OnSynStream( 1104 current_frame_stream_id_, 1105 associated_to_stream_id, 1106 priority, 1107 slot, 1108 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 1109 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 1110 } 1111 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1112 break; 1113 case SYN_REPLY: 1114 case HEADERS: 1115 // SYN_REPLY and HEADERS are the same, save for the visitor call. 1116 { 1117 bool successful_read = true; 1118 if (spdy_version_ < 4) { 1119 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1120 DCHECK(successful_read); 1121 } 1122 if (protocol_version() < 3) { 1123 // SPDY 2 had two unused bytes here. Seek past them. 1124 reader.Seek(2); 1125 } 1126 DCHECK(reader.IsDoneReading()); 1127 if (current_frame_type_ == SYN_REPLY) { 1128 visitor_->OnSynReply( 1129 current_frame_stream_id_, 1130 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 1131 } else { 1132 visitor_->OnHeaders( 1133 current_frame_stream_id_, 1134 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 1135 } 1136 } 1137 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1138 break; 1139 case SETTINGS: 1140 visitor_->OnSettings(current_frame_flags_ & 1141 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS); 1142 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); 1143 break; 1144 default: 1145 DCHECK(false); 1146 } 1147 } 1148 return original_len - len; 1149} 1150 1151// Does not buffer the control payload. Instead, either passes directly to the 1152// visitor or decompresses and then passes directly to the visitor, via 1153// IncrementallyDeliverControlFrameHeaderData() or 1154// IncrementallyDecompressControlFrameHeaderData() respectively. 1155size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 1156 size_t data_len) { 1157 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 1158 1159 bool processed_successfully = true; 1160 if (current_frame_type_ != SYN_STREAM && 1161 current_frame_type_ != SYN_REPLY && 1162 current_frame_type_ != HEADERS) { 1163 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; 1164 } 1165 size_t process_bytes = std::min(data_len, remaining_data_length_); 1166 if (process_bytes > 0) { 1167 if (enable_compression_) { 1168 processed_successfully = IncrementallyDecompressControlFrameHeaderData( 1169 current_frame_stream_id_, data, process_bytes); 1170 } else { 1171 processed_successfully = IncrementallyDeliverControlFrameHeaderData( 1172 current_frame_stream_id_, data, process_bytes); 1173 } 1174 1175 remaining_data_length_ -= process_bytes; 1176 } 1177 1178 // Handle the case that there is no futher data in this frame. 1179 if (remaining_data_length_ == 0 && processed_successfully) { 1180 // The complete header block has been delivered. We send a zero-length 1181 // OnControlFrameHeaderData() to indicate this. 1182 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); 1183 1184 // If this is a FIN, tell the caller. 1185 if (current_frame_flags_ & CONTROL_FLAG_FIN) { 1186 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 1187 } 1188 1189 CHANGE_STATE(SPDY_AUTO_RESET); 1190 } 1191 1192 // Handle error. 1193 if (!processed_successfully) { 1194 return data_len; 1195 } 1196 1197 // Return amount processed. 1198 return process_bytes; 1199} 1200 1201size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, 1202 size_t data_len) { 1203 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); 1204 DCHECK_EQ(SETTINGS, current_frame_type_); 1205 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); 1206 size_t processed_bytes = 0; 1207 1208 // Loop over our incoming data. 1209 while (unprocessed_bytes > 0) { 1210 // Process up to one setting at a time. 1211 size_t processing = std::min( 1212 unprocessed_bytes, 1213 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); 1214 1215 // Check if we have a complete setting in our input. 1216 if (processing == 8) { 1217 // Parse the setting directly out of the input without buffering. 1218 if (!ProcessSetting(data + processed_bytes)) { 1219 set_error(SPDY_INVALID_CONTROL_FRAME); 1220 return processed_bytes; 1221 } 1222 } else { 1223 // Continue updating settings_scratch_.setting_buf. 1224 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len, 1225 data + processed_bytes, 1226 processing); 1227 settings_scratch_.setting_buf_len += processing; 1228 1229 // Check if we have a complete setting buffered. 1230 if (settings_scratch_.setting_buf_len == 8) { 1231 if (!ProcessSetting(settings_scratch_.setting_buf)) { 1232 set_error(SPDY_INVALID_CONTROL_FRAME); 1233 return processed_bytes; 1234 } 1235 // Reset settings_scratch_.setting_buf for our next setting. 1236 settings_scratch_.setting_buf_len = 0; 1237 } 1238 } 1239 1240 // Iterate. 1241 unprocessed_bytes -= processing; 1242 processed_bytes += processing; 1243 } 1244 1245 // Check if we're done handling this SETTINGS frame. 1246 remaining_data_length_ -= processed_bytes; 1247 if (remaining_data_length_ == 0) { 1248 CHANGE_STATE(SPDY_AUTO_RESET); 1249 } 1250 1251 return processed_bytes; 1252} 1253 1254bool SpdyFramer::ProcessSetting(const char* data) { 1255 // Extract fields. 1256 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. 1257 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data)); 1258 SettingsFlagsAndId id_and_flags = 1259 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire); 1260 uint8 flags = id_and_flags.flags(); 1261 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); 1262 1263 // Validate id. 1264 switch (id_and_flags.id()) { 1265 case SETTINGS_UPLOAD_BANDWIDTH: 1266 case SETTINGS_DOWNLOAD_BANDWIDTH: 1267 case SETTINGS_ROUND_TRIP_TIME: 1268 case SETTINGS_MAX_CONCURRENT_STREAMS: 1269 case SETTINGS_CURRENT_CWND: 1270 case SETTINGS_DOWNLOAD_RETRANS_RATE: 1271 case SETTINGS_INITIAL_WINDOW_SIZE: 1272 // Valid values. 1273 break; 1274 default: 1275 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id(); 1276 return false; 1277 } 1278 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id()); 1279 1280 // Detect duplciates. 1281 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) { 1282 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id 1283 << " in " << display_protocol_ << " SETTINGS frame " 1284 << "(last settikng id was " 1285 << settings_scratch_.last_setting_id << ")."; 1286 return false; 1287 } 1288 settings_scratch_.last_setting_id = id; 1289 1290 // Validate flags. 1291 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED; 1292 if ((flags & ~(kFlagsMask)) != 0) { 1293 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": " 1294 << flags; 1295 return false; 1296 } 1297 1298 // Validation succeeded. Pass on to visitor. 1299 visitor_->OnSetting(id, flags, value); 1300 return true; 1301} 1302 1303size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 1304 size_t original_len = len; 1305 size_t bytes_read = 1306 UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_); 1307 remaining_data_length_ -= bytes_read; 1308 if (remaining_data_length_ == 0) { 1309 SpdyFrameReader reader(current_frame_buffer_.get(), 1310 current_frame_buffer_length_); 1311 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header. 1312 1313 // Use frame-specific handlers. 1314 switch (current_frame_type_) { 1315 case PING: { 1316 SpdyPingId id = 0; 1317 bool successful_read = reader.ReadUInt32(&id); 1318 DCHECK(successful_read); 1319 DCHECK(reader.IsDoneReading()); 1320 visitor_->OnPing(id); 1321 } 1322 break; 1323 case WINDOW_UPDATE: { 1324 uint32 delta_window_size = 0; 1325 bool successful_read = true; 1326 if (spdy_version_ < 4) { 1327 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1328 DCHECK(successful_read); 1329 } 1330 successful_read = reader.ReadUInt32(&delta_window_size); 1331 DCHECK(successful_read); 1332 DCHECK(reader.IsDoneReading()); 1333 visitor_->OnWindowUpdate(current_frame_stream_id_, 1334 delta_window_size); 1335 } 1336 break; 1337 case RST_STREAM: { 1338 bool successful_read = true; 1339 if (spdy_version_ < 4) { 1340 successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1341 DCHECK(successful_read); 1342 } 1343 SpdyRstStreamStatus status = RST_STREAM_INVALID; 1344 uint32 status_raw = status; 1345 successful_read = reader.ReadUInt32(&status_raw); 1346 DCHECK(successful_read); 1347 if (status_raw > RST_STREAM_INVALID && 1348 status_raw < RST_STREAM_NUM_STATUS_CODES) { 1349 status = static_cast<SpdyRstStreamStatus>(status_raw); 1350 } else { 1351 // TODO(hkhalil): Probably best to OnError here, depending on 1352 // our interpretation of the spec. Keeping with existing liberal 1353 // behavior for now. 1354 } 1355 DCHECK(reader.IsDoneReading()); 1356 visitor_->OnRstStream(current_frame_stream_id_, status); 1357 } 1358 break; 1359 case GOAWAY: { 1360 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1361 DCHECK(successful_read); 1362 SpdyGoAwayStatus status = GOAWAY_OK; 1363 if (spdy_version_ >= 3) { 1364 uint32 status_raw = GOAWAY_OK; 1365 successful_read = reader.ReadUInt32(&status_raw); 1366 DCHECK(successful_read); 1367 if (status_raw >= GOAWAY_OK && 1368 status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) { 1369 status = static_cast<SpdyGoAwayStatus>(status_raw); 1370 } else { 1371 // TODO(hkhalil): Probably best to OnError here, depending on 1372 // our interpretation of the spec. Keeping with existing liberal 1373 // behavior for now. 1374 } 1375 } 1376 DCHECK(reader.IsDoneReading()); 1377 visitor_->OnGoAway(current_frame_stream_id_, status); 1378 } 1379 break; 1380 case BLOCKED: { 1381 DCHECK_LE(4, protocol_version()); 1382 DCHECK(reader.IsDoneReading()); 1383 visitor_->OnBlocked(current_frame_stream_id_); 1384 } 1385 break; 1386 default: 1387 // Unreachable. 1388 LOG(FATAL) << "Unhandled control frame " << current_frame_type_; 1389 } 1390 1391 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 1392 } 1393 return original_len - len; 1394} 1395 1396size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) { 1397 if (len > 0) { 1398 bool processed_succesfully = visitor_->OnCredentialFrameData(data, len); 1399 remaining_data_length_ -= len; 1400 if (!processed_succesfully) { 1401 set_error(SPDY_CREDENTIAL_FRAME_CORRUPT); 1402 } else if (remaining_data_length_ == 0) { 1403 visitor_->OnCredentialFrameData(NULL, 0); 1404 CHANGE_STATE(SPDY_AUTO_RESET); 1405 } 1406 } 1407 return len; 1408} 1409 1410size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { 1411 size_t original_len = len; 1412 1413 if (remaining_data_length_ > 0) { 1414 size_t amount_to_forward = std::min(remaining_data_length_, len); 1415 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { 1416 // Only inform the visitor if there is data. 1417 if (amount_to_forward) { 1418 visitor_->OnStreamFrameData( 1419 current_frame_stream_id_, data, amount_to_forward, false); 1420 } 1421 } 1422 data += amount_to_forward; 1423 len -= amount_to_forward; 1424 remaining_data_length_ -= amount_to_forward; 1425 1426 // If the FIN flag is set, and there is no more data in this data 1427 // frame, inform the visitor of EOF via a 0-length data frame. 1428 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) { 1429 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 1430 } 1431 } 1432 1433 if (remaining_data_length_ == 0) { 1434 CHANGE_STATE(SPDY_AUTO_RESET); 1435 } 1436 return original_len - len; 1437} 1438 1439size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 1440 size_t header_length, 1441 SpdyHeaderBlock* block) const { 1442 SpdyFrameReader reader(header_data, header_length); 1443 1444 // Read number of headers. 1445 uint32 num_headers; 1446 if (spdy_version_ < 3) { 1447 uint16 temp; 1448 if (!reader.ReadUInt16(&temp)) { 1449 DLOG(INFO) << "Unable to read number of headers."; 1450 return 0; 1451 } 1452 num_headers = temp; 1453 } else { 1454 if (!reader.ReadUInt32(&num_headers)) { 1455 DLOG(INFO) << "Unable to read number of headers."; 1456 return 0; 1457 } 1458 } 1459 1460 // Read each header. 1461 for (uint32 index = 0; index < num_headers; ++index) { 1462 base::StringPiece temp; 1463 1464 // Read header name. 1465 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) 1466 : !reader.ReadStringPiece32(&temp)) { 1467 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " 1468 << num_headers << ")."; 1469 return 0; 1470 } 1471 std::string name = temp.as_string(); 1472 1473 // Read header value. 1474 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) 1475 : !reader.ReadStringPiece32(&temp)) { 1476 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " 1477 << num_headers << ")."; 1478 return 0; 1479 } 1480 std::string value = temp.as_string(); 1481 1482 // Ensure no duplicates. 1483 if (block->find(name) != block->end()) { 1484 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " 1485 << num_headers << ")."; 1486 return 0; 1487 } 1488 1489 // Store header. 1490 (*block)[name] = value; 1491 } 1492 return reader.GetBytesConsumed(); 1493} 1494 1495/* static */ 1496bool SpdyFramer::ParseCredentialData(const char* data, size_t len, 1497 SpdyCredential* credential) { 1498 DCHECK(credential); 1499 1500 SpdyFrameReader parser(data, len); 1501 base::StringPiece temp; 1502 if (!parser.ReadUInt16(&credential->slot)) { 1503 return false; 1504 } 1505 1506 if (!parser.ReadStringPiece32(&temp)) { 1507 return false; 1508 } 1509 credential->proof = temp.as_string(); 1510 1511 while (!parser.IsDoneReading()) { 1512 if (!parser.ReadStringPiece32(&temp)) { 1513 return false; 1514 } 1515 credential->certs.push_back(temp.as_string()); 1516 } 1517 return true; 1518} 1519 1520SpdyFrame* SpdyFramer::CreateSynStream( 1521 SpdyStreamId stream_id, 1522 SpdyStreamId associated_stream_id, 1523 SpdyPriority priority, 1524 uint8 credential_slot, 1525 SpdyControlFlags flags, 1526 bool compressed, 1527 const SpdyHeaderBlock* headers) { 1528 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL); 1529 DCHECK_EQ(enable_compression_, compressed); 1530 1531 SpdySynStreamIR syn_stream(stream_id); 1532 syn_stream.set_associated_to_stream_id(associated_stream_id); 1533 syn_stream.set_priority(priority); 1534 syn_stream.set_slot(credential_slot); 1535 syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0); 1536 syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 1537 // TODO(hkhalil): Avoid copy here. 1538 *(syn_stream.GetMutableNameValueBlock()) = *headers; 1539 1540 scoped_ptr<SpdyFrame> syn_frame(SerializeSynStream(syn_stream)); 1541 return syn_frame.release(); 1542} 1543 1544SpdySerializedFrame* SpdyFramer::SerializeSynStream( 1545 const SpdySynStreamIR& syn_stream) { 1546 uint8 flags = 0; 1547 if (syn_stream.fin()) { 1548 flags |= CONTROL_FLAG_FIN; 1549 } 1550 if (syn_stream.unidirectional()) { 1551 flags |= CONTROL_FLAG_UNIDIRECTIONAL; 1552 } 1553 1554 // The size of this frame, including variable-length name-value block. 1555 const size_t size = GetSynStreamMinimumSize() 1556 + GetSerializedLength(syn_stream.name_value_block()); 1557 1558 SpdyFrameBuilder builder(size); 1559 if (spdy_version_ < 4) { 1560 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); 1561 builder.WriteUInt32(syn_stream.stream_id()); 1562 } else { 1563 builder.WriteFramePrefix(*this, 1564 SYN_STREAM, 1565 flags, 1566 syn_stream.stream_id()); 1567 } 1568 builder.WriteUInt32(syn_stream.associated_to_stream_id()); 1569 uint8 priority = syn_stream.priority(); 1570 if (priority > GetLowestPriority()) { 1571 DLOG(DFATAL) << "Priority out-of-bounds."; 1572 priority = GetLowestPriority(); 1573 } 1574 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); 1575 builder.WriteUInt8(syn_stream.slot()); 1576 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); 1577 SerializeNameValueBlock(&builder, syn_stream); 1578 1579 if (visitor_) 1580 visitor_->OnSynStreamCompressed(size, builder.length()); 1581 1582 return builder.take(); 1583} 1584 1585SpdyFrame* SpdyFramer::CreateSynReply( 1586 SpdyStreamId stream_id, 1587 SpdyControlFlags flags, 1588 bool compressed, 1589 const SpdyHeaderBlock* headers) { 1590 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); 1591 DCHECK_EQ(enable_compression_, compressed); 1592 1593 SpdySynReplyIR syn_reply(stream_id); 1594 syn_reply.set_fin(flags & CONTROL_FLAG_FIN); 1595 // TODO(hkhalil): Avoid copy here. 1596 *(syn_reply.GetMutableNameValueBlock()) = *headers; 1597 1598 scoped_ptr<SpdyFrame> reply_frame(SerializeSynReply(syn_reply)); 1599 return reply_frame.release(); 1600} 1601 1602SpdySerializedFrame* SpdyFramer::SerializeSynReply( 1603 const SpdySynReplyIR& syn_reply) { 1604 uint8 flags = 0; 1605 if (syn_reply.fin()) { 1606 flags |= CONTROL_FLAG_FIN; 1607 } 1608 1609 // The size of this frame, including variable-length name-value block. 1610 size_t size = GetSynReplyMinimumSize() 1611 + GetSerializedLength(syn_reply.name_value_block()); 1612 1613 SpdyFrameBuilder builder(size); 1614 if (spdy_version_ < 4) { 1615 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); 1616 builder.WriteUInt32(syn_reply.stream_id()); 1617 } else { 1618 builder.WriteFramePrefix(*this, 1619 SYN_REPLY, 1620 flags, 1621 syn_reply.stream_id()); 1622 } 1623 if (protocol_version() < 3) { 1624 builder.WriteUInt16(0); // Unused. 1625 } 1626 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); 1627 SerializeNameValueBlock(&builder, syn_reply); 1628 1629 return builder.take(); 1630} 1631 1632SpdyFrame* SpdyFramer::CreateRstStream( 1633 SpdyStreamId stream_id, 1634 SpdyRstStreamStatus status) const { 1635 SpdyRstStreamIR rst_stream(stream_id, status); 1636 return SerializeRstStream(rst_stream); 1637} 1638 1639SpdySerializedFrame* SpdyFramer::SerializeRstStream( 1640 const SpdyRstStreamIR& rst_stream) const { 1641 SpdyFrameBuilder builder(GetRstStreamSize()); 1642 if (spdy_version_ < 4) { 1643 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); 1644 builder.WriteUInt32(rst_stream.stream_id()); 1645 } else { 1646 builder.WriteFramePrefix(*this, 1647 RST_STREAM, 1648 0, 1649 rst_stream.stream_id()); 1650 } 1651 builder.WriteUInt32(rst_stream.status()); 1652 DCHECK_EQ(GetRstStreamSize(), builder.length()); 1653 return builder.take(); 1654} 1655 1656SpdyFrame* SpdyFramer::CreateSettings( 1657 const SettingsMap& values) const { 1658 SpdySettingsIR settings; 1659 for (SettingsMap::const_iterator it = values.begin(); 1660 it != values.end(); 1661 ++it) { 1662 settings.AddSetting(it->first, 1663 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, 1664 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, 1665 it->second.second); 1666 } 1667 return SerializeSettings(settings); 1668} 1669 1670SpdySerializedFrame* SpdyFramer::SerializeSettings( 1671 const SpdySettingsIR& settings) const { 1672 uint8 flags = 0; 1673 if (settings.clear_settings()) { 1674 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 1675 } 1676 const SpdySettingsIR::ValueMap* values = &(settings.values()); 1677 1678 // Size, in bytes, of this SETTINGS frame. 1679 const size_t size = GetSettingsMinimumSize() + (values->size() * 8); 1680 1681 SpdyFrameBuilder builder(size); 1682 if (spdy_version_ < 4) { 1683 builder.WriteControlFrameHeader(*this, SETTINGS, flags); 1684 } else { 1685 builder.WriteFramePrefix(*this, SETTINGS, flags, 0); 1686 } 1687 builder.WriteUInt32(values->size()); 1688 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); 1689 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); 1690 it != values->end(); 1691 ++it) { 1692 uint8 setting_flags = 0; 1693 if (it->second.persist_value) { 1694 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; 1695 } 1696 if (it->second.persisted) { 1697 setting_flags |= SETTINGS_FLAG_PERSISTED; 1698 } 1699 SettingsFlagsAndId flags_and_id(setting_flags, it->first); 1700 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); 1701 builder.WriteBytes(&id_and_flags_wire, 4); 1702 builder.WriteUInt32(it->second.value); 1703 } 1704 DCHECK_EQ(size, builder.length()); 1705 return builder.take(); 1706} 1707 1708SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { 1709 DCHECK_LE(4, protocol_version()); 1710 SpdyFrameBuilder builder(GetBlockedSize()); 1711 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id()); 1712 return builder.take(); 1713} 1714 1715SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { 1716 SpdyPingIR ping(unique_id); 1717 return SerializePing(ping); 1718} 1719 1720SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { 1721 SpdyFrameBuilder builder(GetPingSize()); 1722 if (spdy_version_ < 4) { 1723 builder.WriteControlFrameHeader(*this, PING, kNoFlags); 1724 } else { 1725 builder.WriteFramePrefix(*this, PING, 0, 0); 1726 } 1727 builder.WriteUInt32(ping.id()); 1728 DCHECK_EQ(GetPingSize(), builder.length()); 1729 return builder.take(); 1730} 1731 1732SpdyFrame* SpdyFramer::CreateGoAway( 1733 SpdyStreamId last_accepted_stream_id, 1734 SpdyGoAwayStatus status) const { 1735 SpdyGoAwayIR goaway(last_accepted_stream_id, status); 1736 return SerializeGoAway(goaway); 1737} 1738 1739SpdySerializedFrame* SpdyFramer::SerializeGoAway( 1740 const SpdyGoAwayIR& goaway) const { 1741 SpdyFrameBuilder builder(GetGoAwaySize()); 1742 if (spdy_version_ < 4) { 1743 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); 1744 } else { 1745 builder.WriteFramePrefix(*this, GOAWAY, 0, 0); 1746 } 1747 builder.WriteUInt32(goaway.last_good_stream_id()); 1748 if (protocol_version() >= 3) { 1749 builder.WriteUInt32(goaway.status()); 1750 } 1751 DCHECK_EQ(GetGoAwaySize(), builder.length()); 1752 return builder.take(); 1753} 1754 1755SpdyFrame* SpdyFramer::CreateHeaders( 1756 SpdyStreamId stream_id, 1757 SpdyControlFlags flags, 1758 bool compressed, 1759 const SpdyHeaderBlock* header_block) { 1760 // Basically the same as CreateSynReply(). 1761 DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); 1762 DCHECK_EQ(enable_compression_, compressed); 1763 1764 SpdyHeadersIR headers(stream_id); 1765 headers.set_fin(flags & CONTROL_FLAG_FIN); 1766 // TODO(hkhalil): Avoid copy here. 1767 *(headers.GetMutableNameValueBlock()) = *header_block; 1768 1769 scoped_ptr<SpdyFrame> headers_frame(SerializeHeaders(headers)); 1770 return headers_frame.release(); 1771} 1772 1773SpdySerializedFrame* SpdyFramer::SerializeHeaders( 1774 const SpdyHeadersIR& headers) { 1775 uint8 flags = 0; 1776 if (headers.fin()) { 1777 flags |= CONTROL_FLAG_FIN; 1778 } 1779 1780 // The size of this frame, including variable-length name-value block. 1781 size_t size = GetHeadersMinimumSize() 1782 + GetSerializedLength(headers.name_value_block()); 1783 1784 SpdyFrameBuilder builder(size); 1785 if (spdy_version_ < 4) { 1786 builder.WriteControlFrameHeader(*this, HEADERS, flags); 1787 builder.WriteUInt32(headers.stream_id()); 1788 } else { 1789 builder.WriteFramePrefix(*this, 1790 HEADERS, 1791 flags, 1792 headers.stream_id()); 1793 } 1794 if (protocol_version() < 3) { 1795 builder.WriteUInt16(0); // Unused. 1796 } 1797 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); 1798 1799 SerializeNameValueBlock(&builder, headers); 1800 1801 return builder.take(); 1802} 1803 1804SpdyFrame* SpdyFramer::CreateWindowUpdate( 1805 SpdyStreamId stream_id, 1806 uint32 delta_window_size) const { 1807 SpdyWindowUpdateIR window_update(stream_id, delta_window_size); 1808 return SerializeWindowUpdate(window_update); 1809} 1810 1811SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( 1812 const SpdyWindowUpdateIR& window_update) const { 1813 SpdyFrameBuilder builder(GetWindowUpdateSize()); 1814 if (spdy_version_ < 4) { 1815 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); 1816 builder.WriteUInt32(window_update.stream_id()); 1817 } else { 1818 builder.WriteFramePrefix(*this, 1819 WINDOW_UPDATE, 1820 kNoFlags, 1821 window_update.stream_id()); 1822 } 1823 builder.WriteUInt32(window_update.delta()); 1824 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); 1825 return builder.take(); 1826} 1827 1828// TODO(hkhalil): Gut with SpdyCredential removal. 1829SpdyFrame* SpdyFramer::CreateCredentialFrame( 1830 const SpdyCredential& credential) const { 1831 SpdyCredentialIR credential_ir(credential.slot); 1832 credential_ir.set_proof(credential.proof); 1833 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); 1834 cert != credential.certs.end(); 1835 ++cert) { 1836 credential_ir.AddCertificate(*cert); 1837 } 1838 return SerializeCredential(credential_ir); 1839} 1840 1841SpdySerializedFrame* SpdyFramer::SerializeCredential( 1842 const SpdyCredentialIR& credential) const { 1843 size_t size = GetCredentialMinimumSize(); 1844 size += 4 + credential.proof().length(); // Room for proof. 1845 for (SpdyCredentialIR::CertificateList::const_iterator it = 1846 credential.certificates()->begin(); 1847 it != credential.certificates()->end(); 1848 ++it) { 1849 size += 4 + it->length(); // Room for certificate. 1850 } 1851 1852 SpdyFrameBuilder builder(size); 1853 if (spdy_version_ < 4) { 1854 builder.WriteControlFrameHeader(*this, CREDENTIAL, kNoFlags); 1855 } else { 1856 builder.WriteFramePrefix(*this, CREDENTIAL, kNoFlags, 0); 1857 } 1858 builder.WriteUInt16(credential.slot()); 1859 DCHECK_EQ(GetCredentialMinimumSize(), builder.length()); 1860 builder.WriteStringPiece32(credential.proof()); 1861 for (SpdyCredentialIR::CertificateList::const_iterator it = 1862 credential.certificates()->begin(); 1863 it != credential.certificates()->end(); 1864 ++it) { 1865 builder.WriteStringPiece32(*it); 1866 } 1867 DCHECK_EQ(size, builder.length()); 1868 return builder.take(); 1869} 1870 1871SpdyFrame* SpdyFramer::CreateDataFrame( 1872 SpdyStreamId stream_id, const char* data, 1873 uint32 len, SpdyDataFlags flags) const { 1874 DCHECK_EQ(0, flags & (!DATA_FLAG_FIN)); 1875 1876 SpdyDataIR data_ir(stream_id, base::StringPiece(data, len)); 1877 data_ir.set_fin(flags & DATA_FLAG_FIN); 1878 return SerializeData(data_ir); 1879} 1880 1881SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const { 1882 const size_t kSize = GetDataFrameMinimumSize() + data.data().length(); 1883 1884 SpdyDataFlags flags = DATA_FLAG_NONE; 1885 if (data.fin()) { 1886 flags = DATA_FLAG_FIN; 1887 } 1888 1889 SpdyFrameBuilder builder(kSize); 1890 builder.WriteDataFrameHeader(*this, data.stream_id(), flags); 1891 builder.WriteBytes(data.data().data(), data.data().length()); 1892 DCHECK_EQ(kSize, builder.length()); 1893 return builder.take(); 1894} 1895 1896SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader( 1897 const SpdyDataIR& data) const { 1898 const size_t kSize = GetDataFrameMinimumSize(); 1899 1900 SpdyDataFlags flags = DATA_FLAG_NONE; 1901 if (data.fin()) { 1902 flags = DATA_FLAG_FIN; 1903 } 1904 1905 SpdyFrameBuilder builder(kSize); 1906 builder.WriteDataFrameHeader(*this, data.stream_id(), flags); 1907 if (protocol_version() < 4) { 1908 builder.OverwriteLength(*this, data.data().length()); 1909 } else { 1910 builder.OverwriteLength(*this, data.data().length() + kSize); 1911 } 1912 DCHECK_EQ(kSize, builder.length()); 1913 return builder.take(); 1914} 1915 1916size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { 1917 const size_t uncompressed_length = 1918 GetSerializedLength(protocol_version(), &headers); 1919 if (!enable_compression_) { 1920 return uncompressed_length; 1921 } 1922 z_stream* compressor = GetHeaderCompressor(); 1923 // Since we'll be performing lots of flushes when compressing the data, 1924 // zlib's lower bounds may be insufficient. 1925 return 2 * deflateBound(compressor, uncompressed_length); 1926} 1927 1928// The following compression setting are based on Brian Olson's analysis. See 1929// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792 1930// for more details. 1931#if defined(USE_SYSTEM_ZLIB) 1932// System zlib is not expected to have workaround for http://crbug.com/139744, 1933// so disable compression in that case. 1934// TODO(phajdan.jr): Remove the special case when it's no longer necessary. 1935static const int kCompressorLevel = 0; 1936#else // !defined(USE_SYSTEM_ZLIB) 1937static const int kCompressorLevel = 9; 1938#endif // !defined(USE_SYSTEM_ZLIB) 1939static const int kCompressorWindowSizeInBits = 11; 1940static const int kCompressorMemLevel = 1; 1941 1942z_stream* SpdyFramer::GetHeaderCompressor() { 1943 if (header_compressor_.get()) 1944 return header_compressor_.get(); // Already initialized. 1945 1946 header_compressor_.reset(new z_stream); 1947 memset(header_compressor_.get(), 0, sizeof(z_stream)); 1948 1949 int success = deflateInit2(header_compressor_.get(), 1950 kCompressorLevel, 1951 Z_DEFLATED, 1952 kCompressorWindowSizeInBits, 1953 kCompressorMemLevel, 1954 Z_DEFAULT_STRATEGY); 1955 if (success == Z_OK) { 1956 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary 1957 : kV3Dictionary; 1958 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize 1959 : kV3DictionarySize; 1960 success = deflateSetDictionary(header_compressor_.get(), 1961 reinterpret_cast<const Bytef*>(dictionary), 1962 dictionary_size); 1963 } 1964 if (success != Z_OK) { 1965 LOG(WARNING) << "deflateSetDictionary failure: " << success; 1966 header_compressor_.reset(NULL); 1967 return NULL; 1968 } 1969 return header_compressor_.get(); 1970} 1971 1972z_stream* SpdyFramer::GetHeaderDecompressor() { 1973 if (header_decompressor_.get()) 1974 return header_decompressor_.get(); // Already initialized. 1975 1976 header_decompressor_.reset(new z_stream); 1977 memset(header_decompressor_.get(), 0, sizeof(z_stream)); 1978 1979 int success = inflateInit(header_decompressor_.get()); 1980 if (success != Z_OK) { 1981 LOG(WARNING) << "inflateInit failure: " << success; 1982 header_decompressor_.reset(NULL); 1983 return NULL; 1984 } 1985 return header_decompressor_.get(); 1986} 1987 1988// Incrementally decompress the control frame's header block, feeding the 1989// result to the visitor in chunks. Continue this until the visitor 1990// indicates that it cannot process any more data, or (more commonly) we 1991// run out of data to deliver. 1992bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 1993 SpdyStreamId stream_id, 1994 const char* data, 1995 size_t len) { 1996 // Get a decompressor or set error. 1997 z_stream* decomp = GetHeaderDecompressor(); 1998 if (decomp == NULL) { 1999 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 2000 set_error(SPDY_DECOMPRESS_FAILURE); 2001 return false; 2002 } 2003 2004 bool processed_successfully = true; 2005 char buffer[kHeaderDataChunkMaxSize]; 2006 2007 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 2008 decomp->avail_in = len; 2009 DCHECK_LT(0u, stream_id); 2010 while (decomp->avail_in > 0 && processed_successfully) { 2011 decomp->next_out = reinterpret_cast<Bytef*>(buffer); 2012 decomp->avail_out = arraysize(buffer); 2013 2014 int rv = inflate(decomp, Z_SYNC_FLUSH); 2015 if (rv == Z_NEED_DICT) { 2016 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary 2017 : kV3Dictionary; 2018 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize 2019 : kV3DictionarySize; 2020 const DictionaryIds& ids = g_dictionary_ids.Get(); 2021 const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id 2022 : ids.v3_dictionary_id; 2023 // Need to try again with the right dictionary. 2024 if (decomp->adler == dictionary_id) { 2025 rv = inflateSetDictionary(decomp, 2026 reinterpret_cast<const Bytef*>(dictionary), 2027 dictionary_size); 2028 if (rv == Z_OK) 2029 rv = inflate(decomp, Z_SYNC_FLUSH); 2030 } 2031 } 2032 2033 // Inflate will generate a Z_BUF_ERROR if it runs out of input 2034 // without producing any output. The input is consumed and 2035 // buffered internally by zlib so we can detect this condition by 2036 // checking if avail_in is 0 after the call to inflate. 2037 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); 2038 if ((rv == Z_OK) || input_exhausted) { 2039 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 2040 if (debug_visitor_ != NULL) { 2041 debug_visitor_->OnDecompressedHeaderBlock(decompressed_len, len); 2042 } 2043 if (decompressed_len > 0) { 2044 processed_successfully = visitor_->OnControlFrameHeaderData( 2045 stream_id, buffer, decompressed_len); 2046 } 2047 if (!processed_successfully) { 2048 // Assume that the problem was the header block was too large for the 2049 // visitor. 2050 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 2051 } 2052 } else { 2053 DLOG(WARNING) << "inflate failure: " << rv << " " << len; 2054 set_error(SPDY_DECOMPRESS_FAILURE); 2055 processed_successfully = false; 2056 } 2057 } 2058 return processed_successfully; 2059} 2060 2061bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 2062 SpdyStreamId stream_id, const char* data, size_t len) { 2063 bool read_successfully = true; 2064 while (read_successfully && len > 0) { 2065 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 2066 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 2067 bytes_to_deliver); 2068 data += bytes_to_deliver; 2069 len -= bytes_to_deliver; 2070 if (!read_successfully) { 2071 // Assume that the problem was the header block was too large for the 2072 // visitor. 2073 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 2074 } 2075 } 2076 return read_successfully; 2077} 2078 2079void SpdyFramer::SerializeNameValueBlockWithoutCompression( 2080 SpdyFrameBuilder* builder, 2081 const SpdyNameValueBlock& name_value_block) const { 2082 // Serialize number of headers. 2083 if (protocol_version() < 3) { 2084 builder->WriteUInt16(name_value_block.size()); 2085 } else { 2086 builder->WriteUInt32(name_value_block.size()); 2087 } 2088 2089 // Serialize each header. 2090 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin(); 2091 it != name_value_block.end(); 2092 ++it) { 2093 if (protocol_version() < 3) { 2094 builder->WriteString(it->first); 2095 builder->WriteString(it->second); 2096 } else { 2097 builder->WriteStringPiece32(it->first); 2098 builder->WriteStringPiece32(it->second); 2099 } 2100 } 2101} 2102 2103void SpdyFramer::SerializeNameValueBlock( 2104 SpdyFrameBuilder* builder, 2105 const SpdyFrameWithNameValueBlockIR& frame) { 2106 if (!enable_compression_) { 2107 return SerializeNameValueBlockWithoutCompression(builder, 2108 frame.name_value_block()); 2109 } 2110 2111 // First build an uncompressed version to be fed into the compressor. 2112 const size_t uncompressed_len = GetSerializedLength( 2113 protocol_version(), &(frame.name_value_block())); 2114 SpdyFrameBuilder uncompressed_builder(uncompressed_len); 2115 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, 2116 frame.name_value_block()); 2117 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); 2118 2119 z_stream* compressor = GetHeaderCompressor(); 2120 if (!compressor) { 2121 LOG(DFATAL) << "Could not obtain compressor."; 2122 return; 2123 } 2124 2125 base::StatsCounter compressed_frames("spdy.CompressedFrames"); 2126 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 2127 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 2128 2129 // Create an output frame. 2130 // Since we'll be performing lots of flushes when compressing the data, 2131 // zlib's lower bounds may be insufficient. 2132 // 2133 // TODO(akalin): Avoid the duplicate calculation with 2134 // GetSerializedLength(const SpdyHeaderBlock&). 2135 const int compressed_max_size = 2136 2 * deflateBound(compressor, uncompressed_len); 2137 2138 // TODO(phajdan.jr): Clean up after we no longer need 2139 // to workaround http://crbug.com/139744. 2140#if defined(USE_SYSTEM_ZLIB) 2141 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); 2142 compressor->avail_in = uncompressed_len; 2143#endif // defined(USE_SYSTEM_ZLIB) 2144 compressor->next_out = reinterpret_cast<Bytef*>( 2145 builder->GetWritableBuffer(compressed_max_size)); 2146 compressor->avail_out = compressed_max_size; 2147 2148 // TODO(phajdan.jr): Clean up after we no longer need 2149 // to workaround http://crbug.com/139744. 2150#if defined(USE_SYSTEM_ZLIB) 2151 int rv = deflate(compressor, Z_SYNC_FLUSH); 2152 if (rv != Z_OK) { // How can we know that it compressed everything? 2153 // This shouldn't happen, right? 2154 LOG(WARNING) << "deflate failure: " << rv; 2155 // TODO(akalin): Upstream this return. 2156 return; 2157 } 2158#else 2159 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); 2160#endif // defined(USE_SYSTEM_ZLIB) 2161 2162 int compressed_size = compressed_max_size - compressor->avail_out; 2163 builder->Seek(compressed_size); 2164 builder->RewriteLength(*this); 2165 2166 pre_compress_bytes.Add(uncompressed_len); 2167 post_compress_bytes.Add(compressed_size); 2168 2169 compressed_frames.Increment(); 2170 2171 if (debug_visitor_ != NULL) { 2172 debug_visitor_->OnCompressedHeaderBlock(uncompressed_len, compressed_size); 2173 } 2174} 2175 2176} // namespace net 2177