[chttp2] Rework settings management to be a c++ type (#35449)
Closes #35449
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35449 from ctiller:h2-settings f67e542a8b
PiperOrigin-RevId: 597970333
This commit is contained in:
parent
650bb21abd
commit
9f6789e2b2
1
BUILD
1
BUILD
|
|
@ -4077,6 +4077,7 @@ grpc_cc_library(
|
|||
"//src/core:error",
|
||||
"//src/core:error_utils",
|
||||
"//src/core:experiments",
|
||||
"//src/core:gpr_manual_constructor",
|
||||
"//src/core:http2_errors",
|
||||
"//src/core:http2_settings",
|
||||
"//src/core:init_internally",
|
||||
|
|
|
|||
|
|
@ -1097,6 +1097,7 @@ if(gRPC_BUILD_TESTS)
|
|||
add_dependencies(buildtests_cxx hpack_parser_test)
|
||||
add_dependencies(buildtests_cxx hpack_size_test)
|
||||
add_dependencies(buildtests_cxx http2_client)
|
||||
add_dependencies(buildtests_cxx http2_settings_test)
|
||||
add_dependencies(buildtests_cxx http2_stats_test)
|
||||
add_dependencies(buildtests_cxx http_proxy_mapper_test)
|
||||
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
|
||||
|
|
@ -1846,6 +1847,7 @@ add_library(grpc
|
|||
src/core/ext/transport/chttp2/transport/chttp2_transport.cc
|
||||
src/core/ext/transport/chttp2/transport/decode_huff.cc
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc
|
||||
src/core/ext/transport/chttp2/transport/frame.cc
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc
|
||||
src/core/ext/transport/chttp2/transport/frame_ping.cc
|
||||
|
|
@ -2899,6 +2901,7 @@ add_library(grpc_unsecure
|
|||
src/core/ext/transport/chttp2/transport/chttp2_transport.cc
|
||||
src/core/ext/transport/chttp2/transport/decode_huff.cc
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc
|
||||
src/core/ext/transport/chttp2/transport/frame.cc
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc
|
||||
src/core/ext/transport/chttp2/transport/frame_ping.cc
|
||||
|
|
@ -12175,6 +12178,7 @@ if(gRPC_BUILD_TESTS)
|
|||
|
||||
add_executable(flow_control_test
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc
|
||||
src/core/ext/transport/chttp2/transport/frame.cc
|
||||
src/core/ext/transport/chttp2/transport/http2_settings.cc
|
||||
src/core/ext/upb-gen/google/protobuf/any.upb_minitable.c
|
||||
src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c
|
||||
|
|
@ -12199,6 +12203,7 @@ add_executable(flow_control_test
|
|||
src/core/lib/resource_quota/trace.cc
|
||||
src/core/lib/slice/percent_encoding.cc
|
||||
src/core/lib/slice/slice.cc
|
||||
src/core/lib/slice/slice_buffer.cc
|
||||
src/core/lib/slice/slice_refcount.cc
|
||||
src/core/lib/slice/slice_string_helpers.cc
|
||||
src/core/lib/transport/bdp_estimator.cc
|
||||
|
|
@ -12244,6 +12249,7 @@ target_link_libraries(flow_control_test
|
|||
absl::hash
|
||||
absl::type_traits
|
||||
absl::statusor
|
||||
absl::span
|
||||
gpr
|
||||
)
|
||||
|
||||
|
|
@ -14536,6 +14542,39 @@ target_link_libraries(http2_client
|
|||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
add_executable(http2_settings_test
|
||||
test/core/transport/chttp2/http2_settings_test.cc
|
||||
)
|
||||
target_compile_features(http2_settings_test PUBLIC cxx_std_14)
|
||||
target_include_directories(http2_settings_test
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
|
||||
${_gRPC_RE2_INCLUDE_DIR}
|
||||
${_gRPC_SSL_INCLUDE_DIR}
|
||||
${_gRPC_UPB_GENERATED_DIR}
|
||||
${_gRPC_UPB_GRPC_GENERATED_DIR}
|
||||
${_gRPC_UPB_INCLUDE_DIR}
|
||||
${_gRPC_XXHASH_INCLUDE_DIR}
|
||||
${_gRPC_ZLIB_INCLUDE_DIR}
|
||||
third_party/googletest/googletest/include
|
||||
third_party/googletest/googletest
|
||||
third_party/googletest/googlemock/include
|
||||
third_party/googletest/googlemock
|
||||
${_gRPC_PROTO_GENS_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(http2_settings_test
|
||||
${_gRPC_ALLTARGETS_LIBRARIES}
|
||||
gtest
|
||||
grpc_test_util
|
||||
)
|
||||
|
||||
|
||||
endif()
|
||||
if(gRPC_BUILD_TESTS)
|
||||
|
||||
|
|
|
|||
|
|
@ -1051,6 +1051,7 @@ LIBGRPC_SRC = \
|
|||
src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
|
||||
src/core/ext/transport/chttp2/transport/decode_huff.cc \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_ping.cc \
|
||||
|
|
@ -1956,6 +1957,7 @@ LIBGRPC_UNSECURE_SRC = \
|
|||
src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
|
||||
src/core/ext/transport/chttp2/transport/decode_huff.cc \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_ping.cc \
|
||||
|
|
|
|||
|
|
@ -289,6 +289,8 @@ let package = Package(
|
|||
"src/core/ext/transport/chttp2/transport/decode_huff.h",
|
||||
"src/core/ext/transport/chttp2/transport/flow_control.cc",
|
||||
"src/core/ext/transport/chttp2/transport/flow_control.h",
|
||||
"src/core/ext/transport/chttp2/transport/frame.cc",
|
||||
"src/core/ext/transport/chttp2/transport/frame.h",
|
||||
"src/core/ext/transport/chttp2/transport/frame_data.cc",
|
||||
"src/core/ext/transport/chttp2/transport/frame_data.h",
|
||||
"src/core/ext/transport/chttp2/transport/frame_goaway.cc",
|
||||
|
|
|
|||
|
|
@ -299,6 +299,7 @@ libs:
|
|||
- src/core/ext/transport/chttp2/transport/context_list_entry.h
|
||||
- src/core/ext/transport/chttp2/transport/decode_huff.h
|
||||
- src/core/ext/transport/chttp2/transport/flow_control.h
|
||||
- src/core/ext/transport/chttp2/transport/frame.h
|
||||
- src/core/ext/transport/chttp2/transport/frame_data.h
|
||||
- src/core/ext/transport/chttp2/transport/frame_goaway.h
|
||||
- src/core/ext/transport/chttp2/transport/frame_ping.h
|
||||
|
|
@ -1311,6 +1312,7 @@ libs:
|
|||
- src/core/ext/transport/chttp2/transport/chttp2_transport.cc
|
||||
- src/core/ext/transport/chttp2/transport/decode_huff.cc
|
||||
- src/core/ext/transport/chttp2/transport/flow_control.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame_data.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame_goaway.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame_ping.cc
|
||||
|
|
@ -2239,6 +2241,7 @@ libs:
|
|||
- src/core/ext/transport/chttp2/transport/context_list_entry.h
|
||||
- src/core/ext/transport/chttp2/transport/decode_huff.h
|
||||
- src/core/ext/transport/chttp2/transport/flow_control.h
|
||||
- src/core/ext/transport/chttp2/transport/frame.h
|
||||
- src/core/ext/transport/chttp2/transport/frame_data.h
|
||||
- src/core/ext/transport/chttp2/transport/frame_goaway.h
|
||||
- src/core/ext/transport/chttp2/transport/frame_ping.h
|
||||
|
|
@ -2723,6 +2726,7 @@ libs:
|
|||
- src/core/ext/transport/chttp2/transport/chttp2_transport.cc
|
||||
- src/core/ext/transport/chttp2/transport/decode_huff.cc
|
||||
- src/core/ext/transport/chttp2/transport/flow_control.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame_data.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame_goaway.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame_ping.cc
|
||||
|
|
@ -8978,6 +8982,7 @@ targets:
|
|||
language: c++
|
||||
headers:
|
||||
- src/core/ext/transport/chttp2/transport/flow_control.h
|
||||
- src/core/ext/transport/chttp2/transport/frame.h
|
||||
- src/core/ext/transport/chttp2/transport/http2_settings.h
|
||||
- src/core/ext/upb-gen/google/protobuf/any.upb.h
|
||||
- src/core/ext/upb-gen/google/protobuf/any.upb_minitable.h
|
||||
|
|
@ -9024,6 +9029,7 @@ targets:
|
|||
- src/core/lib/resource_quota/trace.h
|
||||
- src/core/lib/slice/percent_encoding.h
|
||||
- src/core/lib/slice/slice.h
|
||||
- src/core/lib/slice/slice_buffer.h
|
||||
- src/core/lib/slice/slice_internal.h
|
||||
- src/core/lib/slice/slice_refcount.h
|
||||
- src/core/lib/slice/slice_string_helpers.h
|
||||
|
|
@ -9052,6 +9058,7 @@ targets:
|
|||
- third_party/upb/upb/wire/types.h
|
||||
src:
|
||||
- src/core/ext/transport/chttp2/transport/flow_control.cc
|
||||
- src/core/ext/transport/chttp2/transport/frame.cc
|
||||
- src/core/ext/transport/chttp2/transport/http2_settings.cc
|
||||
- src/core/ext/upb-gen/google/protobuf/any.upb_minitable.c
|
||||
- src/core/ext/upb-gen/google/protobuf/descriptor.upb_minitable.c
|
||||
|
|
@ -9076,6 +9083,7 @@ targets:
|
|||
- src/core/lib/resource_quota/trace.cc
|
||||
- src/core/lib/slice/percent_encoding.cc
|
||||
- src/core/lib/slice/slice.cc
|
||||
- src/core/lib/slice/slice_buffer.cc
|
||||
- src/core/lib/slice/slice_refcount.cc
|
||||
- src/core/lib/slice/slice_string_helpers.cc
|
||||
- src/core/lib/transport/bdp_estimator.cc
|
||||
|
|
@ -9099,6 +9107,7 @@ targets:
|
|||
- absl/hash:hash
|
||||
- absl/meta:type_traits
|
||||
- absl/status:statusor
|
||||
- absl/types:span
|
||||
- gpr
|
||||
uses_polling: false
|
||||
- name: for_each_test
|
||||
|
|
@ -10375,6 +10384,16 @@ targets:
|
|||
deps:
|
||||
- grpc++_test_config
|
||||
- grpc++_test_util
|
||||
- name: http2_settings_test
|
||||
gtest: true
|
||||
build: test
|
||||
language: c++
|
||||
headers: []
|
||||
src:
|
||||
- test/core/transport/chttp2/http2_settings_test.cc
|
||||
deps:
|
||||
- gtest
|
||||
- grpc_test_util
|
||||
- name: http2_stats_test
|
||||
gtest: true
|
||||
build: test
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ if test "$PHP_GRPC" != "no"; then
|
|||
src/core/ext/transport/chttp2/transport/chttp2_transport.cc \
|
||||
src/core/ext/transport/chttp2/transport/decode_huff.cc \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_ping.cc \
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ if (PHP_GRPC != "no") {
|
|||
"src\\core\\ext\\transport\\chttp2\\transport\\chttp2_transport.cc " +
|
||||
"src\\core\\ext\\transport\\chttp2\\transport\\decode_huff.cc " +
|
||||
"src\\core\\ext\\transport\\chttp2\\transport\\flow_control.cc " +
|
||||
"src\\core\\ext\\transport\\chttp2\\transport\\frame.cc " +
|
||||
"src\\core\\ext\\transport\\chttp2\\transport\\frame_data.cc " +
|
||||
"src\\core\\ext\\transport\\chttp2\\transport\\frame_goaway.cc " +
|
||||
"src\\core\\ext\\transport\\chttp2\\transport\\frame_ping.cc " +
|
||||
|
|
|
|||
|
|
@ -368,6 +368,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/ext/transport/chttp2/transport/context_list_entry.h',
|
||||
'src/core/ext/transport/chttp2/transport/decode_huff.h',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_ping.h',
|
||||
|
|
@ -1611,6 +1612,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/ext/transport/chttp2/transport/context_list_entry.h',
|
||||
'src/core/ext/transport/chttp2/transport/decode_huff.h',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_ping.h',
|
||||
|
|
|
|||
|
|
@ -392,6 +392,8 @@ Pod::Spec.new do |s|
|
|||
'src/core/ext/transport/chttp2/transport/decode_huff.h',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.cc',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
|
||||
|
|
@ -2382,6 +2384,7 @@ Pod::Spec.new do |s|
|
|||
'src/core/ext/transport/chttp2/transport/context_list_entry.h',
|
||||
'src/core/ext/transport/chttp2/transport/decode_huff.h',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.h',
|
||||
'src/core/ext/transport/chttp2/transport/frame_ping.h',
|
||||
|
|
|
|||
|
|
@ -295,6 +295,8 @@ Gem::Specification.new do |s|
|
|||
s.files += %w( src/core/ext/transport/chttp2/transport/decode_huff.h )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/flow_control.cc )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/flow_control.h )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/frame.cc )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/frame.h )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.cc )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/frame_data.h )
|
||||
s.files += %w( src/core/ext/transport/chttp2/transport/frame_goaway.cc )
|
||||
|
|
|
|||
|
|
@ -364,6 +364,7 @@
|
|||
'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
|
||||
'src/core/ext/transport/chttp2/transport/decode_huff.cc',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_ping.cc',
|
||||
|
|
@ -1209,6 +1210,7 @@
|
|||
'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
|
||||
'src/core/ext/transport/chttp2/transport/decode_huff.cc',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_ping.cc',
|
||||
|
|
|
|||
|
|
@ -277,6 +277,8 @@
|
|||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/decode_huff.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/flow_control.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/flow_control.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.cc" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_data.h" role="src" />
|
||||
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/frame_goaway.cc" role="src" />
|
||||
|
|
|
|||
|
|
@ -6137,9 +6137,15 @@ grpc_cc_library(
|
|||
hdrs = [
|
||||
"ext/transport/chttp2/transport/http2_settings.h",
|
||||
],
|
||||
external_deps = [
|
||||
"absl/functional:function_ref",
|
||||
"absl/strings",
|
||||
"absl/types:optional",
|
||||
],
|
||||
deps = [
|
||||
"http2_errors",
|
||||
"useful",
|
||||
"//:chttp2_frame",
|
||||
"//:gpr_platform",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -163,10 +163,6 @@ static void read_action_locked(grpc_core::RefCountedPtr<grpc_chttp2_transport>,
|
|||
static void continue_read_action_locked(
|
||||
grpc_core::RefCountedPtr<grpc_chttp2_transport> t);
|
||||
|
||||
// Set a transport level setting, and push it to our peer
|
||||
static void queue_setting_update(grpc_chttp2_transport* t,
|
||||
grpc_chttp2_setting_id id, uint32_t value);
|
||||
|
||||
static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
|
||||
grpc_error_handle error, bool tarpit);
|
||||
|
||||
|
|
@ -550,93 +546,54 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|||
t->max_header_list_size_soft_limit = soft_limit;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
absl::string_view channel_arg_name;
|
||||
grpc_chttp2_setting_id setting_id;
|
||||
int default_value;
|
||||
int min;
|
||||
int max;
|
||||
bool availability[2] /* server, client */;
|
||||
} settings_map[] = {{GRPC_ARG_MAX_CONCURRENT_STREAMS,
|
||||
GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
|
||||
-1,
|
||||
0,
|
||||
INT32_MAX,
|
||||
{true, false}},
|
||||
{GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
|
||||
GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
|
||||
-1,
|
||||
0,
|
||||
INT32_MAX,
|
||||
{true, true}},
|
||||
{GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE,
|
||||
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
|
||||
-1,
|
||||
0,
|
||||
INT32_MAX,
|
||||
{true, true}},
|
||||
{GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
|
||||
GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
|
||||
-1,
|
||||
16384,
|
||||
16777215,
|
||||
{true, true}},
|
||||
{GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY,
|
||||
GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
{true, true}},
|
||||
{GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
|
||||
GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
|
||||
-1,
|
||||
5,
|
||||
INT32_MAX,
|
||||
{true, true}}};
|
||||
|
||||
for (size_t i = 0; i < GPR_ARRAY_SIZE(settings_map); i++) {
|
||||
const auto& setting = settings_map[i];
|
||||
if (setting.availability[is_client]) {
|
||||
const int value = channel_args.GetInt(setting.channel_arg_name)
|
||||
.value_or(setting.default_value);
|
||||
if (value >= 0) {
|
||||
const int clamped_value =
|
||||
grpc_core::Clamp(value, setting.min, setting.max);
|
||||
queue_setting_update(t, setting.setting_id, clamped_value);
|
||||
if (setting.setting_id == GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) {
|
||||
t->max_concurrent_streams_policy.SetTarget(clamped_value);
|
||||
}
|
||||
} else if (setting.setting_id ==
|
||||
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE) {
|
||||
// Set value to 1.25 * soft limit if this is larger than
|
||||
// `DEFAULT_MAX_HEADER_LIST_SIZE` and
|
||||
// `GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE` is not set.
|
||||
const int soft_limit = channel_args.GetInt(GRPC_ARG_MAX_METADATA_SIZE)
|
||||
.value_or(setting.default_value);
|
||||
const int value = (soft_limit >= 0 && soft_limit < (INT_MAX / 1.25))
|
||||
? static_cast<int>(soft_limit * 1.25)
|
||||
: soft_limit;
|
||||
if (value > DEFAULT_MAX_HEADER_LIST_SIZE) {
|
||||
queue_setting_update(
|
||||
t, setting.setting_id,
|
||||
grpc_core::Clamp(value, setting.min, setting.max));
|
||||
}
|
||||
}
|
||||
} else if (channel_args.Contains(setting.channel_arg_name)) {
|
||||
gpr_log(GPR_DEBUG, "%s is not available on %s",
|
||||
std::string(setting.channel_arg_name).c_str(),
|
||||
is_client ? "clients" : "servers");
|
||||
int value;
|
||||
if (!is_client) {
|
||||
value = channel_args.GetInt(GRPC_ARG_MAX_CONCURRENT_STREAMS).value_or(-1);
|
||||
if (value >= 0) {
|
||||
t->settings.mutable_local().SetMaxConcurrentStreams(value);
|
||||
t->max_concurrent_streams_policy.SetTarget(value);
|
||||
}
|
||||
} else if (channel_args.Contains(GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
|
||||
gpr_log(GPR_DEBUG, "%s is not available on clients",
|
||||
GRPC_ARG_MAX_CONCURRENT_STREAMS);
|
||||
}
|
||||
value =
|
||||
channel_args.GetInt(GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER).value_or(-1);
|
||||
if (value >= 0) {
|
||||
t->settings.mutable_local().SetHeaderTableSize(value);
|
||||
}
|
||||
value = channel_args.GetInt(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE).value_or(-1);
|
||||
if (value >= 0) {
|
||||
t->settings.mutable_local().SetMaxHeaderListSize(value);
|
||||
} else {
|
||||
// Set value to 1.25 * soft limit if this is larger than
|
||||
// `DEFAULT_MAX_HEADER_LIST_SIZE` and
|
||||
// `GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE` is not set.
|
||||
const int soft_limit =
|
||||
channel_args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1);
|
||||
const int value = (soft_limit >= 0 && soft_limit < (INT_MAX / 1.25))
|
||||
? static_cast<int>(soft_limit * 1.25)
|
||||
: soft_limit;
|
||||
if (value > DEFAULT_MAX_HEADER_LIST_SIZE) {
|
||||
t->settings.mutable_local().SetMaxHeaderListSize(value);
|
||||
}
|
||||
}
|
||||
value = channel_args.GetInt(GRPC_ARG_HTTP2_MAX_FRAME_SIZE).value_or(-1);
|
||||
if (value >= 0) {
|
||||
t->settings.mutable_local().SetMaxFrameSize(value);
|
||||
}
|
||||
value =
|
||||
channel_args.GetInt(GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES).value_or(-1);
|
||||
if (value >= 0) {
|
||||
t->settings.mutable_local().SetInitialWindowSize(value);
|
||||
}
|
||||
value = channel_args.GetInt(GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY).value_or(-1);
|
||||
if (value >= 0) {
|
||||
t->settings.mutable_local().SetAllowTrueBinaryMetadata(value != 0);
|
||||
}
|
||||
|
||||
if (t->enable_preferred_rx_crypto_frame_advertisement) {
|
||||
const grpc_chttp2_setting_parameters* sp =
|
||||
&grpc_chttp2_settings_parameters
|
||||
[GRPC_CHTTP2_SETTINGS_GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE];
|
||||
queue_setting_update(
|
||||
t, GRPC_CHTTP2_SETTINGS_GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE,
|
||||
grpc_core::Clamp(INT_MAX, static_cast<int>(sp->min_value),
|
||||
static_cast<int>(sp->max_value)));
|
||||
t->settings.mutable_local().SetPreferredReceiveCryptoMessageSize(INT_MAX);
|
||||
}
|
||||
|
||||
t->ping_on_rst_stream_percent = grpc_core::Clamp(
|
||||
|
|
@ -710,33 +667,22 @@ grpc_chttp2_transport::grpc_chttp2_transport(
|
|||
grpc_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
|
||||
}
|
||||
grpc_slice_buffer_init(&qbuf);
|
||||
// copy in initial settings to all setting sets
|
||||
size_t i;
|
||||
int j;
|
||||
for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) {
|
||||
for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) {
|
||||
settings[j][i] = grpc_chttp2_settings_parameters[i].default_value;
|
||||
}
|
||||
}
|
||||
grpc_chttp2_goaway_parser_init(&goaway_parser);
|
||||
|
||||
// configure http2 the way we like it
|
||||
if (is_client) {
|
||||
queue_setting_update(this, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
|
||||
queue_setting_update(this, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
|
||||
settings.mutable_local().SetEnablePush(false);
|
||||
settings.mutable_local().SetMaxConcurrentStreams(0);
|
||||
}
|
||||
queue_setting_update(this, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
|
||||
DEFAULT_MAX_HEADER_LIST_SIZE);
|
||||
queue_setting_update(this,
|
||||
GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1);
|
||||
settings.mutable_local().SetMaxHeaderListSize(DEFAULT_MAX_HEADER_LIST_SIZE);
|
||||
settings.mutable_local().SetAllowTrueBinaryMetadata(true);
|
||||
|
||||
read_channel_args(this, channel_args, is_client);
|
||||
|
||||
// Initially allow *UP TO* MAX_CONCURRENT_STREAMS incoming before we start
|
||||
// blanket cancelling them.
|
||||
num_incoming_streams_before_settings_ack =
|
||||
settings[GRPC_LOCAL_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS];
|
||||
settings.local().max_concurrent_streams();
|
||||
|
||||
grpc_core::ExecCtx exec_ctx;
|
||||
combiner->Run(
|
||||
|
|
@ -1126,9 +1072,7 @@ static void write_action(grpc_chttp2_transport* t) {
|
|||
// Choose max_frame_size as the prefered rx crypto frame size indicated by the
|
||||
// peer.
|
||||
int max_frame_size =
|
||||
t->settings
|
||||
[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE];
|
||||
t->settings.peer().preferred_receive_crypto_message_size();
|
||||
// Note: max frame size is 0 if the remote peer does not support adjusting the
|
||||
// sending frame size.
|
||||
if (max_frame_size == 0) {
|
||||
|
|
@ -1205,23 +1149,6 @@ static void write_action_end_locked(
|
|||
grpc_chttp2_end_write(t.get(), error);
|
||||
}
|
||||
|
||||
// Dirties an HTTP2 setting to be sent out next time a writing path occurs.
|
||||
// If the change needs to occur immediately, manually initiate a write.
|
||||
static void queue_setting_update(grpc_chttp2_transport* t,
|
||||
grpc_chttp2_setting_id id, uint32_t value) {
|
||||
const grpc_chttp2_setting_parameters* sp =
|
||||
&grpc_chttp2_settings_parameters[id];
|
||||
uint32_t use_value = grpc_core::Clamp(value, sp->min_value, sp->max_value);
|
||||
if (use_value != value) {
|
||||
gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
|
||||
value, use_value);
|
||||
}
|
||||
if (use_value != t->settings[GRPC_LOCAL_SETTINGS][id]) {
|
||||
t->settings[GRPC_LOCAL_SETTINGS][id] = use_value;
|
||||
t->dirtied_local_settings = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel out streams that haven't yet started if we have received a GOAWAY
|
||||
static void cancel_unstarted_streams(grpc_chttp2_transport* t,
|
||||
grpc_error_handle error, bool tarpit) {
|
||||
|
|
@ -1320,9 +1247,7 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
|
|||
// start streams where we have free grpc_chttp2_stream ids and free
|
||||
// * concurrency
|
||||
while (t->next_stream_id <= MAX_CLIENT_STREAM_ID &&
|
||||
t->stream_map.size() <
|
||||
t->settings[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
|
||||
t->stream_map.size() < t->settings.peer().max_concurrent_streams() &&
|
||||
grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
|
||||
// safe since we can't (legally) be parsing this stream yet
|
||||
GRPC_CHTTP2_IF_TRACING(gpr_log(
|
||||
|
|
@ -2707,21 +2632,19 @@ void grpc_chttp2_act_on_flowctl_action(
|
|||
GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL, []() {});
|
||||
WithUrgency(t, action.send_initial_window_update(),
|
||||
GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS, [t, &action]() {
|
||||
queue_setting_update(t,
|
||||
GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
|
||||
action.initial_window_size());
|
||||
});
|
||||
WithUrgency(t, action.send_max_frame_size_update(),
|
||||
GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS, [t, &action]() {
|
||||
queue_setting_update(t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
|
||||
action.max_frame_size());
|
||||
t->settings.mutable_local().SetInitialWindowSize(
|
||||
action.initial_window_size());
|
||||
});
|
||||
WithUrgency(
|
||||
t, action.send_max_frame_size_update(),
|
||||
GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS, [t, &action]() {
|
||||
t->settings.mutable_local().SetMaxFrameSize(action.max_frame_size());
|
||||
});
|
||||
if (t->enable_preferred_rx_crypto_frame_advertisement) {
|
||||
WithUrgency(
|
||||
t, action.preferred_rx_crypto_frame_size_update(),
|
||||
GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS, [t, &action]() {
|
||||
queue_setting_update(
|
||||
t, GRPC_CHTTP2_SETTINGS_GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE,
|
||||
t->settings.mutable_local().SetPreferredReceiveCryptoMessageSize(
|
||||
action.preferred_rx_crypto_frame_size());
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,18 +230,14 @@ TransportFlowControl::TargetInitialWindowSizeBasedOnMemoryPressureAndBdp()
|
|||
}
|
||||
|
||||
void TransportFlowControl::UpdateSetting(
|
||||
grpc_chttp2_setting_id id, int64_t* desired_value,
|
||||
uint32_t new_desired_value, FlowControlAction* action,
|
||||
absl::string_view name, int64_t* desired_value, uint32_t new_desired_value,
|
||||
FlowControlAction* action,
|
||||
FlowControlAction& (FlowControlAction::*set)(FlowControlAction::Urgency,
|
||||
uint32_t)) {
|
||||
new_desired_value =
|
||||
Clamp(new_desired_value, grpc_chttp2_settings_parameters[id].min_value,
|
||||
grpc_chttp2_settings_parameters[id].max_value);
|
||||
if (new_desired_value != *desired_value) {
|
||||
if (grpc_flowctl_trace.enabled()) {
|
||||
gpr_log(GPR_INFO, "[flowctl] UPDATE SETTING %s from %" PRId64 " to %d",
|
||||
grpc_chttp2_settings_parameters[id].name, *desired_value,
|
||||
new_desired_value);
|
||||
std::string(name).c_str(), *desired_value, new_desired_value);
|
||||
}
|
||||
// Reaching zero can only happen for initial window size, and if it occurs
|
||||
// we really want to wake up writes and ensure all the queued stream
|
||||
|
|
@ -290,13 +286,15 @@ FlowControlAction TransportFlowControl::PeriodicUpdate() {
|
|||
}
|
||||
// Though initial window 'could' drop to 0, we keep the floor at
|
||||
// kMinInitialWindowSize
|
||||
UpdateSetting(GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
|
||||
&target_initial_window_size_, target, &action,
|
||||
&FlowControlAction::set_send_initial_window_update);
|
||||
UpdateSetting(Http2Settings::initial_window_size_name(),
|
||||
&target_initial_window_size_,
|
||||
std::min(target, Http2Settings::max_initial_window_size()),
|
||||
&action, &FlowControlAction::set_send_initial_window_update);
|
||||
// we target the max of BDP or bandwidth in microseconds.
|
||||
UpdateSetting(GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, &target_frame_size_,
|
||||
target, &action,
|
||||
&FlowControlAction::set_send_max_frame_size_update);
|
||||
UpdateSetting(Http2Settings::max_frame_size_name(), &target_frame_size_,
|
||||
Clamp(target, Http2Settings::min_max_frame_size(),
|
||||
Http2Settings::max_max_frame_size()),
|
||||
&action, &FlowControlAction::set_send_max_frame_size_update);
|
||||
|
||||
if (IsTcpFrameSizeTuningEnabled()) {
|
||||
// Advertise PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE to peer. By advertising
|
||||
|
|
@ -306,10 +304,11 @@ FlowControlAction TransportFlowControl::PeriodicUpdate() {
|
|||
// Clamp(target_frame_size_ * 2, 16384, 0x7fffffff). In the future, this
|
||||
// maybe updated to a different function of the memory pressure.
|
||||
UpdateSetting(
|
||||
GRPC_CHTTP2_SETTINGS_GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE,
|
||||
Http2Settings::preferred_receive_crypto_message_size_name(),
|
||||
&target_preferred_rx_crypto_frame_size_,
|
||||
Clamp(static_cast<unsigned int>(target_frame_size_ * 2), 16384u,
|
||||
0x7ffffffu),
|
||||
Clamp(static_cast<unsigned int>(target_frame_size_ * 2),
|
||||
Http2Settings::min_preferred_receive_crypto_message_size(),
|
||||
Http2Settings::max_preferred_receive_crypto_message_size()),
|
||||
&action,
|
||||
&FlowControlAction::set_preferred_rx_crypto_frame_size_update);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ class TransportFlowControl final {
|
|||
|
||||
private:
|
||||
double TargetInitialWindowSizeBasedOnMemoryPressureAndBdp() const;
|
||||
static void UpdateSetting(grpc_chttp2_setting_id id, int64_t* desired_value,
|
||||
static void UpdateSetting(absl::string_view name, int64_t* desired_value,
|
||||
uint32_t new_desired_value,
|
||||
FlowControlAction* action,
|
||||
FlowControlAction& (FlowControlAction::*set)(
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ struct Http2RstStreamFrame {
|
|||
// SETTINGS frame
|
||||
struct Http2SettingsFrame {
|
||||
struct Setting {
|
||||
Setting(uint16_t id, uint32_t value) : id(id), value(value) {}
|
||||
|
||||
uint16_t id;
|
||||
uint32_t value;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "src/core/ext/transport/chttp2/transport/flow_control.h"
|
||||
#include "src/core/ext/transport/chttp2/transport/frame_goaway.h"
|
||||
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
|
||||
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
|
||||
#include "src/core/ext/transport/chttp2/transport/internal.h"
|
||||
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
|
||||
|
|
@ -55,38 +56,6 @@ static uint8_t* fill_header(uint8_t* out, uint32_t length, uint8_t flags) {
|
|||
return out;
|
||||
}
|
||||
|
||||
grpc_slice grpc_chttp2_settings_create(uint32_t* old_settings,
|
||||
const uint32_t* new_settings,
|
||||
uint32_t force_mask, size_t count) {
|
||||
size_t i;
|
||||
uint32_t n = 0;
|
||||
grpc_slice output;
|
||||
uint8_t* p;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
n += (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0);
|
||||
}
|
||||
|
||||
output = GRPC_SLICE_MALLOC(9 + 6 * n);
|
||||
p = fill_header(GRPC_SLICE_START_PTR(output), 6 * n, 0);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0) {
|
||||
*p++ = static_cast<uint8_t>(grpc_setting_id_to_wire_id[i] >> 8);
|
||||
*p++ = static_cast<uint8_t>(grpc_setting_id_to_wire_id[i]);
|
||||
*p++ = static_cast<uint8_t>(new_settings[i] >> 24);
|
||||
*p++ = static_cast<uint8_t>(new_settings[i] >> 16);
|
||||
*p++ = static_cast<uint8_t>(new_settings[i] >> 8);
|
||||
*p++ = static_cast<uint8_t>(new_settings[i]);
|
||||
old_settings[i] = new_settings[i];
|
||||
}
|
||||
}
|
||||
|
||||
GPR_ASSERT(p == GRPC_SLICE_END_PTR(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc_slice grpc_chttp2_settings_ack_create(void) {
|
||||
grpc_slice output = GRPC_SLICE_MALLOC(9);
|
||||
fill_header(GRPC_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK);
|
||||
|
|
@ -95,10 +64,9 @@ grpc_slice grpc_chttp2_settings_ack_create(void) {
|
|||
|
||||
grpc_error_handle grpc_chttp2_settings_parser_begin_frame(
|
||||
grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags,
|
||||
uint32_t* settings) {
|
||||
parser->target_settings = settings;
|
||||
memcpy(parser->incoming_settings, settings,
|
||||
GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
|
||||
grpc_core::Http2Settings& settings) {
|
||||
parser->target_settings = &settings;
|
||||
parser->incoming_settings.Init(settings);
|
||||
parser->is_ack = 0;
|
||||
parser->state = GRPC_CHTTP2_SPS_ID0;
|
||||
if (flags == GRPC_CHTTP2_FLAG_ACK) {
|
||||
|
|
@ -125,7 +93,6 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p,
|
|||
static_cast<grpc_chttp2_settings_parser*>(p);
|
||||
const uint8_t* cur = GRPC_SLICE_START_PTR(slice);
|
||||
const uint8_t* end = GRPC_SLICE_END_PTR(slice);
|
||||
grpc_chttp2_setting_id id;
|
||||
|
||||
if (parser->is_ack) {
|
||||
return absl::OkStatus();
|
||||
|
|
@ -137,8 +104,7 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p,
|
|||
if (cur == end) {
|
||||
parser->state = GRPC_CHTTP2_SPS_ID0;
|
||||
if (is_last) {
|
||||
memcpy(parser->target_settings, parser->incoming_settings,
|
||||
GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
|
||||
*parser->target_settings = *parser->incoming_settings;
|
||||
t->num_pending_induced_frames++;
|
||||
grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create());
|
||||
grpc_chttp2_initiate_write(t,
|
||||
|
|
@ -187,7 +153,7 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p,
|
|||
parser->value |= (static_cast<uint32_t>(*cur)) << 8;
|
||||
cur++;
|
||||
ABSL_FALLTHROUGH_INTENDED;
|
||||
case GRPC_CHTTP2_SPS_VAL3:
|
||||
case GRPC_CHTTP2_SPS_VAL3: {
|
||||
if (cur == end) {
|
||||
parser->state = GRPC_CHTTP2_SPS_VAL3;
|
||||
return absl::OkStatus();
|
||||
|
|
@ -197,47 +163,35 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p,
|
|||
parser->value |= *cur;
|
||||
cur++;
|
||||
|
||||
if (grpc_wire_id_to_setting_id(parser->id, &id)) {
|
||||
const grpc_chttp2_setting_parameters* sp =
|
||||
&grpc_chttp2_settings_parameters[id];
|
||||
if (parser->value < sp->min_value || parser->value > sp->max_value) {
|
||||
switch (sp->invalid_value_behavior) {
|
||||
case GRPC_CHTTP2_CLAMP_INVALID_VALUE:
|
||||
parser->value = grpc_core::Clamp(parser->value, sp->min_value,
|
||||
sp->max_value);
|
||||
break;
|
||||
case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE:
|
||||
grpc_chttp2_goaway_append(
|
||||
t->last_new_stream_id, sp->error_value,
|
||||
grpc_slice_from_static_string("HTTP2 settings error"),
|
||||
&t->qbuf);
|
||||
return GRPC_ERROR_CREATE(absl::StrFormat(
|
||||
"invalid value %u passed for %s", parser->value, sp->name));
|
||||
}
|
||||
if (parser->id == grpc_core::Http2Settings::kInitialWindowSizeWireId) {
|
||||
t->initial_window_update +=
|
||||
static_cast<int64_t>(parser->value) -
|
||||
parser->incoming_settings->initial_window_size();
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
|
||||
GRPC_TRACE_FLAG_ENABLED(grpc_flowctl_trace)) {
|
||||
gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t,
|
||||
t->is_client ? "cli" : "svr",
|
||||
static_cast<int>(t->initial_window_update));
|
||||
}
|
||||
if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE &&
|
||||
parser->incoming_settings[id] != parser->value) {
|
||||
t->initial_window_update += static_cast<int64_t>(parser->value) -
|
||||
parser->incoming_settings[id];
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
|
||||
GRPC_TRACE_FLAG_ENABLED(grpc_flowctl_trace)) {
|
||||
gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t,
|
||||
t->is_client ? "cli" : "svr",
|
||||
static_cast<int>(t->initial_window_update));
|
||||
}
|
||||
}
|
||||
parser->incoming_settings[id] = parser->value;
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
|
||||
gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d",
|
||||
t->is_client ? "CLI" : "SVR",
|
||||
std::string(t->peer_string.as_string_view()).c_str(),
|
||||
sp->name, parser->value);
|
||||
}
|
||||
} else if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
|
||||
gpr_log(GPR_DEBUG, "CHTTP2: Ignoring unknown setting %d (value %d)",
|
||||
parser->id, parser->value);
|
||||
}
|
||||
break;
|
||||
auto error =
|
||||
parser->incoming_settings->Apply(parser->id, parser->value);
|
||||
if (error != GRPC_HTTP2_NO_ERROR) {
|
||||
grpc_chttp2_goaway_append(
|
||||
t->last_new_stream_id, error,
|
||||
grpc_slice_from_static_string("HTTP2 settings error"), &t->qbuf);
|
||||
return GRPC_ERROR_CREATE(absl::StrFormat(
|
||||
"invalid value %u passed for %s", parser->value,
|
||||
grpc_core::Http2Settings::WireIdToName(parser->id).c_str()));
|
||||
}
|
||||
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
|
||||
gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d",
|
||||
t->is_client ? "CLI" : "SVR",
|
||||
std::string(t->peer_string.as_string_view()).c_str(),
|
||||
grpc_core::Http2Settings::WireIdToName(parser->id).c_str(),
|
||||
parser->value);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
|
||||
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
|
||||
#include "src/core/lib/gprpp/manual_constructor.h"
|
||||
#include "src/core/lib/iomgr/error.h"
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -41,22 +42,18 @@ typedef enum {
|
|||
|
||||
struct grpc_chttp2_settings_parser {
|
||||
grpc_chttp2_settings_parse_state state;
|
||||
uint32_t* target_settings;
|
||||
grpc_core::Http2Settings* target_settings;
|
||||
grpc_core::ManualConstructor<grpc_core::Http2Settings> incoming_settings;
|
||||
uint8_t is_ack;
|
||||
uint16_t id;
|
||||
uint32_t value;
|
||||
uint32_t incoming_settings[GRPC_CHTTP2_NUM_SETTINGS];
|
||||
};
|
||||
// Create a settings frame by diffing old & new, and updating old to be new
|
||||
grpc_slice grpc_chttp2_settings_create(uint32_t* old_settings,
|
||||
const uint32_t* new_settings,
|
||||
uint32_t force_mask, size_t count);
|
||||
// Create an ack settings frame
|
||||
grpc_slice grpc_chttp2_settings_ack_create(void);
|
||||
|
||||
grpc_error_handle grpc_chttp2_settings_parser_begin_frame(
|
||||
grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags,
|
||||
uint32_t* settings);
|
||||
grpc_core::Http2Settings& settings);
|
||||
grpc_error_handle grpc_chttp2_settings_parser_parse(void* parser,
|
||||
grpc_chttp2_transport* t,
|
||||
grpc_chttp2_stream* s,
|
||||
|
|
|
|||
|
|
@ -22,43 +22,133 @@
|
|||
|
||||
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
#include "src/core/ext/transport/chttp2/transport/frame.h"
|
||||
#include "src/core/lib/gpr/useful.h"
|
||||
#include "src/core/lib/transport/http2_errors.h"
|
||||
|
||||
const uint16_t grpc_setting_id_to_wire_id[] = {1, 2, 3, 4, 5, 6, 65027, 65028};
|
||||
namespace grpc_core {
|
||||
|
||||
bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id* out) {
|
||||
uint32_t i = wire_id - 1;
|
||||
uint32_t x = i % 256;
|
||||
uint32_t y = i / 256;
|
||||
uint32_t h = x;
|
||||
switch (y) {
|
||||
case 254:
|
||||
h += 4;
|
||||
break;
|
||||
void Http2Settings::Diff(
|
||||
bool is_first_send, const Http2Settings& old,
|
||||
absl::FunctionRef<void(uint16_t key, uint32_t value)> cb) const {
|
||||
if (header_table_size_ != old.header_table_size_) {
|
||||
cb(kHeaderTableSizeWireId, header_table_size_);
|
||||
}
|
||||
if (enable_push_ != old.enable_push_) {
|
||||
cb(kEnablePushWireId, enable_push_);
|
||||
}
|
||||
if (max_concurrent_streams_ != old.max_concurrent_streams_) {
|
||||
cb(kMaxConcurrentStreamsWireId, max_concurrent_streams_);
|
||||
}
|
||||
if (is_first_send || initial_window_size_ != old.initial_window_size_) {
|
||||
cb(kInitialWindowSizeWireId, initial_window_size_);
|
||||
}
|
||||
if (max_frame_size_ != old.max_frame_size_) {
|
||||
cb(kMaxFrameSizeWireId, max_frame_size_);
|
||||
}
|
||||
if (max_header_list_size_ != old.max_header_list_size_) {
|
||||
cb(kMaxHeaderListSizeWireId, max_header_list_size_);
|
||||
}
|
||||
if (allow_true_binary_metadata_ != old.allow_true_binary_metadata_) {
|
||||
cb(kGrpcAllowTrueBinaryMetadataWireId, allow_true_binary_metadata_);
|
||||
}
|
||||
if (preferred_receive_crypto_message_size_ !=
|
||||
old.preferred_receive_crypto_message_size_) {
|
||||
cb(kGrpcPreferredReceiveCryptoFrameSizeWireId,
|
||||
preferred_receive_crypto_message_size_);
|
||||
}
|
||||
*out = static_cast<grpc_chttp2_setting_id>(h);
|
||||
return h < GPR_ARRAY_SIZE(grpc_setting_id_to_wire_id) &&
|
||||
grpc_setting_id_to_wire_id[h] == wire_id;
|
||||
}
|
||||
|
||||
const grpc_chttp2_setting_parameters
|
||||
grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {
|
||||
{"HEADER_TABLE_SIZE", 4096u, 0u, 4294967295u,
|
||||
GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
{"ENABLE_PUSH", 1u, 0u, 1u, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
|
||||
GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
{"MAX_CONCURRENT_STREAMS", 4294967295u, 0u, 4294967295u,
|
||||
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
{"INITIAL_WINDOW_SIZE", 65535u, 0u, 2147483647u,
|
||||
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,
|
||||
GRPC_HTTP2_FLOW_CONTROL_ERROR},
|
||||
{"MAX_FRAME_SIZE", 16384u, 16384u, 16777215u,
|
||||
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
{"MAX_HEADER_LIST_SIZE", 16777216u, 0u, 16777216u,
|
||||
GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
{"GRPC_ALLOW_TRUE_BINARY_METADATA", 0u, 0u, 1u,
|
||||
GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
{"GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE", 0u, 16384u, 2147483647u,
|
||||
GRPC_CHTTP2_CLAMP_INVALID_VALUE, GRPC_HTTP2_PROTOCOL_ERROR},
|
||||
};
|
||||
std::string Http2Settings::WireIdToName(uint16_t wire_id) {
|
||||
switch (wire_id) {
|
||||
case kHeaderTableSizeWireId:
|
||||
return std::string(header_table_size_name());
|
||||
case kEnablePushWireId:
|
||||
return std::string(enable_push_name());
|
||||
case kMaxConcurrentStreamsWireId:
|
||||
return std::string(max_concurrent_streams_name());
|
||||
case kInitialWindowSizeWireId:
|
||||
return std::string(initial_window_size_name());
|
||||
case kMaxFrameSizeWireId:
|
||||
return std::string(max_frame_size_name());
|
||||
case kMaxHeaderListSizeWireId:
|
||||
return std::string(max_header_list_size_name());
|
||||
case kGrpcAllowTrueBinaryMetadataWireId:
|
||||
return std::string(allow_true_binary_metadata_name());
|
||||
case kGrpcPreferredReceiveCryptoFrameSizeWireId:
|
||||
return std::string(preferred_receive_crypto_message_size_name());
|
||||
default:
|
||||
return absl::StrCat("UNKNOWN (", wire_id, ")");
|
||||
}
|
||||
}
|
||||
|
||||
grpc_http2_error_code Http2Settings::Apply(uint16_t key, uint32_t value) {
|
||||
switch (key) {
|
||||
case kHeaderTableSizeWireId:
|
||||
header_table_size_ = value;
|
||||
break;
|
||||
case kEnablePushWireId:
|
||||
if (value > 1) return GRPC_HTTP2_PROTOCOL_ERROR;
|
||||
enable_push_ = value != 0;
|
||||
break;
|
||||
case kMaxConcurrentStreamsWireId:
|
||||
max_concurrent_streams_ = value;
|
||||
break;
|
||||
case kInitialWindowSizeWireId:
|
||||
if (value > max_initial_window_size()) {
|
||||
return GRPC_HTTP2_FLOW_CONTROL_ERROR;
|
||||
}
|
||||
initial_window_size_ = value;
|
||||
break;
|
||||
case kMaxFrameSizeWireId:
|
||||
if (value < min_max_frame_size() || value > max_max_frame_size()) {
|
||||
return GRPC_HTTP2_PROTOCOL_ERROR;
|
||||
}
|
||||
max_frame_size_ = value;
|
||||
break;
|
||||
case kMaxHeaderListSizeWireId:
|
||||
max_header_list_size_ = std::min(value, 16777216u);
|
||||
break;
|
||||
case kGrpcAllowTrueBinaryMetadataWireId:
|
||||
if (value > 1) return GRPC_HTTP2_PROTOCOL_ERROR;
|
||||
allow_true_binary_metadata_ = value != 0;
|
||||
break;
|
||||
case kGrpcPreferredReceiveCryptoFrameSizeWireId:
|
||||
preferred_receive_crypto_message_size_ =
|
||||
Clamp(value, min_preferred_receive_crypto_message_size(),
|
||||
max_preferred_receive_crypto_message_size());
|
||||
break;
|
||||
}
|
||||
return GRPC_HTTP2_NO_ERROR;
|
||||
}
|
||||
|
||||
absl::optional<Http2SettingsFrame> Http2SettingsManager::MaybeSendUpdate() {
|
||||
switch (update_state_) {
|
||||
case UpdateState::kSending:
|
||||
return absl::nullopt;
|
||||
case UpdateState::kIdle:
|
||||
if (local_ == sent_) return absl::nullopt;
|
||||
break;
|
||||
case UpdateState::kFirst:
|
||||
break;
|
||||
}
|
||||
Http2SettingsFrame frame;
|
||||
local_.Diff(update_state_ == UpdateState::kFirst, sent_,
|
||||
[&frame](uint16_t key, uint32_t value) {
|
||||
frame.settings.emplace_back(key, value);
|
||||
});
|
||||
sent_ = local_;
|
||||
update_state_ = UpdateState::kSending;
|
||||
return frame;
|
||||
}
|
||||
|
||||
bool Http2SettingsManager::AckLastSend() {
|
||||
if (update_state_ != UpdateState::kSending) return false;
|
||||
update_state_ = UpdateState::kIdle;
|
||||
acked_ = sent_;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
|
|
|||
|
|
@ -14,10 +14,6 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
|
||||
//
|
||||
// Automatically generated by tools/codegen/core/gen_settings_ids.py
|
||||
//
|
||||
|
||||
#ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H
|
||||
#define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H
|
||||
|
||||
|
|
@ -25,38 +21,147 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE = 0, // wire id 1
|
||||
GRPC_CHTTP2_SETTINGS_ENABLE_PUSH = 1, // wire id 2
|
||||
GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 2, // wire id 3
|
||||
GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 3, // wire id 4
|
||||
GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE = 4, // wire id 5
|
||||
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 5, // wire id 6
|
||||
GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA = 6, // wire id 65027
|
||||
GRPC_CHTTP2_SETTINGS_GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE =
|
||||
7, // wire id 65028
|
||||
} grpc_chttp2_setting_id;
|
||||
#include <cstdint>
|
||||
|
||||
#define GRPC_CHTTP2_NUM_SETTINGS 8
|
||||
extern const uint16_t grpc_setting_id_to_wire_id[];
|
||||
#include "absl/functional/function_ref.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id* out);
|
||||
#include "src/core/ext/transport/chttp2/transport/frame.h"
|
||||
#include "src/core/lib/gpr/useful.h"
|
||||
#include "src/core/lib/transport/http2_errors.h"
|
||||
|
||||
typedef enum {
|
||||
GRPC_CHTTP2_CLAMP_INVALID_VALUE,
|
||||
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
|
||||
} grpc_chttp2_invalid_value_behavior;
|
||||
namespace grpc_core {
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
uint32_t default_value;
|
||||
uint32_t min_value;
|
||||
uint32_t max_value;
|
||||
grpc_chttp2_invalid_value_behavior invalid_value_behavior;
|
||||
uint32_t error_value;
|
||||
} grpc_chttp2_setting_parameters;
|
||||
class Http2Settings {
|
||||
public:
|
||||
enum : uint16_t {
|
||||
kHeaderTableSizeWireId = 1,
|
||||
kEnablePushWireId = 2,
|
||||
kMaxConcurrentStreamsWireId = 3,
|
||||
kInitialWindowSizeWireId = 4,
|
||||
kMaxFrameSizeWireId = 5,
|
||||
kMaxHeaderListSizeWireId = 6,
|
||||
kGrpcAllowTrueBinaryMetadataWireId = 65027,
|
||||
kGrpcPreferredReceiveCryptoFrameSizeWireId = 65028,
|
||||
};
|
||||
|
||||
extern const grpc_chttp2_setting_parameters
|
||||
grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
|
||||
void Diff(bool is_first_send, const Http2Settings& old,
|
||||
absl::FunctionRef<void(uint16_t key, uint32_t value)> cb) const;
|
||||
GRPC_MUST_USE_RESULT grpc_http2_error_code Apply(uint16_t key,
|
||||
uint32_t value);
|
||||
uint32_t header_table_size() const { return header_table_size_; }
|
||||
uint32_t max_concurrent_streams() const { return max_concurrent_streams_; }
|
||||
uint32_t initial_window_size() const { return initial_window_size_; }
|
||||
uint32_t max_frame_size() const { return max_frame_size_; }
|
||||
uint32_t max_header_list_size() const { return max_header_list_size_; }
|
||||
uint32_t preferred_receive_crypto_message_size() const {
|
||||
return preferred_receive_crypto_message_size_;
|
||||
}
|
||||
bool enable_push() const { return enable_push_; }
|
||||
bool allow_true_binary_metadata() const {
|
||||
return allow_true_binary_metadata_;
|
||||
}
|
||||
|
||||
void SetHeaderTableSize(uint32_t x) { header_table_size_ = x; }
|
||||
void SetMaxConcurrentStreams(uint32_t x) { max_concurrent_streams_ = x; }
|
||||
void SetInitialWindowSize(uint32_t x) {
|
||||
initial_window_size_ = std::min(x, max_initial_window_size());
|
||||
}
|
||||
void SetEnablePush(bool x) { enable_push_ = x; }
|
||||
void SetMaxHeaderListSize(uint32_t x) {
|
||||
max_header_list_size_ = std::min(x, 16777216u);
|
||||
}
|
||||
void SetAllowTrueBinaryMetadata(bool x) { allow_true_binary_metadata_ = x; }
|
||||
void SetMaxFrameSize(uint32_t x) {
|
||||
max_frame_size_ = Clamp(x, min_max_frame_size(), max_max_frame_size());
|
||||
}
|
||||
void SetPreferredReceiveCryptoMessageSize(uint32_t x) {
|
||||
preferred_receive_crypto_message_size_ =
|
||||
Clamp(x, min_preferred_receive_crypto_message_size(),
|
||||
max_preferred_receive_crypto_message_size());
|
||||
}
|
||||
|
||||
static absl::string_view header_table_size_name() {
|
||||
return "HEADER_TABLE_SIZE";
|
||||
}
|
||||
static absl::string_view max_concurrent_streams_name() {
|
||||
return "MAX_CONCURRENT_STREAMS";
|
||||
}
|
||||
static absl::string_view initial_window_size_name() {
|
||||
return "INITIAL_WINDOW_SIZE";
|
||||
}
|
||||
static absl::string_view max_frame_size_name() { return "MAX_FRAME_SIZE"; }
|
||||
static absl::string_view max_header_list_size_name() {
|
||||
return "MAX_HEADER_LIST_SIZE";
|
||||
}
|
||||
static absl::string_view enable_push_name() { return "ENABLE_PUSH"; }
|
||||
static absl::string_view allow_true_binary_metadata_name() {
|
||||
return "GRPC_ALLOW_TRUE_BINARY_METADATA";
|
||||
}
|
||||
static absl::string_view preferred_receive_crypto_message_size_name() {
|
||||
return "GRPC_PREFERRED_RECEIVE_MESSAGE_SIZE";
|
||||
}
|
||||
|
||||
static uint32_t max_initial_window_size() { return 2147483647u; }
|
||||
static uint32_t max_max_frame_size() { return 16777215u; }
|
||||
static uint32_t min_max_frame_size() { return 16384u; }
|
||||
static uint32_t min_preferred_receive_crypto_message_size() { return 16384u; }
|
||||
static uint32_t max_preferred_receive_crypto_message_size() {
|
||||
return 2147483647u;
|
||||
}
|
||||
|
||||
static std::string WireIdToName(uint16_t wire_id);
|
||||
|
||||
bool operator==(const Http2Settings& rhs) const {
|
||||
return header_table_size_ == rhs.header_table_size_ &&
|
||||
max_concurrent_streams_ == rhs.max_concurrent_streams_ &&
|
||||
initial_window_size_ == rhs.initial_window_size_ &&
|
||||
max_frame_size_ == rhs.max_frame_size_ &&
|
||||
max_header_list_size_ == rhs.max_header_list_size_ &&
|
||||
preferred_receive_crypto_message_size_ ==
|
||||
rhs.preferred_receive_crypto_message_size_ &&
|
||||
enable_push_ == rhs.enable_push_ &&
|
||||
allow_true_binary_metadata_ == rhs.allow_true_binary_metadata_;
|
||||
}
|
||||
|
||||
bool operator!=(const Http2Settings& rhs) const { return !operator==(rhs); }
|
||||
|
||||
private:
|
||||
uint32_t header_table_size_ = 4096;
|
||||
uint32_t max_concurrent_streams_ = 4294967295u;
|
||||
uint32_t initial_window_size_ = 65535u;
|
||||
uint32_t max_frame_size_ = 16384u;
|
||||
uint32_t max_header_list_size_ = 16777216u;
|
||||
uint32_t preferred_receive_crypto_message_size_ = 0u;
|
||||
bool enable_push_ = true;
|
||||
bool allow_true_binary_metadata_ = false;
|
||||
};
|
||||
|
||||
class Http2SettingsManager {
|
||||
public:
|
||||
Http2Settings& mutable_local() { return local_; }
|
||||
const Http2Settings& local() const { return local_; }
|
||||
const Http2Settings& acked() const { return acked_; }
|
||||
Http2Settings& mutable_peer() { return peer_; }
|
||||
const Http2Settings& peer() const { return peer_; }
|
||||
|
||||
absl::optional<Http2SettingsFrame> MaybeSendUpdate();
|
||||
GRPC_MUST_USE_RESULT bool AckLastSend();
|
||||
|
||||
private:
|
||||
enum class UpdateState : uint8_t {
|
||||
kFirst,
|
||||
kSending,
|
||||
kIdle,
|
||||
};
|
||||
UpdateState update_state_ = UpdateState::kFirst;
|
||||
Http2Settings local_;
|
||||
Http2Settings sent_;
|
||||
Http2Settings peer_;
|
||||
Http2Settings acked_;
|
||||
};
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H
|
||||
|
|
|
|||
|
|
@ -203,18 +203,6 @@ struct grpc_chttp2_stream_link {
|
|||
grpc_chttp2_stream* next;
|
||||
grpc_chttp2_stream* prev;
|
||||
};
|
||||
// We keep several sets of connection wide parameters
|
||||
typedef enum {
|
||||
// The settings our peer has asked for (and we have acked)
|
||||
GRPC_PEER_SETTINGS = 0,
|
||||
// The settings we'd like to have
|
||||
GRPC_LOCAL_SETTINGS,
|
||||
// The settings we've published to our peer
|
||||
GRPC_SENT_SETTINGS,
|
||||
// The settings the peer has acked
|
||||
GRPC_ACKED_SETTINGS,
|
||||
GRPC_NUM_SETTING_SETS
|
||||
} grpc_chttp2_setting_set;
|
||||
|
||||
typedef enum {
|
||||
GRPC_CHTTP2_NO_GOAWAY_SEND,
|
||||
|
|
@ -359,12 +347,8 @@ struct grpc_chttp2_transport final
|
|||
|
||||
grpc_chttp2_sent_goaway_state sent_goaway_state = GRPC_CHTTP2_NO_GOAWAY_SEND;
|
||||
|
||||
/// bitmask of setting indexes to send out
|
||||
/// Hack: it's common for implementations to assume 65536 bytes initial send
|
||||
/// window -- this should by rights be 0
|
||||
uint32_t force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
/// settings values
|
||||
uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
|
||||
grpc_core::Http2SettingsManager settings;
|
||||
|
||||
grpc_event_engine::experimental::EventEngine::TaskHandle
|
||||
settings_ack_watchdog =
|
||||
|
|
@ -538,11 +522,6 @@ struct grpc_chttp2_transport final
|
|||
/// is this a client?
|
||||
bool is_client;
|
||||
|
||||
/// are the local settings dirty and need to be sent?
|
||||
bool dirtied_local_settings = true;
|
||||
/// have local settings been sent?
|
||||
bool sent_local_settings = false;
|
||||
|
||||
/// If start_bdp_ping_locked has been called
|
||||
bool bdp_ping_started = false;
|
||||
// True if pings should be acked
|
||||
|
|
|
|||
|
|
@ -357,13 +357,10 @@ absl::variant<size_t, absl::Status> grpc_chttp2_perform_read(
|
|||
}
|
||||
goto dts_fh_0; // loop
|
||||
} else if (t->incoming_frame_size >
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]) {
|
||||
return GRPC_ERROR_CREATE(
|
||||
absl::StrFormat("Frame size %d is larger than max frame size %d",
|
||||
t->incoming_frame_size,
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]));
|
||||
t->settings.acked().max_frame_size()) {
|
||||
return GRPC_ERROR_CREATE(absl::StrFormat(
|
||||
"Frame size %d is larger than max frame size %d",
|
||||
t->incoming_frame_size, t->settings.acked().max_frame_size()));
|
||||
}
|
||||
if (++cur == end) {
|
||||
return absl::OkStatus();
|
||||
|
|
@ -505,8 +502,7 @@ static grpc_error_handle init_header_skip_frame_parser(
|
|||
/*metadata_size_soft_limit=*/
|
||||
t->max_header_list_size_soft_limit,
|
||||
/*metadata_size_hard_limit=*/
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE],
|
||||
t->settings.acked().max_header_list_size(),
|
||||
hpack_boundary_type(t, is_eoh), priority_type,
|
||||
hpack_parser_log_info(t, HPackParser::LogInfo::kDontKnow));
|
||||
return absl::OkStatus();
|
||||
|
|
@ -646,10 +642,8 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|||
"ignoring grpc_chttp2_stream with non-client generated index %d",
|
||||
t->incoming_stream_id));
|
||||
return init_header_skip_frame_parser(t, priority_type, is_eoh);
|
||||
} else if (GPR_UNLIKELY(
|
||||
t->stream_map.size() + t->extra_streams >=
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS])) {
|
||||
} else if (GPR_UNLIKELY(t->stream_map.size() + t->extra_streams >=
|
||||
t->settings.acked().max_concurrent_streams())) {
|
||||
if (grpc_core::IsRfcMaxConcurrentStreamsEnabled()) {
|
||||
++t->num_pending_induced_frames;
|
||||
grpc_slice_buffer_add(
|
||||
|
|
@ -678,8 +672,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|||
t->max_concurrent_streams_policy.AdvertiseValue() &&
|
||||
grpc_core::RandomEarlyDetection(
|
||||
t->max_concurrent_streams_policy.AdvertiseValue(),
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS])
|
||||
t->settings.acked().max_concurrent_streams())
|
||||
.Reject(t->stream_map.size(), t->bitgen))) {
|
||||
// We are under the limit of max concurrent streams for the current
|
||||
// setting, but are over the next value that will be advertised.
|
||||
|
|
@ -788,15 +781,13 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
|
|||
return GRPC_ERROR_CREATE(
|
||||
"Trailing metadata frame received without an end-o-stream");
|
||||
}
|
||||
t->hpack_parser.BeginFrame(
|
||||
incoming_metadata_buffer,
|
||||
/*metadata_size_soft_limit=*/
|
||||
t->max_header_list_size_soft_limit,
|
||||
/*metadata_size_hard_limit=*/
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE],
|
||||
hpack_boundary_type(t, is_eoh), priority_type,
|
||||
hpack_parser_log_info(t, frame_type));
|
||||
t->hpack_parser.BeginFrame(incoming_metadata_buffer,
|
||||
/*metadata_size_soft_limit=*/
|
||||
t->max_header_list_size_soft_limit,
|
||||
/*metadata_size_hard_limit=*/
|
||||
t->settings.acked().max_header_list_size(),
|
||||
hpack_boundary_type(t, is_eoh), priority_type,
|
||||
hpack_parser_log_info(t, frame_type));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
|
|
@ -867,21 +858,20 @@ static grpc_error_handle init_settings_frame_parser(grpc_chttp2_transport* t) {
|
|||
|
||||
grpc_error_handle err = grpc_chttp2_settings_parser_begin_frame(
|
||||
&t->simple.settings, t->incoming_frame_size, t->incoming_frame_flags,
|
||||
t->settings[GRPC_PEER_SETTINGS]);
|
||||
t->settings.mutable_peer());
|
||||
if (!err.ok()) {
|
||||
return err;
|
||||
}
|
||||
if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
|
||||
t->max_concurrent_streams_policy.AckLastSend();
|
||||
memcpy(t->settings[GRPC_ACKED_SETTINGS], t->settings[GRPC_SENT_SETTINGS],
|
||||
GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t));
|
||||
if (!t->settings.AckLastSend()) {
|
||||
return GRPC_ERROR_CREATE("Received unexpected settings ack");
|
||||
}
|
||||
t->hpack_parser.hpack_table()->SetMaxBytes(
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
|
||||
t->settings.acked().header_table_size());
|
||||
grpc_chttp2_act_on_flowctl_action(
|
||||
t->flow_control.SetAckedInitialWindow(
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]),
|
||||
t->settings.acked().initial_window_size()),
|
||||
t, nullptr);
|
||||
if (t->settings_ack_watchdog !=
|
||||
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) {
|
||||
|
|
@ -889,7 +879,6 @@ static grpc_error_handle init_settings_frame_parser(grpc_chttp2_transport* t) {
|
|||
t->settings_ack_watchdog,
|
||||
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
|
||||
}
|
||||
t->sent_local_settings = false;
|
||||
// This is more streams than can be started in http2, so setting this
|
||||
// effictively removes the limit for the rest of the connection.
|
||||
t->num_incoming_streams_before_settings_ack =
|
||||
|
|
|
|||
|
|
@ -218,15 +218,12 @@ static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
|
|||
":peer_initwin=%d:t_win=%" PRId64 ":s_win=%d:s_delta=%" PRId64 "]",
|
||||
std::string(t->peer_string.as_string_view()).c_str(), t, s->id, staller,
|
||||
s->flow_controlled_buffer.length, s->flow_controlled_bytes_flowed,
|
||||
t->settings[GRPC_ACKED_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
|
||||
t->settings.acked().initial_window_size(),
|
||||
t->flow_control.remote_window(),
|
||||
static_cast<uint32_t>(std::max(
|
||||
int64_t{0},
|
||||
s->flow_control.remote_window_delta() +
|
||||
static_cast<int64_t>(
|
||||
t->settings[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]))),
|
||||
int64_t{0}, s->flow_control.remote_window_delta() +
|
||||
static_cast<int64_t>(
|
||||
t->settings.peer().initial_window_size()))),
|
||||
s->flow_control.remote_window_delta());
|
||||
}
|
||||
}
|
||||
|
|
@ -266,21 +263,12 @@ class WriteContext {
|
|||
}
|
||||
|
||||
void FlushSettings() {
|
||||
const bool dirty =
|
||||
t_->dirtied_local_settings ||
|
||||
t_->settings[GRPC_SENT_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] !=
|
||||
t_->max_concurrent_streams_policy.AdvertiseValue();
|
||||
if (dirty && !t_->sent_local_settings) {
|
||||
t_->settings[GRPC_LOCAL_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] =
|
||||
t_->max_concurrent_streams_policy.AdvertiseValue();
|
||||
grpc_slice_buffer_add(
|
||||
t_->outbuf.c_slice_buffer(),
|
||||
grpc_chttp2_settings_create(t_->settings[GRPC_SENT_SETTINGS],
|
||||
t_->settings[GRPC_LOCAL_SETTINGS],
|
||||
t_->force_send_settings,
|
||||
GRPC_CHTTP2_NUM_SETTINGS));
|
||||
t_->settings.mutable_local().SetMaxConcurrentStreams(
|
||||
t_->max_concurrent_streams_policy.AdvertiseValue());
|
||||
auto update = t_->settings.MaybeSendUpdate();
|
||||
if (update.has_value()) {
|
||||
grpc_core::Http2Frame frame(std::move(*update));
|
||||
Serialize(absl::Span<grpc_core::Http2Frame>(&frame, 1), t_->outbuf);
|
||||
if (t_->keepalive_timeout != grpc_core::Duration::Infinity()) {
|
||||
GPR_ASSERT(
|
||||
t_->settings_ack_watchdog ==
|
||||
|
|
@ -294,9 +282,6 @@ class WriteContext {
|
|||
grpc_chttp2_settings_timeout(std::move(t));
|
||||
});
|
||||
}
|
||||
t_->force_send_settings = false;
|
||||
t_->dirtied_local_settings = false;
|
||||
t_->sent_local_settings = true;
|
||||
t_->flow_control.FlushedSettings();
|
||||
t_->max_concurrent_streams_policy.FlushedSettings();
|
||||
grpc_core::global_stats().IncrementHttp2SettingsWrites();
|
||||
|
|
@ -336,8 +321,7 @@ class WriteContext {
|
|||
|
||||
void EnactHpackSettings() {
|
||||
t_->hpack_compressor.SetMaxTableSize(
|
||||
t_->settings[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
|
||||
t_->settings.peer().header_table_size());
|
||||
}
|
||||
|
||||
void UpdateStreamsNoLongerStalled() {
|
||||
|
|
@ -410,17 +394,14 @@ class DataSendContext {
|
|||
return static_cast<uint32_t>(std::max(
|
||||
int64_t{0},
|
||||
s_->flow_control.remote_window_delta() +
|
||||
static_cast<int64_t>(
|
||||
t_->settings[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE])));
|
||||
static_cast<int64_t>(t_->settings.peer().initial_window_size())));
|
||||
}
|
||||
|
||||
uint32_t max_outgoing() const {
|
||||
return grpc_core::Clamp<uint32_t>(
|
||||
std::min<int64_t>(
|
||||
{t_->settings[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
|
||||
stream_remote_window(), t_->flow_control.remote_window(),
|
||||
{t_->settings.peer().max_frame_size(), stream_remote_window(),
|
||||
t_->flow_control.remote_window(),
|
||||
grpc_core::IsWriteSizeCapEnabled()
|
||||
? static_cast<int64_t>(write_context_->target_write_size())
|
||||
: std::numeric_limits<uint32_t>::max()}),
|
||||
|
|
@ -494,14 +475,10 @@ class StreamWriteContext {
|
|||
grpc_core::HPackCompressor::EncodeHeaderOptions{
|
||||
s_->id, // stream_id
|
||||
false, // is_eof
|
||||
t_->settings
|
||||
[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
|
||||
0, // use_true_binary_metadata
|
||||
t_->settings
|
||||
[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], // max_frame_size
|
||||
&s_->stats.outgoing // stats
|
||||
t_->settings.peer()
|
||||
.allow_true_binary_metadata(), // use_true_binary_metadata
|
||||
t_->settings.peer().max_frame_size(), // max_frame_size
|
||||
&s_->stats.outgoing // stats
|
||||
},
|
||||
*s_->send_initial_metadata, t_->outbuf.c_slice_buffer());
|
||||
grpc_chttp2_reset_ping_clock(t_);
|
||||
|
|
@ -596,14 +573,8 @@ class StreamWriteContext {
|
|||
}
|
||||
t_->hpack_compressor.EncodeHeaders(
|
||||
grpc_core::HPackCompressor::EncodeHeaderOptions{
|
||||
s_->id, true,
|
||||
t_->settings
|
||||
[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] !=
|
||||
0,
|
||||
t_->settings[GRPC_PEER_SETTINGS]
|
||||
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
|
||||
&s_->stats.outgoing},
|
||||
s_->id, true, t_->settings.peer().allow_true_binary_metadata(),
|
||||
t_->settings.peer().max_frame_size(), &s_->stats.outgoing},
|
||||
*s_->send_trailing_metadata, t_->outbuf.c_slice_buffer());
|
||||
}
|
||||
write_context_->IncTrailingMetadataWrites();
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ CORE_SOURCE_FILES = [
|
|||
'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
|
||||
'src/core/ext/transport/chttp2/transport/decode_huff.cc',
|
||||
'src/core/ext/transport/chttp2/transport/flow_control.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_data.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
|
||||
'src/core/ext/transport/chttp2/transport/frame_ping.cc',
|
||||
|
|
|
|||
|
|
@ -446,3 +446,20 @@ grpc_cc_test(
|
|||
"//test/core/util:grpc_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
grpc_cc_test(
|
||||
name = "http2_settings_test",
|
||||
srcs = [
|
||||
"http2_settings_test.cc",
|
||||
],
|
||||
external_deps = [
|
||||
"gtest",
|
||||
],
|
||||
language = "C++",
|
||||
deps = [
|
||||
"//:gpr",
|
||||
"//:grpc",
|
||||
"//src/core:http2_settings",
|
||||
"//test/core/util:grpc_test_util",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,514 @@
|
|||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace grpc_core {
|
||||
|
||||
TEST(Http2SettingsTest, CanSetAndRetrieveSettings) {
|
||||
Http2Settings settings;
|
||||
settings.SetHeaderTableSize(1);
|
||||
settings.SetEnablePush(true);
|
||||
settings.SetMaxConcurrentStreams(3);
|
||||
settings.SetInitialWindowSize(4);
|
||||
settings.SetMaxFrameSize(50000);
|
||||
settings.SetMaxHeaderListSize(6);
|
||||
settings.SetAllowTrueBinaryMetadata(true);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(77777);
|
||||
EXPECT_EQ(settings.header_table_size(), 1u);
|
||||
EXPECT_EQ(settings.enable_push(), true);
|
||||
EXPECT_EQ(settings.max_concurrent_streams(), 3u);
|
||||
EXPECT_EQ(settings.initial_window_size(), 4u);
|
||||
EXPECT_EQ(settings.max_frame_size(), 50000u);
|
||||
EXPECT_EQ(settings.max_header_list_size(), 6u);
|
||||
EXPECT_EQ(settings.allow_true_binary_metadata(), true);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 77777u);
|
||||
settings.SetHeaderTableSize(10);
|
||||
settings.SetEnablePush(false);
|
||||
settings.SetMaxConcurrentStreams(30);
|
||||
settings.SetInitialWindowSize(40);
|
||||
settings.SetMaxFrameSize(5000000);
|
||||
settings.SetMaxHeaderListSize(60);
|
||||
settings.SetAllowTrueBinaryMetadata(false);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(70000);
|
||||
EXPECT_EQ(settings.header_table_size(), 10u);
|
||||
EXPECT_EQ(settings.enable_push(), false);
|
||||
EXPECT_EQ(settings.max_concurrent_streams(), 30u);
|
||||
EXPECT_EQ(settings.initial_window_size(), 40u);
|
||||
EXPECT_EQ(settings.max_frame_size(), 5000000u);
|
||||
EXPECT_EQ(settings.max_header_list_size(), 60u);
|
||||
EXPECT_EQ(settings.allow_true_binary_metadata(), false);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 70000u);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, InitialWindowSizeLimits) {
|
||||
Http2Settings settings;
|
||||
settings.SetInitialWindowSize(0);
|
||||
EXPECT_EQ(settings.initial_window_size(), 0u);
|
||||
settings.SetInitialWindowSize(0x7fffffff);
|
||||
EXPECT_EQ(settings.initial_window_size(), 0x7fffffffu);
|
||||
settings.SetInitialWindowSize(0x80000000);
|
||||
EXPECT_EQ(settings.initial_window_size(), 0x7fffffffu);
|
||||
settings.SetInitialWindowSize(0xffffffff);
|
||||
EXPECT_EQ(settings.initial_window_size(), 0x7fffffffu);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, MaxFrameSizeLimits) {
|
||||
Http2Settings settings;
|
||||
settings.SetMaxFrameSize(0);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16384u);
|
||||
settings.SetMaxFrameSize(16384);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16384u);
|
||||
settings.SetMaxFrameSize(16385);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16385u);
|
||||
settings.SetMaxFrameSize(16777215);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16777215u);
|
||||
settings.SetMaxFrameSize(16777216);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16777215u);
|
||||
settings.SetMaxFrameSize(16777217);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16777215u);
|
||||
settings.SetMaxFrameSize(0xffffffff);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16777215u);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, PreferredReceiveCryptoMessageSize) {
|
||||
Http2Settings settings;
|
||||
settings.SetPreferredReceiveCryptoMessageSize(0);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16384u);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(16384);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16384u);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(16385);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16385u);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(16777215);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16777215u);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(16777216);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16777216u);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(16777217);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16777217u);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(0x7fffffff);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 0x7fffffffu);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(0x80000000);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 0x7fffffffu);
|
||||
settings.SetPreferredReceiveCryptoMessageSize(0xffffffff);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 0x7fffffffu);
|
||||
}
|
||||
|
||||
namespace {
|
||||
using KeyValue = std::pair<uint16_t, uint32_t>;
|
||||
using KeyValueVec = std::vector<KeyValue>;
|
||||
|
||||
KeyValueVec Diff(const Http2Settings& a, const Http2Settings& b,
|
||||
bool is_first_send) {
|
||||
KeyValueVec diffs;
|
||||
a.Diff(is_first_send, b, [&diffs](uint16_t key, uint32_t value) {
|
||||
diffs.emplace_back(key, value);
|
||||
});
|
||||
return diffs;
|
||||
}
|
||||
|
||||
bool operator==(const KeyValue& a, const Http2SettingsFrame::Setting& b) {
|
||||
return a.first == b.id && a.second == b.value;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnFreshlyInitializedSettings) {
|
||||
const Http2Settings settings1;
|
||||
const Http2Settings settings2;
|
||||
EXPECT_THAT(Diff(settings1, settings2, false), ::testing::IsEmpty());
|
||||
EXPECT_THAT(Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(KeyValue{4, 65535}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithOneValueSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}));
|
||||
EXPECT_THAT(
|
||||
Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{4, 65535}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithTwoValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0}));
|
||||
EXPECT_THAT(Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{4, 65535}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithThreeValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
settings1.SetMaxConcurrentStreams(3);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{3, 3}));
|
||||
EXPECT_THAT(
|
||||
Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{3, 3}, KeyValue{4, 65535}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithFourValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
settings1.SetMaxConcurrentStreams(3);
|
||||
settings1.SetInitialWindowSize(4);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{3, 3}, KeyValue{4, 4}));
|
||||
EXPECT_THAT(Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{3, 3}, KeyValue{4, 4}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithFiveValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
settings1.SetMaxConcurrentStreams(3);
|
||||
settings1.SetInitialWindowSize(4);
|
||||
settings1.SetMaxFrameSize(50000);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{3, 3}, KeyValue{4, 4},
|
||||
KeyValue{5, 50000}));
|
||||
EXPECT_THAT(Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(KeyValue{1, 1}, KeyValue{2, 0},
|
||||
KeyValue{3, 3}, KeyValue{4, 4},
|
||||
KeyValue{5, 50000}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithSixValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
settings1.SetMaxConcurrentStreams(3);
|
||||
settings1.SetInitialWindowSize(4);
|
||||
settings1.SetMaxFrameSize(50000);
|
||||
settings1.SetMaxHeaderListSize(6);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(
|
||||
KeyValue{1, 1}, KeyValue{2, 0}, KeyValue{3, 3},
|
||||
KeyValue{4, 4}, KeyValue{5, 50000}, KeyValue{6, 6}));
|
||||
EXPECT_THAT(Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(
|
||||
KeyValue{1, 1}, KeyValue{2, 0}, KeyValue{3, 3},
|
||||
KeyValue{4, 4}, KeyValue{5, 50000}, KeyValue{6, 6}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithSevenValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
settings1.SetMaxConcurrentStreams(3);
|
||||
settings1.SetInitialWindowSize(4);
|
||||
settings1.SetMaxFrameSize(50000);
|
||||
settings1.SetMaxHeaderListSize(6);
|
||||
settings1.SetAllowTrueBinaryMetadata(true);
|
||||
EXPECT_THAT(
|
||||
Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(
|
||||
KeyValue{1, 1}, KeyValue{2, 0}, KeyValue{3, 3}, KeyValue{4, 4},
|
||||
KeyValue{5, 50000}, KeyValue{6, 6}, KeyValue{65027, 1}));
|
||||
EXPECT_THAT(
|
||||
Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(
|
||||
KeyValue{1, 1}, KeyValue{2, 0}, KeyValue{3, 3}, KeyValue{4, 4},
|
||||
KeyValue{5, 50000}, KeyValue{6, 6}, KeyValue{65027, 1}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, DiffOnSettingsWithEightValuesSet) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
settings1.SetEnablePush(false);
|
||||
settings1.SetMaxConcurrentStreams(3);
|
||||
settings1.SetInitialWindowSize(4);
|
||||
settings1.SetMaxFrameSize(50000);
|
||||
settings1.SetMaxHeaderListSize(6);
|
||||
settings1.SetAllowTrueBinaryMetadata(true);
|
||||
settings1.SetPreferredReceiveCryptoMessageSize(77777);
|
||||
EXPECT_THAT(Diff(settings1, settings2, false),
|
||||
::testing::UnorderedElementsAre(
|
||||
KeyValue{1, 1}, KeyValue{2, 0}, KeyValue{3, 3},
|
||||
KeyValue{4, 4}, KeyValue{5, 50000}, KeyValue{6, 6},
|
||||
KeyValue{65027, 1}, KeyValue{65028, 77777}));
|
||||
EXPECT_THAT(Diff(settings1, settings2, true),
|
||||
::testing::UnorderedElementsAre(
|
||||
KeyValue{1, 1}, KeyValue{2, 0}, KeyValue{3, 3},
|
||||
KeyValue{4, 4}, KeyValue{5, 50000}, KeyValue{6, 6},
|
||||
KeyValue{65027, 1}, KeyValue{65028, 77777}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingHeaderTableSizeChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetHeaderTableSize(1);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetHeaderTableSize(1);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetHeaderTableSize(2);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingEnablePushChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetEnablePush(false);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetEnablePush(false);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetEnablePush(true);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingMaxConcurrentStreamsChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetMaxConcurrentStreams(1);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetMaxConcurrentStreams(1);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetMaxConcurrentStreams(2);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingInitialWindowSizeChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetInitialWindowSize(1);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetInitialWindowSize(1);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetInitialWindowSize(2);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingMaxFrameSizeChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetMaxFrameSize(100000);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetMaxFrameSize(100000);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetMaxFrameSize(200000);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingMaxHeaderListSizeChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetMaxHeaderListSize(1);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetMaxHeaderListSize(1);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetMaxHeaderListSize(2);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ChangingAllowTrueBinaryMetadataChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetAllowTrueBinaryMetadata(true);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetAllowTrueBinaryMetadata(true);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetAllowTrueBinaryMetadata(false);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest,
|
||||
ChangingPreferredReceiveCryptoMessageSizeChangesEquality) {
|
||||
Http2Settings settings1;
|
||||
Http2Settings settings2;
|
||||
settings1.SetPreferredReceiveCryptoMessageSize(100000);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
settings2.SetPreferredReceiveCryptoMessageSize(100000);
|
||||
EXPECT_EQ(settings1, settings2);
|
||||
settings2.SetPreferredReceiveCryptoMessageSize(200000);
|
||||
EXPECT_NE(settings1, settings2);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, WireIdToNameWorks) {
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(1), "HEADER_TABLE_SIZE");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(2), "ENABLE_PUSH");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(3), "MAX_CONCURRENT_STREAMS");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(4), "INITIAL_WINDOW_SIZE");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(5), "MAX_FRAME_SIZE");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(6), "MAX_HEADER_LIST_SIZE");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(65027),
|
||||
"GRPC_ALLOW_TRUE_BINARY_METADATA");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(65028),
|
||||
"GRPC_PREFERRED_RECEIVE_MESSAGE_SIZE");
|
||||
EXPECT_EQ(Http2Settings::WireIdToName(65029), "UNKNOWN (65029)");
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyHeaderTableSizeWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(1, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.header_table_size(), 1u);
|
||||
EXPECT_EQ(settings.Apply(1, 0x7fffffff), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.header_table_size(), 0x7fffffffu);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyEnablePushWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(2, 0), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.enable_push(), false);
|
||||
EXPECT_EQ(settings.Apply(2, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.enable_push(), true);
|
||||
EXPECT_EQ(settings.Apply(2, 2), GRPC_HTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyMaxConcurrentStreamsWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(3, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.max_concurrent_streams(), 1u);
|
||||
EXPECT_EQ(settings.Apply(3, 0x7fffffff), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.max_concurrent_streams(), 0x7fffffffu);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyInitialWindowSizeWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(4, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.initial_window_size(), 1u);
|
||||
EXPECT_EQ(settings.Apply(4, 0x7fffffff), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.initial_window_size(), 0x7fffffffu);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyMaxFrameSizeWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(5, 16384), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16384u);
|
||||
EXPECT_EQ(settings.Apply(5, 16777215), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.max_frame_size(), 16777215);
|
||||
EXPECT_EQ(settings.Apply(5, 16383), GRPC_HTTP2_PROTOCOL_ERROR);
|
||||
EXPECT_EQ(settings.Apply(5, 16777216), GRPC_HTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyMaxHeaderListSizeWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(6, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.max_header_list_size(), 1u);
|
||||
EXPECT_EQ(settings.Apply(6, 0x7fffffff), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.max_header_list_size(), 16777216);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyAllowTrueBinaryMetadataWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(65027, 0), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.allow_true_binary_metadata(), false);
|
||||
EXPECT_EQ(settings.Apply(65027, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.allow_true_binary_metadata(), true);
|
||||
EXPECT_EQ(settings.Apply(65027, 2), GRPC_HTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsTest, ApplyPreferredReceiveCryptoMessageSizeWorks) {
|
||||
Http2Settings settings;
|
||||
EXPECT_EQ(settings.Apply(65028, 1), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 16384u);
|
||||
EXPECT_EQ(settings.Apply(65028, 0x7fffffff), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 0x7fffffffu);
|
||||
EXPECT_EQ(settings.Apply(65028, 0x80000000), GRPC_HTTP2_NO_ERROR);
|
||||
EXPECT_EQ(settings.preferred_receive_crypto_message_size(), 0x7fffffffu);
|
||||
}
|
||||
|
||||
namespace {
|
||||
MATCHER_P(SettingsFrame, settings, "") {
|
||||
if (!arg.has_value()) {
|
||||
*result_listener << "Expected a settings frame, got nothing";
|
||||
return false;
|
||||
}
|
||||
if (arg->ack) {
|
||||
*result_listener << "Expected a settings frame, got an ack";
|
||||
return false;
|
||||
}
|
||||
if (arg->settings.size() != settings.size()) {
|
||||
*result_listener << "Expected settings frame with " << settings.size()
|
||||
<< " settings, got " << arg->settings.size();
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < settings.size(); i++) {
|
||||
bool found = false;
|
||||
for (size_t j = 0; j < arg->settings.size(); j++) {
|
||||
if (settings[i] == arg->settings[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
*result_listener << "Expected settings frame with setting "
|
||||
<< settings[i].first << " = " << settings[i].second
|
||||
<< ", but it was not found";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(Http2SettingsManagerTest, ImmediatelyNeedsToSend) {
|
||||
Http2SettingsManager settings_manager;
|
||||
EXPECT_THAT(settings_manager.MaybeSendUpdate(),
|
||||
SettingsFrame(KeyValueVec{{4, 65535}}));
|
||||
}
|
||||
|
||||
TEST(Http2SettingsManagerTest, SendAckWorks) {
|
||||
Http2SettingsManager settings_manager;
|
||||
settings_manager.mutable_local().SetInitialWindowSize(100000);
|
||||
EXPECT_EQ(settings_manager.acked().initial_window_size(), 65535u);
|
||||
EXPECT_THAT(settings_manager.MaybeSendUpdate(),
|
||||
SettingsFrame(KeyValueVec{{4, 100000}}));
|
||||
EXPECT_TRUE(settings_manager.AckLastSend());
|
||||
EXPECT_EQ(settings_manager.acked().initial_window_size(), 100000u);
|
||||
}
|
||||
|
||||
TEST(Http2SettingsManagerTest, AckWithoutSendFails) {
|
||||
Http2SettingsManager settings_manager;
|
||||
EXPECT_FALSE(settings_manager.AckLastSend());
|
||||
}
|
||||
|
||||
TEST(Http2SettingsManagerTest, AckAfterAckFails) {
|
||||
Http2SettingsManager settings_manager;
|
||||
settings_manager.mutable_local().SetInitialWindowSize(100000);
|
||||
EXPECT_THAT(settings_manager.MaybeSendUpdate(),
|
||||
SettingsFrame(KeyValueVec{{4, 100000}}));
|
||||
EXPECT_TRUE(settings_manager.AckLastSend());
|
||||
EXPECT_FALSE(settings_manager.AckLastSend());
|
||||
}
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2017 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import collections
|
||||
import sys
|
||||
|
||||
import perfection
|
||||
|
||||
_MAX_HEADER_LIST_SIZE = 16 * 1024 * 1024
|
||||
|
||||
Setting = collections.namedtuple("Setting", "id default min max on_error")
|
||||
OnError = collections.namedtuple("OnError", "behavior code")
|
||||
clamp_invalid_value = OnError("CLAMP_INVALID_VALUE", "PROTOCOL_ERROR")
|
||||
disconnect_on_invalid_value = lambda e: OnError(
|
||||
"DISCONNECT_ON_INVALID_VALUE", e
|
||||
)
|
||||
DecoratedSetting = collections.namedtuple(
|
||||
"DecoratedSetting", "enum name setting"
|
||||
)
|
||||
|
||||
_SETTINGS = {
|
||||
"HEADER_TABLE_SIZE": Setting(1, 4096, 0, 0xFFFFFFFF, clamp_invalid_value),
|
||||
"ENABLE_PUSH": Setting(
|
||||
2, 1, 0, 1, disconnect_on_invalid_value("PROTOCOL_ERROR")
|
||||
),
|
||||
"MAX_CONCURRENT_STREAMS": Setting(
|
||||
3,
|
||||
0xFFFFFFFF,
|
||||
0,
|
||||
0xFFFFFFFF,
|
||||
disconnect_on_invalid_value("PROTOCOL_ERROR"),
|
||||
),
|
||||
"INITIAL_WINDOW_SIZE": Setting(
|
||||
4,
|
||||
65535,
|
||||
0,
|
||||
0x7FFFFFFF,
|
||||
disconnect_on_invalid_value("FLOW_CONTROL_ERROR"),
|
||||
),
|
||||
"MAX_FRAME_SIZE": Setting(
|
||||
5, 16384, 16384, 16777215, disconnect_on_invalid_value("PROTOCOL_ERROR")
|
||||
),
|
||||
"MAX_HEADER_LIST_SIZE": Setting(
|
||||
6, _MAX_HEADER_LIST_SIZE, 0, _MAX_HEADER_LIST_SIZE, clamp_invalid_value
|
||||
),
|
||||
"GRPC_ALLOW_TRUE_BINARY_METADATA": Setting(
|
||||
0xFE03, 0, 0, 1, clamp_invalid_value
|
||||
),
|
||||
"GRPC_PREFERRED_RECEIVE_CRYPTO_FRAME_SIZE": Setting(
|
||||
0xFE04, 0, 16384, 0x7FFFFFFF, clamp_invalid_value
|
||||
),
|
||||
}
|
||||
|
||||
H = open("src/core/ext/transport/chttp2/transport/http2_settings.h", "w")
|
||||
C = open("src/core/ext/transport/chttp2/transport/http2_settings.cc", "w")
|
||||
|
||||
|
||||
# utility: print a big comment block into a set of files
|
||||
def put_banner(files, banner):
|
||||
for f in files:
|
||||
print("/*", file=f)
|
||||
for line in banner:
|
||||
print(" * %s" % line, file=f)
|
||||
print(" */", file=f)
|
||||
print(file=f)
|
||||
|
||||
|
||||
# copy-paste copyright notice from this file
|
||||
with open(sys.argv[0]) as my_source:
|
||||
copyright = []
|
||||
for line in my_source:
|
||||
if line[0] != "#":
|
||||
break
|
||||
for line in my_source:
|
||||
if line[0] == "#":
|
||||
copyright.append(line)
|
||||
break
|
||||
for line in my_source:
|
||||
if line[0] != "#":
|
||||
break
|
||||
copyright.append(line)
|
||||
put_banner([H, C], [line[2:].rstrip() for line in copyright])
|
||||
|
||||
put_banner(
|
||||
[H, C],
|
||||
["Automatically generated by tools/codegen/core/gen_settings_ids.py"],
|
||||
)
|
||||
|
||||
print(
|
||||
"#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H", file=H
|
||||
)
|
||||
print(
|
||||
"#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H", file=H
|
||||
)
|
||||
print(file=H)
|
||||
print("#include <grpc/support/port_platform.h>", file=H)
|
||||
print("#include <stdint.h>", file=H)
|
||||
print(file=H)
|
||||
|
||||
print("#include <grpc/support/port_platform.h>", file=C)
|
||||
print(
|
||||
'#include "src/core/ext/transport/chttp2/transport/http2_settings.h"',
|
||||
file=C,
|
||||
)
|
||||
print(file=C)
|
||||
print('#include "src/core/lib/gpr/useful.h"', file=C)
|
||||
print('#include "src/core/lib/transport/http2_errors.h"', file=C)
|
||||
print(file=C)
|
||||
|
||||
p = perfection.hash_parameters(sorted(x.id for x in list(_SETTINGS.values())))
|
||||
print(p)
|
||||
|
||||
|
||||
def hash(i):
|
||||
i += p.offset
|
||||
x = i % p.t
|
||||
y = i // p.t
|
||||
return x + p.r[y]
|
||||
|
||||
|
||||
decorated_settings = [
|
||||
DecoratedSetting(hash(setting.id), name, setting)
|
||||
for name, setting in _SETTINGS.items()
|
||||
]
|
||||
|
||||
print("typedef enum {", file=H)
|
||||
for decorated_setting in sorted(decorated_settings):
|
||||
print(
|
||||
" GRPC_CHTTP2_SETTINGS_%s = %d, /* wire id %d */"
|
||||
% (
|
||||
decorated_setting.name,
|
||||
decorated_setting.enum,
|
||||
decorated_setting.setting.id,
|
||||
),
|
||||
file=H,
|
||||
)
|
||||
print("} grpc_chttp2_setting_id;", file=H)
|
||||
print(file=H)
|
||||
print(
|
||||
"#define GRPC_CHTTP2_NUM_SETTINGS %d"
|
||||
% (max(x.enum for x in decorated_settings) + 1),
|
||||
file=H,
|
||||
)
|
||||
|
||||
print("extern const uint16_t grpc_setting_id_to_wire_id[];", file=H)
|
||||
print(
|
||||
"const uint16_t grpc_setting_id_to_wire_id[] = {%s};"
|
||||
% ",".join("%d" % s for s in p.slots),
|
||||
file=C,
|
||||
)
|
||||
print(file=H)
|
||||
print(
|
||||
(
|
||||
"bool grpc_wire_id_to_setting_id(uint32_t wire_id,"
|
||||
" grpc_chttp2_setting_id *out);"
|
||||
),
|
||||
file=H,
|
||||
)
|
||||
cgargs = {
|
||||
"r": ",".join("%d" % (r if r is not None else 0) for r in p.r),
|
||||
"t": p.t,
|
||||
"offset": abs(p.offset),
|
||||
"offset_sign": "+" if p.offset > 0 else "-",
|
||||
}
|
||||
print(
|
||||
"""
|
||||
bool grpc_wire_id_to_setting_id(uint32_t wire_id, grpc_chttp2_setting_id *out) {
|
||||
uint32_t i = wire_id %(offset_sign)s %(offset)d;
|
||||
uint32_t x = i %% %(t)d;
|
||||
uint32_t y = i / %(t)d;
|
||||
uint32_t h = x;
|
||||
switch (y) {
|
||||
"""
|
||||
% cgargs,
|
||||
file=C,
|
||||
)
|
||||
for i, r in enumerate(p.r):
|
||||
if not r:
|
||||
continue
|
||||
if r < 0:
|
||||
print("case %d: h -= %d; break;" % (i, -r), file=C)
|
||||
else:
|
||||
print("case %d: h += %d; break;" % (i, r), file=C)
|
||||
print(
|
||||
"""
|
||||
}
|
||||
*out = static_cast<grpc_chttp2_setting_id>(h);
|
||||
return h < GPR_ARRAY_SIZE(grpc_setting_id_to_wire_id) && grpc_setting_id_to_wire_id[h] == wire_id;
|
||||
}
|
||||
"""
|
||||
% cgargs,
|
||||
file=C,
|
||||
)
|
||||
|
||||
print(
|
||||
"""
|
||||
typedef enum {
|
||||
GRPC_CHTTP2_CLAMP_INVALID_VALUE,
|
||||
GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE
|
||||
} grpc_chttp2_invalid_value_behavior;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
uint32_t default_value;
|
||||
uint32_t min_value;
|
||||
uint32_t max_value;
|
||||
grpc_chttp2_invalid_value_behavior invalid_value_behavior;
|
||||
uint32_t error_value;
|
||||
} grpc_chttp2_setting_parameters;
|
||||
|
||||
extern const grpc_chttp2_setting_parameters grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
|
||||
""",
|
||||
file=H,
|
||||
)
|
||||
print(
|
||||
(
|
||||
"const grpc_chttp2_setting_parameters"
|
||||
" grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS] = {"
|
||||
),
|
||||
file=C,
|
||||
)
|
||||
i = 0
|
||||
for decorated_setting in sorted(decorated_settings):
|
||||
while i < decorated_setting.enum:
|
||||
print(
|
||||
(
|
||||
"{NULL, 0, 0, 0, GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE,"
|
||||
" GRPC_HTTP2_PROTOCOL_ERROR},"
|
||||
),
|
||||
file=C,
|
||||
)
|
||||
i += 1
|
||||
print(
|
||||
'{"%s", %du, %du, %du, GRPC_CHTTP2_%s, GRPC_HTTP2_%s},'
|
||||
% (
|
||||
decorated_setting.name,
|
||||
decorated_setting.setting.default,
|
||||
decorated_setting.setting.min,
|
||||
decorated_setting.setting.max,
|
||||
decorated_setting.setting.on_error.behavior,
|
||||
decorated_setting.setting.on_error.code,
|
||||
),
|
||||
file=C,
|
||||
)
|
||||
i += 1
|
||||
print("};", file=C)
|
||||
|
||||
print(file=H)
|
||||
print(
|
||||
"#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H */",
|
||||
file=H,
|
||||
)
|
||||
|
||||
H.close()
|
||||
C.close()
|
||||
|
|
@ -1293,6 +1293,8 @@ src/core/ext/transport/chttp2/transport/decode_huff.cc \
|
|||
src/core/ext/transport/chttp2/transport/decode_huff.h \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.h \
|
||||
src/core/ext/transport/chttp2/transport/frame.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame.h \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.h \
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc \
|
||||
|
|
|
|||
|
|
@ -1068,6 +1068,8 @@ src/core/ext/transport/chttp2/transport/decode_huff.cc \
|
|||
src/core/ext/transport/chttp2/transport/decode_huff.h \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.cc \
|
||||
src/core/ext/transport/chttp2/transport/flow_control.h \
|
||||
src/core/ext/transport/chttp2/transport/frame.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame.h \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.cc \
|
||||
src/core/ext/transport/chttp2/transport/frame_data.h \
|
||||
src/core/ext/transport/chttp2/transport/frame_goaway.cc \
|
||||
|
|
|
|||
|
|
@ -4727,6 +4727,30 @@
|
|||
],
|
||||
"uses_polling": true
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
"ci_platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
],
|
||||
"cpu_cost": 1.0,
|
||||
"exclude_configs": [],
|
||||
"exclude_iomgrs": [],
|
||||
"flaky": false,
|
||||
"gtest": true,
|
||||
"language": "c++",
|
||||
"name": "http2_settings_test",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"mac",
|
||||
"posix",
|
||||
"windows"
|
||||
],
|
||||
"uses_polling": true
|
||||
},
|
||||
{
|
||||
"args": [],
|
||||
"benchmark": false,
|
||||
|
|
|
|||
Loading…
Reference in New Issue