Commit 7038e9c5 authored by bnc's avatar bnc Committed by Commit bot

Add Http2FrameDecoderAdapter.

This lands server change 127437330 by jamessynge.

BUG=488484

Review-Url: https://codereview.chromium.org/2558243002
Cr-Commit-Position: refs/heads/master@{#437630}
parent d928ba63
...@@ -1337,6 +1337,8 @@ ...@@ -1337,6 +1337,8 @@
'spdy/hpack/hpack_output_stream.h', 'spdy/hpack/hpack_output_stream.h',
'spdy/hpack/hpack_static_table.cc', 'spdy/hpack/hpack_static_table.cc',
'spdy/hpack/hpack_static_table.h', 'spdy/hpack/hpack_static_table.h',
'spdy/http2_frame_decoder_adapter.cc',
'spdy/http2_frame_decoder_adapter.h',
'spdy/http2_priority_dependencies.cc', 'spdy/http2_priority_dependencies.cc',
'spdy/http2_priority_dependencies.h', 'spdy/http2_priority_dependencies.h',
'spdy/http2_write_scheduler.h', 'spdy/http2_write_scheduler.h',
......
This diff is collapsed.
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SPDY_HTTP2_FRAME_DECODER_ADAPTER_H_
#define NET_SPDY_HTTP2_FRAME_DECODER_ADAPTER_H_
// Provides a SpdyFramerDecoderAdapter that uses Http2FrameDecoder for decoding
// HTTP/2 frames. The adapter does not directly decode HPACK, but instead calls
// SpdyFramer::GetHpackDecoderForAdapter() to get the decoder to be used.
#include <memory>
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_framer_decoder_adapter.h"
namespace net {
std::unique_ptr<SpdyFramerDecoderAdapter> CreateHttp2FrameDecoderAdapter(
SpdyFramer* outer_framer);
} // namespace net
#endif // NET_SPDY_HTTP2_FRAME_DECODER_ADAPTER_H_
...@@ -16,6 +16,9 @@ bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false; ...@@ -16,6 +16,9 @@ bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
// clients allow it. // clients allow it.
bool FLAGS_chromium_reloadable_flag_increase_hpack_table_size = false; bool FLAGS_chromium_reloadable_flag_increase_hpack_table_size = false;
// Use Http2FrameDecoderAdapter.
bool FLAGS_use_http2_frame_decoder_adapter = false;
// Use NestedSpdyFramerDecoder. // Use NestedSpdyFramerDecoder.
bool FLAGS_use_nested_spdy_framer_decoder = false; bool FLAGS_use_nested_spdy_framer_decoder = false;
......
...@@ -14,6 +14,7 @@ NET_EXPORT_PRIVATE extern bool ...@@ -14,6 +14,7 @@ NET_EXPORT_PRIVATE extern bool
FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2; FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2;
NET_EXPORT_PRIVATE extern bool NET_EXPORT_PRIVATE extern bool
FLAGS_chromium_reloadable_flag_increase_hpack_table_size; FLAGS_chromium_reloadable_flag_increase_hpack_table_size;
NET_EXPORT_PRIVATE extern bool FLAGS_use_http2_frame_decoder_adapter;
NET_EXPORT_PRIVATE extern bool FLAGS_use_nested_spdy_framer_decoder; NET_EXPORT_PRIVATE extern bool FLAGS_use_nested_spdy_framer_decoder;
} // namespace net } // namespace net
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/hpack/hpack_constants.h"
#include "net/spdy/hpack/hpack_decoder.h" #include "net/spdy/hpack/hpack_decoder.h"
#include "net/spdy/hpack/hpack_decoder2.h" #include "net/spdy/hpack/hpack_decoder2.h"
#include "net/spdy/http2_frame_decoder_adapter.h"
#include "net/spdy/spdy_bitmasks.h" #include "net/spdy/spdy_bitmasks.h"
#include "net/spdy/spdy_bug_tracker.h" #include "net/spdy/spdy_bug_tracker.h"
#include "net/spdy/spdy_flags.h" #include "net/spdy/spdy_flags.h"
...@@ -68,9 +69,18 @@ void UnpackStreamDependencyValues(uint32_t packed, ...@@ -68,9 +69,18 @@ void UnpackStreamDependencyValues(uint32_t packed,
std::unique_ptr<SpdyFramerDecoderAdapter> DecoderAdapterFactory( std::unique_ptr<SpdyFramerDecoderAdapter> DecoderAdapterFactory(
SpdyFramer* outer) { SpdyFramer* outer) {
if (FLAGS_use_nested_spdy_framer_decoder) { if (FLAGS_use_nested_spdy_framer_decoder) {
if (FLAGS_use_http2_frame_decoder_adapter) {
SPDY_BUG << "Two SpdyFramerDecoderAdapter are enabled!";
}
DVLOG(1) << "Creating NestedSpdyFramerDecoder."; DVLOG(1) << "Creating NestedSpdyFramerDecoder.";
return CreateNestedSpdyFramerDecoder(outer); return CreateNestedSpdyFramerDecoder(outer);
} }
if (FLAGS_use_http2_frame_decoder_adapter) {
DVLOG(1) << "Creating Http2FrameDecoderAdapter.";
return CreateHttp2FrameDecoderAdapter(outer);
}
return nullptr; return nullptr;
} }
......
...@@ -553,6 +553,12 @@ class NET_EXPORT_PRIVATE SpdyFramer { ...@@ -553,6 +553,12 @@ class NET_EXPORT_PRIVATE SpdyFramer {
void SetEncoderHeaderTableDebugVisitor( void SetEncoderHeaderTableDebugVisitor(
std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor); std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
// For use in SpdyFramerDecoderAdapter implementations; returns a HPACK
// decoder to be used.
HpackDecoderInterface* GetHpackDecoderForAdapter() {
return GetHpackDecoder();
}
protected: protected:
friend class BufferedSpdyFramer; friend class BufferedSpdyFramer;
friend class HttpNetworkLayer; // This is temporary for the server. friend class HttpNetworkLayer; // This is temporary for the server.
......
...@@ -54,9 +54,10 @@ class SpdyFramerDecoderAdapter { ...@@ -54,9 +54,10 @@ class SpdyFramerDecoderAdapter {
return process_single_input_frame_; return process_single_input_frame_;
} }
// Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns the // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns
// number of bytes consumed. It is safe to pass more bytes in than may be // the number of bytes consumed. It is safe to pass more bytes in than
// consumed. // may be consumed. Should process (or otherwise buffer) as much as
// available, unless process_single_input_frame is true.
virtual size_t ProcessInput(const char* data, size_t len) = 0; virtual size_t ProcessInput(const char* data, size_t len) = 0;
// Reset the decoder (used just for tests at this time). // Reset the decoder (used just for tests at this time).
...@@ -68,9 +69,9 @@ class SpdyFramerDecoderAdapter { ...@@ -68,9 +69,9 @@ class SpdyFramerDecoderAdapter {
// Current error code (NO_ERROR if state != ERROR). // Current error code (NO_ERROR if state != ERROR).
virtual SpdyFramer::SpdyError error_code() const = 0; virtual SpdyFramer::SpdyError error_code() const = 0;
// Did the most recently decoded frame header appear to be the start of an // Has any frame header looked like the start of an HTTP/1.1 (or earlier)
// HTTP/1.1 (or earlier) response? Used to detect if a backend/server that // response? Used to detect if a backend/server that we sent a request to
// we sent a request to, responded with an HTTP/1.1 response? // has responded with an HTTP/1.1 (or earlier) response.
virtual bool probable_http_response() const = 0; virtual bool probable_http_response() const = 0;
private: private:
......
...@@ -613,7 +613,7 @@ StringPiece GetSerializedHeaders(const SpdySerializedFrame& frame, ...@@ -613,7 +613,7 @@ StringPiece GetSerializedHeaders(const SpdySerializedFrame& frame,
frame.size() - framer.GetHeadersMinimumSize()); frame.size() - framer.GetHeadersMinimumSize());
} }
enum DecoderChoice { DECODER_SELF, DECODER_NESTED }; enum DecoderChoice { DECODER_SELF, DECODER_NESTED, DECODER_HTTP2 };
enum HpackChoice { HPACK_DECODER_1, HPACK_DECODER_2 }; enum HpackChoice { HPACK_DECODER_1, HPACK_DECODER_2 };
class SpdyFramerTest class SpdyFramerTest
...@@ -624,9 +624,15 @@ class SpdyFramerTest ...@@ -624,9 +624,15 @@ class SpdyFramerTest
switch (std::get<0>(param)) { switch (std::get<0>(param)) {
case DECODER_SELF: case DECODER_SELF:
FLAGS_use_nested_spdy_framer_decoder = false; FLAGS_use_nested_spdy_framer_decoder = false;
FLAGS_use_http2_frame_decoder_adapter = false;
break; break;
case DECODER_NESTED: case DECODER_NESTED:
FLAGS_use_nested_spdy_framer_decoder = true; FLAGS_use_nested_spdy_framer_decoder = true;
FLAGS_use_http2_frame_decoder_adapter = false;
break;
case DECODER_HTTP2:
FLAGS_use_nested_spdy_framer_decoder = false;
FLAGS_use_http2_frame_decoder_adapter = true;
break; break;
} }
switch (std::get<1>(param)) { switch (std::get<1>(param)) {
...@@ -661,11 +667,13 @@ class SpdyFramerTest ...@@ -661,11 +667,13 @@ class SpdyFramerTest
} }
}; };
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
SpdyFramerTests, SpdyFramerTest,
SpdyFramerTest, ::testing::Combine(::testing::Values(DECODER_SELF,
::testing::Combine(::testing::Values(DECODER_SELF, DECODER_NESTED), DECODER_NESTED,
::testing::Values(HPACK_DECODER_1, HPACK_DECODER_2))); DECODER_HTTP2),
::testing::Values(HPACK_DECODER_1,
HPACK_DECODER_2)));
// Test that we can encode and decode a SpdyHeaderBlock in serialized form. // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
TEST_P(SpdyFramerTest, HeaderBlockInBuffer) { TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
...@@ -1133,9 +1141,8 @@ TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) { ...@@ -1133,9 +1141,8 @@ TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
push_promise.SetHeader("alpha", "beta"); push_promise.SetHeader("alpha", "beta");
SpdySerializedFrame frame(framer.SerializePushPromise(push_promise)); SpdySerializedFrame frame(framer.SerializePushPromise(push_promise));
// We shouldn't have to read the whole frame before we signal an error.
EXPECT_CALL(visitor, OnError(testing::Eq(&framer))); EXPECT_CALL(visitor, OnError(testing::Eq(&framer)));
EXPECT_GT(frame.size(), framer.ProcessInput(frame.data(), frame.size())); framer.ProcessInput(frame.data(), frame.size());
EXPECT_TRUE(framer.HasError()); EXPECT_TRUE(framer.HasError());
EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code()) EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME, framer.error_code())
<< SpdyFramer::ErrorCodeToString(framer.error_code()); << SpdyFramer::ErrorCodeToString(framer.error_code());
...@@ -2794,12 +2801,16 @@ TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) { ...@@ -2794,12 +2801,16 @@ TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
SpdyFramer framer; SpdyFramer framer;
SpdySettingsIR settings_ir; SpdySettingsIR settings_ir;
// Add a setting to pad the frame so that we don't get a buffer overflow when // Add settings to more than fill the frame so that we don't get a buffer
// calling SimulateInFramer() below. // overflow when calling SimulateInFramer() below. These settings must be
// distinct parameters because SpdySettingsIR has a map for settings, and will
// collapse multiple copies of the same parameter.
settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false, settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, false, false,
0x00000002); 0x00000002);
settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, false, false,
0x00000002);
SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir)); SpdySerializedFrame control_frame(framer.SerializeSettings(settings_ir));
const size_t kNewLength = 14; const size_t kNewLength = 8;
SetFrameLength(&control_frame, kNewLength); SetFrameLength(&control_frame, kNewLength);
TestSpdyVisitor visitor; TestSpdyVisitor visitor;
visitor.use_compression_ = false; visitor.use_compression_ = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment