| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't | 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- | 6 // constantly adding and subtracting header sizes; this is ugly and error- |
| 7 // prone. | 7 // prone. |
| 8 | 8 |
| 9 #include "net/spdy/spdy_framer.h" | 9 #include "net/spdy/spdy_framer.h" |
| 10 | 10 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 } // namespace | 57 } // namespace |
| 58 | 58 |
| 59 const int SpdyFramer::kMinSpdyVersion = 2; | 59 const int SpdyFramer::kMinSpdyVersion = 2; |
| 60 const int SpdyFramer::kMaxSpdyVersion = 3; | 60 const int SpdyFramer::kMaxSpdyVersion = 3; |
| 61 const SpdyStreamId SpdyFramer::kInvalidStream = -1; | 61 const SpdyStreamId SpdyFramer::kInvalidStream = -1; |
| 62 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 62 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
| 63 const size_t SpdyFramer::kControlFrameBufferSize = | 63 const size_t SpdyFramer::kControlFrameBufferSize = |
| 64 sizeof(SpdySynStreamControlFrameBlock); | 64 sizeof(SpdySynStreamControlFrameBlock); |
| 65 const size_t SpdyFramer::kMaxControlFrameSize = 16 * 1024; | 65 const size_t SpdyFramer::kMaxControlFrameSize = 16 * 1024; |
| 66 | 66 |
| 67 | |
| 68 #ifdef DEBUG_SPDY_STATE_CHANGES | 67 #ifdef DEBUG_SPDY_STATE_CHANGES |
| 69 #define CHANGE_STATE(newstate) \ | 68 #define CHANGE_STATE(newstate) \ |
| 70 do { \ | 69 do { \ |
| 71 LOG(INFO) << "Changing state from: " \ | 70 LOG(INFO) << "Changing state from: " \ |
| 72 << StateToString(state_) \ | 71 << StateToString(state_) \ |
| 73 << " to " << StateToString(newstate) << "\n"; \ | 72 << " to " << StateToString(newstate) << "\n"; \ |
| 74 DCHECK(state_ != SPDY_ERROR); \ | 73 DCHECK(state_ != SPDY_ERROR); \ |
| 75 DCHECK_EQ(previous_state_, state_); \ | 74 DCHECK_EQ(previous_state_, state_); \ |
| 76 previous_state_ = state_; \ | 75 previous_state_ = state_; \ |
| 77 state_ = newstate; \ | 76 state_ = newstate; \ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 89 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, | 88 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, |
| 90 uint32 wire) { | 89 uint32 wire) { |
| 91 if (version < 3) { | 90 if (version < 3) { |
| 92 ConvertFlagsAndIdForSpdy2(&wire); | 91 ConvertFlagsAndIdForSpdy2(&wire); |
| 93 } | 92 } |
| 94 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); | 93 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); |
| 95 } | 94 } |
| 96 | 95 |
| 97 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) | 96 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) |
| 98 : flags_(flags), id_(id & 0x00ffffff) { | 97 : flags_(flags), id_(id & 0x00ffffff) { |
| 99 DCHECK_GT(static_cast<uint32>(1 << 24), id); | 98 DCHECK_GT(1u << 24, id) << "SPDY setting ID too large."; |
| 100 } | 99 } |
| 101 | 100 |
| 102 uint32 SettingsFlagsAndId::GetWireFormat(int version) const { | 101 uint32 SettingsFlagsAndId::GetWireFormat(int version) const { |
| 103 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); | 102 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); |
| 104 if (version < 3) { | 103 if (version < 3) { |
| 105 ConvertFlagsAndIdForSpdy2(&wire); | 104 ConvertFlagsAndIdForSpdy2(&wire); |
| 106 } | 105 } |
| 107 return wire; | 106 return wire; |
| 108 } | 107 } |
| 109 | 108 |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 case SPDY_IGNORE_REMAINING_PAYLOAD: | 352 case SPDY_IGNORE_REMAINING_PAYLOAD: |
| 354 // control frame has too-large payload | 353 // control frame has too-large payload |
| 355 // intentional fallthrough | 354 // intentional fallthrough |
| 356 case SPDY_FORWARD_STREAM_FRAME: { | 355 case SPDY_FORWARD_STREAM_FRAME: { |
| 357 size_t bytes_read = ProcessDataFramePayload(data, len); | 356 size_t bytes_read = ProcessDataFramePayload(data, len); |
| 358 len -= bytes_read; | 357 len -= bytes_read; |
| 359 data += bytes_read; | 358 data += bytes_read; |
| 360 break; | 359 break; |
| 361 } | 360 } |
| 362 default: | 361 default: |
| 363 LOG(ERROR) << "Invalid value for " << display_protocol_ | 362 LOG(DFATAL) << "Invalid value for " << display_protocol_ |
| 364 << " framer state: " << state_; | 363 << " framer state: " << state_; |
| 365 // This ensures that we don't infinite-loop if state_ gets an | 364 // This ensures that we don't infinite-loop if state_ gets an |
| 366 // invalid value somehow, such as due to a SpdyFramer getting deleted | 365 // invalid value somehow, such as due to a SpdyFramer getting deleted |
| 367 // from a callback it calls. | 366 // from a callback it calls. |
| 368 goto bottom; | 367 goto bottom; |
| 369 } | 368 } |
| 370 } while (state_ != previous_state_); | 369 } while (state_ != previous_state_); |
| 371 bottom: | 370 bottom: |
| 372 DCHECK(len == 0 || state_ == SPDY_ERROR); | 371 DCHECK(len == 0 || state_ == SPDY_ERROR); |
| 373 if (current_frame_len_ == 0 && | 372 if (current_frame_len_ == 0 && |
| 374 remaining_data_ == 0 && | 373 remaining_data_ == 0 && |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 break; | 521 break; |
| 523 case CREDENTIAL: | 522 case CREDENTIAL: |
| 524 if (current_control_frame.length() < | 523 if (current_control_frame.length() < |
| 525 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize) | 524 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize) |
| 526 set_error(SPDY_INVALID_CONTROL_FRAME); | 525 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 527 break; | 526 break; |
| 528 default: | 527 default: |
| 529 LOG(WARNING) << "Valid " << display_protocol_ | 528 LOG(WARNING) << "Valid " << display_protocol_ |
| 530 << " control frame with unhandled type: " | 529 << " control frame with unhandled type: " |
| 531 << current_control_frame.type(); | 530 << current_control_frame.type(); |
| 532 DCHECK(false); | 531 DLOG(FATAL); |
| 533 set_error(SPDY_INVALID_CONTROL_FRAME); | 532 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 534 break; | 533 break; |
| 535 } | 534 } |
| 536 | 535 |
| 537 if (state_ == SPDY_ERROR) { | 536 if (state_ == SPDY_ERROR) { |
| 538 return; | 537 return; |
| 539 } | 538 } |
| 540 | 539 |
| 541 remaining_control_payload_ = current_control_frame.length(); | 540 remaining_control_payload_ = current_control_frame.length(); |
| 542 const size_t total_frame_size = | 541 const size_t total_frame_size = |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 case SETTINGS: | 578 case SETTINGS: |
| 580 frame_size_without_variable_data = SpdySettingsControlFrame::size(); | 579 frame_size_without_variable_data = SpdySettingsControlFrame::size(); |
| 581 break; | 580 break; |
| 582 default: | 581 default: |
| 583 frame_size_without_variable_data = -1; | 582 frame_size_without_variable_data = -1; |
| 584 break; | 583 break; |
| 585 } | 584 } |
| 586 | 585 |
| 587 if ((frame_size_without_variable_data == -1) && | 586 if ((frame_size_without_variable_data == -1) && |
| 588 (total_frame_size > kControlFrameBufferSize)) { | 587 (total_frame_size > kControlFrameBufferSize)) { |
| 588 // We should already be in an error state. Double-check. |
| 589 DCHECK_EQ(SPDY_ERROR, state_); | 589 DCHECK_EQ(SPDY_ERROR, state_); |
| 590 if (state_ != SPDY_ERROR) { | 590 if (state_ != SPDY_ERROR) { |
| 591 LOG(DFATAL) << display_protocol_ | 591 LOG(DFATAL) << display_protocol_ |
| 592 << " control frame buffer too small for fixed-length frame."; | 592 << " control frame buffer too small for fixed-length frame."; |
| 593 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 593 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
| 594 } | 594 } |
| 595 return; | 595 return; |
| 596 } | 596 } |
| 597 if (frame_size_without_variable_data > 0) { | 597 if (frame_size_without_variable_data > 0) { |
| 598 // We have a control frame with a header block. We need to parse the | 598 // We have a control frame with a header block. We need to parse the |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, | 667 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
| 668 size_t len) { | 668 size_t len) { |
| 669 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); | 669 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); |
| 670 size_t original_len = len; | 670 size_t original_len = len; |
| 671 | 671 |
| 672 if (remaining_control_header_ > 0) { | 672 if (remaining_control_header_ > 0) { |
| 673 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, | 673 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, |
| 674 remaining_control_header_); | 674 remaining_control_header_); |
| 675 remaining_control_header_ -= bytes_read; | 675 remaining_control_header_ -= bytes_read; |
| 676 } | 676 } |
| 677 |
| 677 if (remaining_control_header_ == 0) { | 678 if (remaining_control_header_ == 0) { |
| 678 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 679 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
| 679 DCHECK(control_frame.type() == SYN_STREAM || | 680 DCHECK(control_frame.type() == SYN_STREAM || |
| 680 control_frame.type() == SYN_REPLY || | 681 control_frame.type() == SYN_REPLY || |
| 681 control_frame.type() == HEADERS || | 682 control_frame.type() == HEADERS || |
| 682 control_frame.type() == SETTINGS); | 683 control_frame.type() == SETTINGS); |
| 683 visitor_->OnControl(&control_frame); | 684 visitor_->OnControl(&control_frame); |
| 684 | 685 |
| 685 if (control_frame.type() == SETTINGS) { | 686 if (control_frame.type() == SETTINGS) { |
| 686 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); | 687 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 698 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, | 699 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, |
| 699 size_t data_len) { | 700 size_t data_len) { |
| 700 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | 701 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); |
| 701 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 702 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
| 702 | 703 |
| 703 bool processed_successfully = true; | 704 bool processed_successfully = true; |
| 704 DCHECK(control_frame.type() == SYN_STREAM || | 705 DCHECK(control_frame.type() == SYN_STREAM || |
| 705 control_frame.type() == SYN_REPLY || | 706 control_frame.type() == SYN_REPLY || |
| 706 control_frame.type() == HEADERS); | 707 control_frame.type() == HEADERS); |
| 707 size_t process_bytes = std::min(data_len, remaining_control_payload_); | 708 size_t process_bytes = std::min(data_len, remaining_control_payload_); |
| 708 | |
| 709 if (process_bytes > 0) { | 709 if (process_bytes > 0) { |
| 710 if (enable_compression_) { | 710 if (enable_compression_) { |
| 711 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | 711 processed_successfully = IncrementallyDecompressControlFrameHeaderData( |
| 712 &control_frame, data, process_bytes); | 712 &control_frame, data, process_bytes); |
| 713 } else { | 713 } else { |
| 714 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | 714 processed_successfully = IncrementallyDeliverControlFrameHeaderData( |
| 715 &control_frame, data, process_bytes); | 715 &control_frame, data, process_bytes); |
| 716 } | 716 } |
| 717 |
| 717 remaining_control_payload_ -= process_bytes; | 718 remaining_control_payload_ -= process_bytes; |
| 718 remaining_data_ -= process_bytes; | 719 remaining_data_ -= process_bytes; |
| 719 } | 720 } |
| 720 | 721 |
| 721 // Handle the case that there is no futher data in this frame. | 722 // Handle the case that there is no futher data in this frame. |
| 722 if (remaining_control_payload_ == 0 && processed_successfully) { | 723 if (remaining_control_payload_ == 0 && processed_successfully) { |
| 723 // The complete header block has been delivered. We send a zero-length | 724 // The complete header block has been delivered. We send a zero-length |
| 724 // OnControlFrameHeaderData() to indicate this. | 725 // OnControlFrameHeaderData() to indicate this. |
| 725 visitor_->OnControlFrameHeaderData( | 726 visitor_->OnControlFrameHeaderData( |
| 726 GetControlFrameStreamId(&control_frame), NULL, 0); | 727 GetControlFrameStreamId(&control_frame), NULL, 0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 740 } | 741 } |
| 741 | 742 |
| 742 // Return amount processed. | 743 // Return amount processed. |
| 743 return process_bytes; | 744 return process_bytes; |
| 744 } | 745 } |
| 745 | 746 |
| 746 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, | 747 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, |
| 747 size_t data_len) { | 748 size_t data_len) { |
| 748 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); | 749 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); |
| 749 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 750 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
| 750 DCHECK_EQ(control_frame.type(), SETTINGS); | 751 DCHECK_EQ(SETTINGS, control_frame.type()); |
| 751 size_t unprocessed_bytes = std::min(data_len, remaining_control_payload_); | 752 size_t unprocessed_bytes = std::min(data_len, remaining_control_payload_); |
| 752 size_t processed_bytes = 0; | 753 size_t processed_bytes = 0; |
| 753 | 754 |
| 754 // Loop over our incoming data. | 755 // Loop over our incoming data. |
| 755 while (unprocessed_bytes > 0) { | 756 while (unprocessed_bytes > 0) { |
| 756 // Process up to one setting at a time. | 757 // Process up to one setting at a time. |
| 757 size_t processing = std::min( | 758 size_t processing = std::min( |
| 758 unprocessed_bytes, | 759 unprocessed_bytes, |
| 759 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); | 760 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); |
| 760 | 761 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 return len; | 882 return len; |
| 882 } | 883 } |
| 883 | 884 |
| 884 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { | 885 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { |
| 885 size_t original_len = len; | 886 size_t original_len = len; |
| 886 | 887 |
| 887 SpdyDataFrame current_data_frame(current_frame_buffer_.get(), false); | 888 SpdyDataFrame current_data_frame(current_frame_buffer_.get(), false); |
| 888 if (remaining_data_ > 0) { | 889 if (remaining_data_ > 0) { |
| 889 size_t amount_to_forward = std::min(remaining_data_, len); | 890 size_t amount_to_forward = std::min(remaining_data_, len); |
| 890 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { | 891 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { |
| 891 // Only inform the visitor if there is data. | 892 // Only inform the visitor if there is data. |
| 892 if (amount_to_forward) { | 893 if (amount_to_forward) { |
| 893 visitor_->OnStreamFrameData(current_data_frame.stream_id(), | 894 visitor_->OnStreamFrameData(current_data_frame.stream_id(), |
| 894 data, amount_to_forward); | 895 data, amount_to_forward); |
| 895 } | 896 } |
| 896 } | 897 } |
| 897 data += amount_to_forward; | 898 data += amount_to_forward; |
| 898 len -= amount_to_forward; | 899 len -= amount_to_forward; |
| 899 remaining_data_ -= amount_to_forward; | 900 remaining_data_ -= amount_to_forward; |
| 900 | 901 |
| 901 // If the FIN flag is set, and there is no more data in this data | 902 // If the FIN flag is set, and there is no more data in this data |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 for (uint32 index = 0; index < num_headers; ++index) { | 938 for (uint32 index = 0; index < num_headers; ++index) { |
| 938 base::StringPiece temp; | 939 base::StringPiece temp; |
| 939 | 940 |
| 940 // Read header name. | 941 // Read header name. |
| 941 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) | 942 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) |
| 942 : !reader.ReadStringPiece32(&temp)) { | 943 : !reader.ReadStringPiece32(&temp)) { |
| 943 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " | 944 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " |
| 944 << num_headers << ")."; | 945 << num_headers << ")."; |
| 945 return false; | 946 return false; |
| 946 } | 947 } |
| 947 std::string name; | 948 std::string name = temp.as_string(); |
| 948 temp.CopyToString(&name); | |
| 949 | 949 |
| 950 // Read header value. | 950 // Read header value. |
| 951 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) | 951 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) |
| 952 : !reader.ReadStringPiece32(&temp)) { | 952 : !reader.ReadStringPiece32(&temp)) { |
| 953 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " | 953 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " |
| 954 << num_headers << ")."; | 954 << num_headers << ")."; |
| 955 return false; | 955 return false; |
| 956 } | 956 } |
| 957 std::string value; | 957 std::string value = temp.as_string(); |
| 958 temp.CopyToString(&value); | |
| 959 | 958 |
| 960 // Ensure no duplicates. | 959 // Ensure no duplicates. |
| 961 if (block->find(name) != block->end()) { | 960 if (block->find(name) != block->end()) { |
| 962 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " | 961 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " |
| 963 << num_headers << ")."; | 962 << num_headers << ")."; |
| 964 return false; | 963 return false; |
| 965 } | 964 } |
| 966 | 965 |
| 967 // Store header. | 966 // Store header. |
| 968 (*block)[name] = value; | 967 (*block)[name] = value; |
| 969 } | 968 } |
| 970 return true; | 969 return true; |
| 971 } | 970 } |
| 972 | 971 |
| 972 // TODO(hkhalil): Remove, or move to test utils kit. |
| 973 /* static */ | 973 /* static */ |
| 974 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, | 974 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, |
| 975 SettingsMap* settings) { | 975 SettingsMap* settings) { |
| 976 DCHECK_EQ(frame->type(), SETTINGS); | 976 DCHECK_EQ(frame->type(), SETTINGS); |
| 977 DCHECK(settings); | 977 DCHECK(settings); |
| 978 | 978 |
| 979 SpdyFrameReader parser(frame->header_block(), frame->header_block_len()); | 979 SpdyFrameReader parser(frame->header_block(), frame->header_block_len()); |
| 980 for (size_t index = 0; index < frame->num_entries(); ++index) { | 980 for (size_t index = 0; index < frame->num_entries(); ++index) { |
| 981 uint32 id_and_flags_wire; | 981 uint32 id_and_flags_wire; |
| 982 uint32 value; | 982 uint32 value; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1004 | 1004 |
| 1005 SpdyFrameReader parser(data, len); | 1005 SpdyFrameReader parser(data, len); |
| 1006 base::StringPiece temp; | 1006 base::StringPiece temp; |
| 1007 if (!parser.ReadUInt16(&credential->slot)) { | 1007 if (!parser.ReadUInt16(&credential->slot)) { |
| 1008 return false; | 1008 return false; |
| 1009 } | 1009 } |
| 1010 | 1010 |
| 1011 if (!parser.ReadStringPiece32(&temp)) { | 1011 if (!parser.ReadStringPiece32(&temp)) { |
| 1012 return false; | 1012 return false; |
| 1013 } | 1013 } |
| 1014 temp.CopyToString(&credential->proof); | 1014 credential->proof = temp.as_string(); |
| 1015 | 1015 |
| 1016 while (!parser.IsDoneReading()) { | 1016 while (!parser.IsDoneReading()) { |
| 1017 if (!parser.ReadStringPiece32(&temp)) { | 1017 if (!parser.ReadStringPiece32(&temp)) { |
| 1018 return false; | 1018 return false; |
| 1019 } | 1019 } |
| 1020 std::string cert; | 1020 credential->certs.push_back(temp.as_string()); |
| 1021 temp.CopyToString(&cert); | |
| 1022 credential->certs.push_back(cert); | |
| 1023 } | 1021 } |
| 1024 return true; | 1022 return true; |
| 1025 } | 1023 } |
| 1026 | 1024 |
| 1027 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( | 1025 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
| 1028 SpdyStreamId stream_id, | 1026 SpdyStreamId stream_id, |
| 1029 SpdyStreamId associated_stream_id, | 1027 SpdyStreamId associated_stream_id, |
| 1030 SpdyPriority priority, | 1028 SpdyPriority priority, |
| 1031 uint8 credential_slot, | 1029 uint8 credential_slot, |
| 1032 SpdyControlFlags flags, | 1030 SpdyControlFlags flags, |
| 1033 bool compressed, | 1031 bool compressed, |
| 1034 const SpdyHeaderBlock* headers) { | 1032 const SpdyHeaderBlock* headers) { |
| 1035 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1033 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 1036 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); | 1034 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); |
| 1037 | 1035 |
| 1038 // Find our length. | 1036 // Find our length. |
| 1039 size_t frame_size = SpdySynStreamControlFrame::size() + | 1037 size_t frame_size = SpdySynStreamControlFrame::size() + |
| 1040 GetSerializedLength(headers); | 1038 GetSerializedLength(headers); |
| 1041 | 1039 |
| 1042 SpdyFrameBuilder frame(SYN_STREAM, flags, spdy_version_, frame_size); | 1040 SpdyFrameBuilder frame(SYN_STREAM, flags, spdy_version_, frame_size); |
| 1043 frame.WriteUInt32(stream_id); | 1041 frame.WriteUInt32(stream_id); |
| 1044 frame.WriteUInt32(associated_stream_id); | 1042 frame.WriteUInt32(associated_stream_id); |
| 1045 // Cap as appropriate. | 1043 // Cap as appropriate. |
| 1046 if (priority > GetLowestPriority()) { | 1044 if (priority > GetLowestPriority()) { |
| 1047 DLOG(ERROR) << "Priority out-of-bounds."; | 1045 DLOG(DFATAL) << "Priority out-of-bounds."; |
| 1048 priority = GetLowestPriority(); | 1046 priority = GetLowestPriority(); |
| 1049 } | 1047 } |
| 1050 // Priority is 2 bits for <spdy3, 3 bits otherwise. | 1048 // Priority is 2 bits for <spdy3, 3 bits otherwise. |
| 1051 frame.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); | 1049 frame.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
| 1052 frame.WriteUInt8((spdy_version_ < 3) ? 0 : credential_slot); | 1050 frame.WriteUInt8((spdy_version_ < 3) ? 0 : credential_slot); |
| 1053 WriteHeaderBlock(&frame, headers); | 1051 WriteHeaderBlock(&frame, headers); |
| 1054 DCHECK_EQ(frame.length(), frame_size); | 1052 DCHECK_EQ(frame.length(), frame_size); |
| 1055 | 1053 |
| 1056 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | 1054 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
| 1057 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); | 1055 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 SpdyStreamId stream_id, | 1159 SpdyStreamId stream_id, |
| 1162 SpdyControlFlags flags, | 1160 SpdyControlFlags flags, |
| 1163 bool compressed, | 1161 bool compressed, |
| 1164 const SpdyHeaderBlock* headers) { | 1162 const SpdyHeaderBlock* headers) { |
| 1165 // Basically the same as CreateSynReply(). | 1163 // Basically the same as CreateSynReply(). |
| 1166 DCHECK_GT(stream_id, 0u); | 1164 DCHECK_GT(stream_id, 0u); |
| 1167 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1165 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 1168 | 1166 |
| 1169 // Find our length. | 1167 // Find our length. |
| 1170 size_t frame_size = SpdyHeadersControlFrame::size() + | 1168 size_t frame_size = SpdyHeadersControlFrame::size() + |
| 1171 GetSerializedLength(headers); | 1169 GetSerializedLength(headers); |
| 1172 // In SPDY 2, there were 2 unused bytes before payload. | 1170 // In SPDY 2, there were 2 unused bytes before payload. |
| 1173 if (spdy_version_ < 3) { | 1171 if (spdy_version_ < 3) { |
| 1174 frame_size += 2; | 1172 frame_size += 2; |
| 1175 } | 1173 } |
| 1176 | 1174 |
| 1177 SpdyFrameBuilder frame(HEADERS, flags, spdy_version_, frame_size); | 1175 SpdyFrameBuilder frame(HEADERS, flags, spdy_version_, frame_size); |
| 1178 frame.WriteUInt32(stream_id); | 1176 frame.WriteUInt32(stream_id); |
| 1179 if (spdy_version_ < 3) { | 1177 if (spdy_version_ < 3) { |
| 1180 frame.WriteUInt16(0); // Unused | 1178 frame.WriteUInt16(0); // Unused |
| 1181 } | 1179 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 frame.WriteBytes(cert->c_str(), cert->length()); | 1233 frame.WriteBytes(cert->c_str(), cert->length()); |
| 1236 } | 1234 } |
| 1237 DCHECK_EQ(frame.length(), frame_size); | 1235 DCHECK_EQ(frame.length(), frame_size); |
| 1238 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); | 1236 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); |
| 1239 } | 1237 } |
| 1240 | 1238 |
| 1241 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, | 1239 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, |
| 1242 const char* data, | 1240 const char* data, |
| 1243 uint32 len, SpdyDataFlags flags) { | 1241 uint32 len, SpdyDataFlags flags) { |
| 1244 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1242 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 1245 | |
| 1246 size_t frame_size = SpdyDataFrame::size() + len; | 1243 size_t frame_size = SpdyDataFrame::size() + len; |
| 1247 SpdyFrameBuilder frame(stream_id, flags, frame_size); | 1244 SpdyFrameBuilder frame(stream_id, flags, frame_size); |
| 1248 frame.WriteBytes(data, len); | 1245 frame.WriteBytes(data, len); |
| 1249 DCHECK_EQ(frame.length(), frame_size); | 1246 DCHECK_EQ(frame.length(), frame_size); |
| 1250 return reinterpret_cast<SpdyDataFrame*>(frame.take()); | 1247 return reinterpret_cast<SpdyDataFrame*>(frame.take()); |
| 1251 } | 1248 } |
| 1252 | 1249 |
| 1253 // The following compression setting are based on Brian Olson's analysis. See | 1250 // The following compression setting are based on Brian Olson's analysis. See |
| 1254 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 | 1251 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 |
| 1255 // for more details. | 1252 // for more details. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); | 1377 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); |
| 1381 | 1378 |
| 1382 if (!enable_compression_) | 1379 if (!enable_compression_) |
| 1383 return reinterpret_cast<SpdyControlFrame*>(DuplicateFrame(frame)); | 1380 return reinterpret_cast<SpdyControlFrame*>(DuplicateFrame(frame)); |
| 1384 | 1381 |
| 1385 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) | 1382 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) |
| 1386 return NULL; | 1383 return NULL; |
| 1387 | 1384 |
| 1388 // Create an output frame. | 1385 // Create an output frame. |
| 1389 int compressed_max_size = deflateBound(compressor, payload_length); | 1386 int compressed_max_size = deflateBound(compressor, payload_length); |
| 1390 int new_frame_size = header_length + compressed_max_size; | 1387 size_t new_frame_size = header_length + compressed_max_size; |
| 1391 if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) && | 1388 if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) && |
| 1392 spdy_version_ < 3) { | 1389 spdy_version_ < 3) { |
| 1393 new_frame_size += 2; | 1390 new_frame_size += 2; |
| 1394 } | 1391 } |
| 1395 DCHECK_GE(new_frame_size, | 1392 DCHECK_GE(new_frame_size, frame.length() + SpdyFrame::kHeaderSize); |
| 1396 static_cast<int>(frame.length() + SpdyFrame::kHeaderSize)); | |
| 1397 scoped_ptr<SpdyControlFrame> new_frame(new SpdyControlFrame(new_frame_size)); | 1393 scoped_ptr<SpdyControlFrame> new_frame(new SpdyControlFrame(new_frame_size)); |
| 1398 memcpy(new_frame->data(), frame.data(), | 1394 memcpy(new_frame->data(), frame.data(), |
| 1399 frame.length() + SpdyFrame::kHeaderSize); | 1395 frame.length() + SpdyFrame::kHeaderSize); |
| 1400 | 1396 |
| 1401 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); | 1397 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); |
| 1402 compressor->avail_in = payload_length; | 1398 compressor->avail_in = payload_length; |
| 1403 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + | 1399 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + |
| 1404 header_length; | 1400 header_length; |
| 1405 compressor->avail_out = compressed_max_size; | 1401 compressor->avail_out = compressed_max_size; |
| 1406 | 1402 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1577 case HEADERS: | 1573 case HEADERS: |
| 1578 return SpdyHeadersControlFrame::size(); | 1574 return SpdyHeadersControlFrame::size(); |
| 1579 case WINDOW_UPDATE: | 1575 case WINDOW_UPDATE: |
| 1580 return SpdyWindowUpdateControlFrame::size(); | 1576 return SpdyWindowUpdateControlFrame::size(); |
| 1581 case CREDENTIAL: | 1577 case CREDENTIAL: |
| 1582 return SpdyCredentialControlFrame::size(); | 1578 return SpdyCredentialControlFrame::size(); |
| 1583 case NUM_CONTROL_FRAME_TYPES: | 1579 case NUM_CONTROL_FRAME_TYPES: |
| 1584 break; | 1580 break; |
| 1585 } | 1581 } |
| 1586 LOG(ERROR) << "Unknown control frame type " << type; | 1582 LOG(ERROR) << "Unknown control frame type " << type; |
| 1587 return 0x7FFFFFFF; // Max signed 32bit int | 1583 return std::numeric_limits<size_t>::max(); |
| 1588 } | 1584 } |
| 1589 | 1585 |
| 1590 /* static */ | 1586 /* static */ |
| 1591 SpdyStreamId SpdyFramer::GetControlFrameStreamId( | 1587 SpdyStreamId SpdyFramer::GetControlFrameStreamId( |
| 1592 const SpdyControlFrame* control_frame) { | 1588 const SpdyControlFrame* control_frame) { |
| 1593 SpdyStreamId stream_id = kInvalidStream; | 1589 SpdyStreamId stream_id = kInvalidStream; |
| 1594 if (control_frame != NULL) { | 1590 if (control_frame != NULL) { |
| 1595 switch (control_frame->type()) { | 1591 switch (control_frame->type()) { |
| 1596 case SYN_STREAM: | 1592 case SYN_STREAM: |
| 1597 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( | 1593 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 | 1627 |
| 1632 void SpdyFramer::set_enable_compression(bool value) { | 1628 void SpdyFramer::set_enable_compression(bool value) { |
| 1633 enable_compression_ = value; | 1629 enable_compression_ = value; |
| 1634 } | 1630 } |
| 1635 | 1631 |
| 1636 void SpdyFramer::set_enable_compression_default(bool value) { | 1632 void SpdyFramer::set_enable_compression_default(bool value) { |
| 1637 g_enable_compression_default = value; | 1633 g_enable_compression_default = value; |
| 1638 } | 1634 } |
| 1639 | 1635 |
| 1640 } // namespace net | 1636 } // namespace net |
| OLD | NEW |