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