summaryrefslogtreecommitdiffstats
path: root/net/spdy
diff options
context:
space:
mode:
authorjgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-20 03:05:07 +0000
committerjgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-20 03:05:07 +0000
commitcc279a331b3e8c803b8b63adbeecd2f5f8307ec3 (patch)
tree5d124feba45ac474d791984c61d46cc7db74bb30 /net/spdy
parent910ee638672e31050f57917084de07d39da54839 (diff)
downloadchromium_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.cc46
-rw-r--r--net/spdy/spdy_framer.h5
-rw-r--r--net/spdy/spdy_framer_test.cc73
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