diff options
Diffstat (limited to 'src/core/ext/transport/chttp2/transport/http2_settings.cc')
-rw-r--r-- | src/core/ext/transport/chttp2/transport/http2_settings.cc | 154 |
1 files changed, 122 insertions, 32 deletions
diff --git a/src/core/ext/transport/chttp2/transport/http2_settings.cc b/src/core/ext/transport/chttp2/transport/http2_settings.cc index d966a7aebe..d9e4341250 100644 --- a/src/core/ext/transport/chttp2/transport/http2_settings.cc +++ b/src/core/ext/transport/chttp2/transport/http2_settings.cc @@ -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 { + +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_); + } +} + +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; +} -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; +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; } - *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; + 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; } -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}, -}; +} // namespace grpc_core |