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 #include "net/spdy/core/spdy_framer.h" | 5 #include "net/spdy/core/spdy_framer.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cctype> | 10 #include <cctype> |
11 #include <ios> | 11 #include <ios> |
12 #include <iterator> | 12 #include <iterator> |
13 #include <list> | 13 #include <list> |
14 #include <new> | 14 #include <new> |
15 #include <vector> | |
16 | 15 |
17 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
18 #include "base/logging.h" | 17 #include "base/logging.h" |
19 #include "base/metrics/histogram_macros.h" | 18 #include "base/metrics/histogram_macros.h" |
20 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
21 #include "net/quic/platform/api/quic_flags.h" | 20 #include "net/quic/platform/api/quic_flags.h" |
22 #include "net/spdy/chromium/spdy_flags.h" | 21 #include "net/spdy/chromium/spdy_flags.h" |
23 #include "net/spdy/core/hpack/hpack_constants.h" | 22 #include "net/spdy/core/hpack/hpack_constants.h" |
24 #include "net/spdy/core/hpack/hpack_decoder.h" | 23 #include "net/spdy/core/hpack/hpack_decoder.h" |
25 #include "net/spdy/core/hpack/hpack_decoder3.h" | 24 #include "net/spdy/core/hpack/hpack_decoder3.h" |
26 #include "net/spdy/core/http2_frame_decoder_adapter.h" | 25 #include "net/spdy/core/http2_frame_decoder_adapter.h" |
27 #include "net/spdy/core/spdy_bitmasks.h" | 26 #include "net/spdy/core/spdy_bitmasks.h" |
28 #include "net/spdy/core/spdy_bug_tracker.h" | 27 #include "net/spdy/core/spdy_bug_tracker.h" |
29 #include "net/spdy/core/spdy_frame_builder.h" | 28 #include "net/spdy/core/spdy_frame_builder.h" |
30 #include "net/spdy/core/spdy_frame_reader.h" | 29 #include "net/spdy/core/spdy_frame_reader.h" |
31 #include "net/spdy/core/spdy_framer_decoder_adapter.h" | 30 #include "net/spdy/core/spdy_framer_decoder_adapter.h" |
32 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h" | 31 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h" |
33 #include "net/spdy/platform/api/spdy_ptr_util.h" | 32 #include "net/spdy/platform/api/spdy_ptr_util.h" |
34 #include "net/spdy/platform/api/spdy_string_utils.h" | 33 #include "net/spdy/platform/api/spdy_string_utils.h" |
35 | 34 |
36 using std::vector; | |
37 | |
38 namespace net { | 35 namespace net { |
39 | 36 |
40 namespace { | 37 namespace { |
41 | 38 |
42 // Pack parent stream ID and exclusive flag into the format used by HTTP/2 | 39 // Pack parent stream ID and exclusive flag into the format used by HTTP/2 |
43 // headers and priority frames. | 40 // headers and priority frames. |
44 uint32_t PackStreamDependencyValues(bool exclusive, | 41 uint32_t PackStreamDependencyValues(bool exclusive, |
45 SpdyStreamId parent_stream_id) { | 42 SpdyStreamId parent_stream_id) { |
46 // Make sure the highest-order bit in the parent stream id is zeroed out. | 43 // Make sure the highest-order bit in the parent stream id is zeroed out. |
47 uint32_t parent = parent_stream_id & 0x7fffffff; | 44 uint32_t parent = parent_stream_id & 0x7fffffff; |
(...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1015 expect_continuation_ = current_frame_stream_id_; | 1012 expect_continuation_ = current_frame_stream_id_; |
1016 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; | 1013 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; |
1017 } | 1014 } |
1018 if (current_frame_flags_ & HEADERS_FLAG_PADDED) { | 1015 if (current_frame_flags_ & HEADERS_FLAG_PADDED) { |
1019 uint8_t pad_payload_len = 0; | 1016 uint8_t pad_payload_len = 0; |
1020 DCHECK_EQ(remaining_padding_payload_length_, 0u); | 1017 DCHECK_EQ(remaining_padding_payload_length_, 0u); |
1021 successful_read = reader.ReadUInt8(&pad_payload_len); | 1018 successful_read = reader.ReadUInt8(&pad_payload_len); |
1022 DCHECK(successful_read); | 1019 DCHECK(successful_read); |
1023 remaining_padding_payload_length_ = pad_payload_len; | 1020 remaining_padding_payload_length_ = pad_payload_len; |
1024 } | 1021 } |
1025 const bool has_priority = | |
1026 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; | |
1027 int weight = 0; | 1022 int weight = 0; |
1028 uint32_t parent_stream_id = 0; | 1023 uint32_t parent_stream_id = 0; |
1029 bool exclusive = false; | 1024 bool exclusive = false; |
1030 if (has_priority) { | 1025 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) { |
1031 uint32_t stream_dependency; | 1026 uint32_t stream_dependency; |
1032 successful_read = reader.ReadUInt32(&stream_dependency); | 1027 successful_read = reader.ReadUInt32(&stream_dependency); |
1033 DCHECK(successful_read); | 1028 DCHECK(successful_read); |
1034 UnpackStreamDependencyValues(stream_dependency, &exclusive, | 1029 UnpackStreamDependencyValues(stream_dependency, &exclusive, |
1035 &parent_stream_id); | 1030 &parent_stream_id); |
1036 | 1031 |
1037 uint8_t serialized_weight = 0; | 1032 uint8_t serialized_weight = 0; |
1038 successful_read = reader.ReadUInt8(&serialized_weight); | 1033 successful_read = reader.ReadUInt8(&serialized_weight); |
1039 if (successful_read) { | 1034 if (successful_read) { |
1040 // Per RFC 7540 section 6.3, serialized weight value is actual | 1035 // Per RFC 7540 section 6.3, serialized weight value is actual |
1041 // value - 1. | 1036 // value - 1. |
1042 weight = serialized_weight + 1; | 1037 weight = serialized_weight + 1; |
1043 } | 1038 } |
1044 } | 1039 } |
1045 DCHECK(reader.IsDoneReading()); | 1040 DCHECK(reader.IsDoneReading()); |
1046 if (debug_visitor_) { | 1041 if (debug_visitor_) { |
1047 debug_visitor_->OnReceiveCompressedFrame(current_frame_stream_id_, | 1042 debug_visitor_->OnReceiveCompressedFrame(current_frame_stream_id_, |
1048 current_frame_type_, | 1043 current_frame_type_, |
1049 current_frame_length_); | 1044 current_frame_length_); |
1050 } | 1045 } |
1051 visitor_->OnHeaders(current_frame_stream_id_, | 1046 visitor_->OnHeaders(current_frame_stream_id_, |
1052 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, | 1047 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, |
1053 weight, parent_stream_id, exclusive, | 1048 weight, parent_stream_id, exclusive, |
1054 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, | 1049 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, |
1055 expect_continuation_ == 0); | 1050 expect_continuation_ == 0); |
1051 } break; | |
Biren Roy
2017/05/24 15:25:09
This line looks weird, but I see it's the same in
Bence
2017/05/24 15:38:48
Yeah, I agree. Maybe if I move all local variable
| |
1052 case SpdyFrameType::PUSH_PROMISE: { | |
1053 if (current_frame_stream_id_ == 0) { | |
1054 set_error(SPDY_INVALID_CONTROL_FRAME); | |
1055 return original_len - len; | |
1056 } | 1056 } |
1057 break; | 1057 bool successful_read = true; |
1058 case SpdyFrameType::PUSH_PROMISE: { | 1058 if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) { |
1059 if (current_frame_stream_id_ == 0) { | 1059 DCHECK_EQ(remaining_padding_payload_length_, 0u); |
1060 set_error(SPDY_INVALID_CONTROL_FRAME); | 1060 uint8_t pad_payload_len = 0; |
1061 return original_len - len; | 1061 successful_read = reader.ReadUInt8(&pad_payload_len); |
1062 } | 1062 DCHECK(successful_read); |
1063 bool successful_read = true; | 1063 remaining_padding_payload_length_ = pad_payload_len; |
1064 if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) { | |
1065 DCHECK_EQ(remaining_padding_payload_length_, 0u); | |
1066 uint8_t pad_payload_len = 0; | |
1067 successful_read = reader.ReadUInt8(&pad_payload_len); | |
1068 DCHECK(successful_read); | |
1069 remaining_padding_payload_length_ = pad_payload_len; | |
1070 } | |
1071 } | 1064 } |
1072 { | 1065 SpdyStreamId promised_stream_id = kInvalidStream; |
1073 SpdyStreamId promised_stream_id = kInvalidStream; | 1066 successful_read = reader.ReadUInt31(&promised_stream_id); |
1074 bool successful_read = reader.ReadUInt31(&promised_stream_id); | 1067 DCHECK(successful_read); |
1075 DCHECK(successful_read); | 1068 DCHECK(reader.IsDoneReading()); |
1076 DCHECK(reader.IsDoneReading()); | 1069 if (promised_stream_id == 0) { |
1077 if (promised_stream_id == 0) { | 1070 set_error(SPDY_INVALID_CONTROL_FRAME); |
1078 set_error(SPDY_INVALID_CONTROL_FRAME); | 1071 return original_len - len; |
1079 return original_len - len; | |
1080 } | |
1081 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) { | |
1082 expect_continuation_ = current_frame_stream_id_; | |
1083 } | |
1084 if (debug_visitor_) { | |
1085 debug_visitor_->OnReceiveCompressedFrame( | |
1086 current_frame_stream_id_, | |
1087 current_frame_type_, | |
1088 current_frame_length_); | |
1089 } | |
1090 visitor_->OnPushPromise(current_frame_stream_id_, | |
1091 promised_stream_id, | |
1092 (current_frame_flags_ & | |
1093 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); | |
1094 } | 1072 } |
1095 break; | 1073 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) { |
1096 case SpdyFrameType::CONTINUATION: { | 1074 expect_continuation_ = current_frame_stream_id_; |
1097 // Check to make sure the stream id of the current frame is | |
1098 // the same as that of the preceding frame. | |
1099 // If we're at this point we should already know that | |
1100 // expect_continuation_ != 0, so this doubles as a check | |
1101 // that current_frame_stream_id != 0. | |
1102 if (current_frame_stream_id_ != expect_continuation_) { | |
1103 set_error(SPDY_UNEXPECTED_FRAME); | |
1104 return original_len - len; | |
1105 } | |
1106 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) { | |
1107 expect_continuation_ = 0; | |
1108 } | |
1109 if (debug_visitor_) { | |
1110 debug_visitor_->OnReceiveCompressedFrame( | |
1111 current_frame_stream_id_, | |
1112 current_frame_type_, | |
1113 current_frame_length_); | |
1114 } | |
1115 visitor_->OnContinuation(current_frame_stream_id_, | |
1116 (current_frame_flags_ & | |
1117 HEADERS_FLAG_END_HEADERS) != 0); | |
1118 } | 1075 } |
1119 break; | 1076 if (debug_visitor_) { |
1077 debug_visitor_->OnReceiveCompressedFrame(current_frame_stream_id_, | |
1078 current_frame_type_, | |
1079 current_frame_length_); | |
1080 } | |
1081 visitor_->OnPushPromise( | |
1082 current_frame_stream_id_, promised_stream_id, | |
1083 (current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); | |
1084 } break; | |
1085 case SpdyFrameType::CONTINUATION: { | |
1086 // Check to make sure the stream id of the current frame is | |
1087 // the same as that of the preceding frame. | |
1088 // If we're at this point we should already know that | |
1089 // expect_continuation_ != 0, so this doubles as a check | |
1090 // that current_frame_stream_id != 0. | |
1091 if (current_frame_stream_id_ != expect_continuation_) { | |
1092 set_error(SPDY_UNEXPECTED_FRAME); | |
1093 return original_len - len; | |
1094 } | |
1095 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) { | |
1096 expect_continuation_ = 0; | |
1097 } | |
1098 if (debug_visitor_) { | |
1099 debug_visitor_->OnReceiveCompressedFrame(current_frame_stream_id_, | |
1100 current_frame_type_, | |
1101 current_frame_length_); | |
1102 } | |
1103 visitor_->OnContinuation( | |
1104 current_frame_stream_id_, | |
1105 (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) != 0); | |
1106 } break; | |
1120 default: | 1107 default: |
1121 #ifndef NDEBUG | 1108 #ifndef NDEBUG |
1122 LOG(FATAL) << "Invalid control frame type: " << current_frame_type_; | 1109 LOG(FATAL) << "Invalid control frame type: " << current_frame_type_; |
1123 #else | 1110 #else |
1124 set_error(SPDY_INVALID_CONTROL_FRAME); | 1111 set_error(SPDY_INVALID_CONTROL_FRAME); |
1125 return original_len - len; | 1112 return original_len - len; |
1126 #endif | 1113 #endif |
1127 } | 1114 } |
1128 | 1115 |
1129 if (current_frame_type_ != SpdyFrameType::CONTINUATION) { | 1116 if (current_frame_type_ != SpdyFrameType::CONTINUATION) { |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1614 ? GetFrameSizeSansBlock() | 1601 ? GetFrameSizeSansBlock() |
1615 : framer_->GetContinuationMinimumSize(); | 1602 : framer_->GetContinuationMinimumSize(); |
1616 auto encoding = SpdyMakeUnique<SpdyString>(); | 1603 auto encoding = SpdyMakeUnique<SpdyString>(); |
1617 encoder_->Next(kMaxControlFrameSize - size_without_block, encoding.get()); | 1604 encoder_->Next(kMaxControlFrameSize - size_without_block, encoding.get()); |
1618 has_next_frame_ = encoder_->HasNext(); | 1605 has_next_frame_ = encoder_->HasNext(); |
1619 | 1606 |
1620 if (framer_->debug_visitor_ != nullptr) { | 1607 if (framer_->debug_visitor_ != nullptr) { |
1621 debug_total_size_ += size_without_block; | 1608 debug_total_size_ += size_without_block; |
1622 debug_total_size_ += encoding->size(); | 1609 debug_total_size_ += encoding->size(); |
1623 if (!has_next_frame_) { | 1610 if (!has_next_frame_) { |
1624 auto* header_block_frame_ir = | |
1625 static_cast<const SpdyFrameWithHeaderBlockIR*>(frame_ir); | |
1626 // TODO(birenroy) are these (here and below) still necessary? | 1611 // TODO(birenroy) are these (here and below) still necessary? |
1627 // HTTP2 uses HPACK for header compression. However, continue to | 1612 // HTTP2 uses HPACK for header compression. However, continue to |
1628 // use GetSerializedLength() for an apples-to-apples comparision of | 1613 // use GetSerializedLength() for an apples-to-apples comparision of |
1629 // compression performance between HPACK and SPDY w/ deflate. | 1614 // compression performance between HPACK and SPDY w/ deflate. |
1615 auto* header_block_frame_ir = | |
1616 static_cast<const SpdyFrameWithHeaderBlockIR*>(frame_ir); | |
1630 size_t debug_payload_len = | 1617 size_t debug_payload_len = |
1631 framer_->GetSerializedLength(&header_block_frame_ir->header_block()); | 1618 framer_->GetSerializedLength(&header_block_frame_ir->header_block()); |
1632 framer_->debug_visitor_->OnSendCompressedFrame( | 1619 framer_->debug_visitor_->OnSendCompressedFrame( |
1633 frame_ir->stream_id(), frame_ir->frame_type(), debug_payload_len, | 1620 frame_ir->stream_id(), frame_ir->frame_type(), debug_payload_len, |
1634 debug_total_size_); | 1621 debug_total_size_); |
1635 } | 1622 } |
1636 } | 1623 } |
1637 | 1624 |
1638 framer_->SetIsLastFrame(!has_next_frame_); | 1625 framer_->SetIsLastFrame(!has_next_frame_); |
1639 const size_t free_bytes_before = output->BytesFree(); | 1626 const size_t free_bytes_before = output->BytesFree(); |
(...skipping 1197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2837 if (hpack_decoder_.get() == nullptr) { | 2824 if (hpack_decoder_.get() == nullptr) { |
2838 if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3) { | 2825 if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3) { |
2839 hpack_decoder_ = SpdyMakeUnique<HpackDecoder3>(); | 2826 hpack_decoder_ = SpdyMakeUnique<HpackDecoder3>(); |
2840 } else { | 2827 } else { |
2841 hpack_decoder_ = SpdyMakeUnique<HpackDecoder>(); | 2828 hpack_decoder_ = SpdyMakeUnique<HpackDecoder>(); |
2842 } | 2829 } |
2843 } | 2830 } |
2844 return hpack_decoder_.get(); | 2831 return hpack_decoder_.get(); |
2845 } | 2832 } |
2846 | 2833 |
2847 void SpdyFramer::SetDecoderHeaderTableDebugVisitor( | |
2848 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) { | |
2849 if (decoder_adapter_ != nullptr) { | |
2850 decoder_adapter_->SetDecoderHeaderTableDebugVisitor(std::move(visitor)); | |
2851 } else { | |
2852 GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor)); | |
2853 } | |
2854 } | |
2855 | |
2856 void SpdyFramer::SetEncoderHeaderTableDebugVisitor( | |
2857 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) { | |
2858 GetHpackEncoder()->SetHeaderTableDebugVisitor(std::move(visitor)); | |
2859 } | |
2860 | |
2861 size_t SpdyFramer::EstimateMemoryUsage() const { | |
2862 return SpdyEstimateMemoryUsage(current_frame_buffer_) + | |
2863 SpdyEstimateMemoryUsage(settings_scratch_) + | |
2864 SpdyEstimateMemoryUsage(altsvc_scratch_) + | |
2865 SpdyEstimateMemoryUsage(hpack_encoder_) + | |
2866 SpdyEstimateMemoryUsage(hpack_decoder_) + | |
2867 SpdyEstimateMemoryUsage(decoder_adapter_); | |
2868 } | |
2869 | |
2870 void SpdyFramer::UpdateHeaderEncoderTableSize(uint32_t value) { | 2834 void SpdyFramer::UpdateHeaderEncoderTableSize(uint32_t value) { |
2871 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value); | 2835 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value); |
2872 } | 2836 } |
2873 | 2837 |
2874 void SpdyFramer::UpdateHeaderDecoderTableSize(uint32_t value) { | 2838 void SpdyFramer::UpdateHeaderDecoderTableSize(uint32_t value) { |
2875 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value); | 2839 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value); |
2876 } | 2840 } |
2877 | 2841 |
2878 size_t SpdyFramer::header_encoder_table_size() const { | 2842 size_t SpdyFramer::header_encoder_table_size() const { |
2879 if (hpack_encoder_ == nullptr) { | 2843 if (hpack_encoder_ == nullptr) { |
2880 return kDefaultHeaderTableSizeSetting; | 2844 return kDefaultHeaderTableSizeSetting; |
2881 } else { | 2845 } else { |
2882 return hpack_encoder_->CurrentHeaderTableSizeSetting(); | 2846 return hpack_encoder_->CurrentHeaderTableSizeSetting(); |
2883 } | 2847 } |
2884 } | 2848 } |
2885 | 2849 |
2886 void SpdyFramer::SerializeHeaderBlockWithoutCompression( | 2850 void SpdyFramer::SerializeHeaderBlockWithoutCompression( |
2887 SpdyFrameBuilder* builder, | 2851 SpdyFrameBuilder* builder, |
2888 const SpdyHeaderBlock& header_block) const { | 2852 const SpdyHeaderBlock& header_block) const { |
2889 // Serialize number of headers. | 2853 // Serialize number of headers. |
2890 builder->WriteUInt32(header_block.size()); | 2854 builder->WriteUInt32(header_block.size()); |
2891 | 2855 |
2892 // Serialize each header. | 2856 // Serialize each header. |
2893 for (const auto& header : header_block) { | 2857 for (const auto& header : header_block) { |
2894 builder->WriteStringPiece32(base::ToLowerASCII(header.first)); | 2858 builder->WriteStringPiece32(base::ToLowerASCII(header.first)); |
2895 builder->WriteStringPiece32(header.second); | 2859 builder->WriteStringPiece32(header.second); |
2896 } | 2860 } |
2897 } | 2861 } |
2898 | 2862 |
2863 void SpdyFramer::SetDecoderHeaderTableDebugVisitor( | |
2864 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) { | |
2865 if (decoder_adapter_ != nullptr) { | |
2866 decoder_adapter_->SetDecoderHeaderTableDebugVisitor(std::move(visitor)); | |
2867 } else { | |
2868 GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor)); | |
2869 } | |
2870 } | |
2871 | |
2872 void SpdyFramer::SetEncoderHeaderTableDebugVisitor( | |
2873 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) { | |
2874 GetHpackEncoder()->SetHeaderTableDebugVisitor(std::move(visitor)); | |
2875 } | |
2876 | |
2877 size_t SpdyFramer::EstimateMemoryUsage() const { | |
2878 return SpdyEstimateMemoryUsage(current_frame_buffer_) + | |
2879 SpdyEstimateMemoryUsage(settings_scratch_) + | |
2880 SpdyEstimateMemoryUsage(altsvc_scratch_) + | |
2881 SpdyEstimateMemoryUsage(hpack_encoder_) + | |
2882 SpdyEstimateMemoryUsage(hpack_decoder_) + | |
2883 SpdyEstimateMemoryUsage(decoder_adapter_); | |
2884 } | |
2885 | |
2899 } // namespace net | 2886 } // namespace net |
OLD | NEW |