diff options
author | jgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-20 03:05:07 +0000 |
---|---|---|
committer | jgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-20 03:05:07 +0000 |
commit | cc279a331b3e8c803b8b63adbeecd2f5f8307ec3 (patch) | |
tree | 5d124feba45ac474d791984c61d46cc7db74bb30 /net/spdy | |
parent | 910ee638672e31050f57917084de07d39da54839 (diff) | |
download | chromium_src-cc279a331b3e8c803b8b63adbeecd2f5f8307ec3.zip chromium_src-cc279a331b3e8c803b8b63adbeecd2f5f8307ec3.tar.gz chromium_src-cc279a331b3e8c803b8b63adbeecd2f5f8307ec3.tar.bz2 |
Initial support for HTTP/2 dependencies and weights.
A non-exclusive root dependency is always emitted, and parsed
dependencies are ignored. Weights are mapped to existing SPDY
priorities, and vice versa.
BUG=345769
Review URL: https://codereview.chromium.org/287003011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271555 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy')
-rw-r--r-- | net/spdy/spdy_framer.cc | 46 | ||||
-rw-r--r-- | net/spdy/spdy_framer.h | 5 | ||||
-rw-r--r-- | net/spdy/spdy_framer_test.cc | 73 |
3 files changed, 94 insertions, 30 deletions
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index 79a529f..af2c8b7 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc @@ -47,6 +47,10 @@ base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; // Used to indicate no flags in a SPDY flags field. const uint8 kNoFlags = 0; +// Wire sizes of priority payloads. +const size_t kPriorityDependencyPayloadSize = 4; +const size_t kPriorityWeightPayloadSize = 1; + } // namespace const SpdyStreamId SpdyFramer::kInvalidStream = -1; @@ -183,9 +187,9 @@ size_t SpdyFramer::GetSynStreamMinimumSize() const { // + 1 (unused, was credential slot) return GetControlFrameHeaderSize() + 10; } else { - // Calculated as: - // frame prefix + 4 (priority) - return GetControlFrameHeaderSize() + 4; + return GetControlFrameHeaderSize() + + kPriorityDependencyPayloadSize + + kPriorityWeightPayloadSize; } } @@ -323,8 +327,9 @@ size_t SpdyFramer::GetAltSvcMinimumSize() const { size_t SpdyFramer::GetPrioritySize() const { // Size, in bytes, of a PRIORITY frame. - // Calculated as frame prefix + 4 (stream dependency) + 1 (weight) - return GetControlFrameHeaderSize() + 5; + return GetControlFrameHeaderSize() + + kPriorityDependencyPayloadSize + + kPriorityWeightPayloadSize; } size_t SpdyFramer::GetFrameMinimumSize() const { @@ -1047,7 +1052,9 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { frame_size_without_variable_data = GetHeadersMinimumSize(); if (protocol_version() > SPDY3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) { - frame_size_without_variable_data += 4; // priority + frame_size_without_variable_data += + kPriorityDependencyPayloadSize + + kPriorityWeightPayloadSize; } break; case PUSH_PROMISE: @@ -1414,8 +1421,13 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; uint32 priority = 0; if (protocol_version() > SPDY3 && has_priority) { - successful_read = reader.ReadUInt31(&priority); - DCHECK(successful_read); + // TODO(jgraettinger): Process dependency rather than ignoring it. + reader.Seek(kPriorityDependencyPayloadSize); + uint8 weight = 0; + successful_read = reader.ReadUInt8(&weight); + if (successful_read) { + priority = MapWeightToPriority(weight); + } } DCHECK(reader.IsDoneReading()); if (debug_visitor_) { @@ -2376,7 +2388,9 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream( HEADERS, flags, syn_stream.stream_id()); - builder.WriteUInt32(priority); + // TODO(jgraettinger): Plumb priorities and stream dependencies. + builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. + builder.WriteUInt8(MapPriorityToWeight(priority)); } DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); if (protocol_version() > SPDY3) { @@ -2664,7 +2678,9 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders( flags, headers.stream_id()); if (headers.has_priority()) { - builder.WriteUInt32(priority); + // TODO(jgraettinger): Plumb priorities and stream dependencies. + builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. + builder.WriteUInt8(MapPriorityToWeight(priority)); } } if (protocol_version() <= SPDY2) { @@ -3055,6 +3071,16 @@ HpackDecoder* SpdyFramer::GetHpackDecoder() { return hpack_decoder_.get(); } +uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) { + const float kSteps = 255.9f / 7.f; + return static_cast<uint8>(kSteps * (7.f - priority)); +} + +SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) { + const float kSteps = 255.9f / 7.f; + return static_cast<SpdyPriority>(7.f - weight / kSteps); +} + // Incrementally decompress the control frame's header block, feeding the // result to the visitor in chunks. Continue this until the visitor // indicates that it cannot process any more data, or (more commonly) we diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index dd657a5..2184234 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h @@ -559,6 +559,11 @@ class NET_EXPORT_PRIVATE SpdyFramer { SpdyPriority GetHighestPriority() const { return 0; } + // Interpolates SpdyPriority values into SPDY4/HTTP2 priority weights, + // and vice versa. + uint8 MapPriorityToWeight(SpdyPriority priority); + SpdyPriority MapWeightToPriority(uint8 weight); + // Deliver the given control frame's compressed headers block to the visitor // in decompressed form, in chunks. Returns true if the visitor has // accepted all of the chunks. diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 78cb0cd..cd3e5e3 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc @@ -839,7 +839,8 @@ TEST_P(SpdyFramerTest, MultiValueHeader) { HEADERS, HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, 3); - frame.WriteUInt32(framer.GetHighestPriority()); + frame.WriteUInt32(0); // Priority exclusivity and dependent stream. + frame.WriteUInt8(255); // Priority weight. } string value("value1\0value2", 13); @@ -1876,14 +1877,14 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) { 'a', 'r' }; const unsigned char kV4FrameData[] = { - 0x00, 0x16, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS + 0x00, 0x17, 0x01, 0x24, // HEADERS: PRIORITY | END_HEADERS 0x00, 0x00, 0x00, 0x01, // Stream 1 - 0x00, 0x00, 0x00, 0x07, // Priority 7 - 0x00, 0x03, 0x62, 0x61, // @.ba - 0x72, 0x03, 0x66, 0x6f, // r.fo - 0x6f, 0x00, 0x03, 0x66, // o@.f - 0x6f, 0x6f, 0x03, 0x62, // oo.b - 0x61, 0x72, // ar + 0x00, 0x00, 0x00, 0x00, // Non-exclusive dependency 0. Weight 0. + 0x00, 0x00, 0x03, 0x62, + 0x61, 0x72, 0x03, 0x66, + 0x6f, 0x6f, 0x00, 0x03, + 0x66, 0x6f, 0x6f, 0x03, + 0x62, 0x61, 0x72, }; SpdySynStreamIR syn_stream(1); syn_stream.set_priority(framer.GetLowestPriority()); @@ -1931,13 +1932,13 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) { 'b', 'a', 'r' }; const unsigned char kV4FrameData[] = { - 0x00, 0x13, 0x01, 0x25, // HEADERS: PRIORITY | FIN | END_HEADERS + 0x00, 0x14, 0x01, 0x25, // HEADERS: PRIORITY | FIN | END_HEADERS 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff - 0x00, 0x00, 0x00, 0x00, // Priority 0 - 0x00, 0x00, 0x03, 0x66, // @..f - 0x6f, 0x6f, 0x00, 0x03, // oo@. - 0x66, 0x6f, 0x6f, 0x03, // foo. - 0x62, 0x61, 0x72, // bar + 0x00, 0x00, 0x00, 0x00, // Non-exclusive dependency 0. Weight 255. + 0xff, 0x00, 0x00, 0x03, + 0x66, 0x6f, 0x6f, 0x00, + 0x03, 0x66, 0x6f, 0x6f, + 0x03, 0x62, 0x61, 0x72, }; SpdySynStreamIR syn_stream(0x7fffffff); syn_stream.set_associated_to_stream_id(0x7fffffff); @@ -1988,13 +1989,13 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) { 0x00, 0x00, 0x00 }; const unsigned char kV4FrameData[] = { - 0x00, 0x13, 0x01, 0x25, // HEADERS: PRIORITY | FIN | END_HEADERS + 0x00, 0x14, 0x01, 0x25, // HEADERS: PRIORITY | FIN | END_HEADERS 0x7f, 0xff, 0xff, 0xff, // Stream 0x7fffffff - 0x00, 0x00, 0x00, 0x01, // Priority 1 - 0x00, 0x03, 0x62, 0x61, // @.ba - 0x72, 0x03, 0x66, 0x6f, // r.fo - 0x6f, 0x00, 0x03, 0x66, // o@.f - 0x6f, 0x6f, 0x00, // oo. + 0x00, 0x00, 0x00, 0x00, // Non-exclusive dependency 0. Weight 219. + 0xdb, 0x00, 0x03, 0x62, + 0x61, 0x72, 0x03, 0x66, + 0x6f, 0x6f, 0x00, 0x03, + 0x66, 0x6f, 0x6f, 0x00, }; SpdySynStreamIR syn_stream(0x7fffffff); syn_stream.set_associated_to_stream_id(0x7fffffff); @@ -5396,4 +5397,36 @@ TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) { << SpdyFramer::ErrorCodeToString(visitor.framer_.error_code()); } +TEST_P(SpdyFramerTest, PriorityWeightMapping) { + if (spdy_version_ <= SPDY3) { + return; + } + SpdyFramer framer(spdy_version_); + + EXPECT_EQ(255u, framer.MapPriorityToWeight(0)); + EXPECT_EQ(219u, framer.MapPriorityToWeight(1)); + EXPECT_EQ(182u, framer.MapPriorityToWeight(2)); + EXPECT_EQ(146u, framer.MapPriorityToWeight(3)); + EXPECT_EQ(109u, framer.MapPriorityToWeight(4)); + EXPECT_EQ(73u, framer.MapPriorityToWeight(5)); + EXPECT_EQ(36u, framer.MapPriorityToWeight(6)); + EXPECT_EQ(0u, framer.MapPriorityToWeight(7)); + + EXPECT_EQ(0u, framer.MapWeightToPriority(255)); + EXPECT_EQ(0u, framer.MapWeightToPriority(220)); + EXPECT_EQ(1u, framer.MapWeightToPriority(219)); + EXPECT_EQ(1u, framer.MapWeightToPriority(183)); + EXPECT_EQ(2u, framer.MapWeightToPriority(182)); + EXPECT_EQ(2u, framer.MapWeightToPriority(147)); + EXPECT_EQ(3u, framer.MapWeightToPriority(146)); + EXPECT_EQ(3u, framer.MapWeightToPriority(110)); + EXPECT_EQ(4u, framer.MapWeightToPriority(109)); + EXPECT_EQ(4u, framer.MapWeightToPriority(74)); + EXPECT_EQ(5u, framer.MapWeightToPriority(73)); + EXPECT_EQ(5u, framer.MapWeightToPriority(37)); + EXPECT_EQ(6u, framer.MapWeightToPriority(36)); + EXPECT_EQ(6u, framer.MapWeightToPriority(1)); + EXPECT_EQ(7u, framer.MapWeightToPriority(0)); +} + } // namespace net |