1 // 2 // Copyright 2017 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H 18 #define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H 19 20 #include <grpc/support/port_platform.h> 21 #include <stdint.h> 22 23 #include <cstdint> 24 25 #include "absl/functional/function_ref.h" 26 #include "absl/strings/string_view.h" 27 #include "absl/types/optional.h" 28 #include "src/core/ext/transport/chttp2/transport/frame.h" 29 #include "src/core/lib/transport/http2_errors.h" 30 #include "src/core/util/useful.h" 31 32 namespace grpc_core { 33 34 class Http2Settings { 35 public: 36 enum : uint16_t { 37 kHeaderTableSizeWireId = 1, 38 kEnablePushWireId = 2, 39 kMaxConcurrentStreamsWireId = 3, 40 kInitialWindowSizeWireId = 4, 41 kMaxFrameSizeWireId = 5, 42 kMaxHeaderListSizeWireId = 6, 43 kGrpcAllowTrueBinaryMetadataWireId = 65027, 44 kGrpcPreferredReceiveCryptoFrameSizeWireId = 65028, 45 kGrpcAllowSecurityFrameWireId = 65029, 46 }; 47 48 void Diff(bool is_first_send, const Http2Settings& old, 49 absl::FunctionRef<void(uint16_t key, uint32_t value)> cb) const; 50 GRPC_MUST_USE_RESULT grpc_http2_error_code Apply(uint16_t key, 51 uint32_t value); header_table_size()52 uint32_t header_table_size() const { return header_table_size_; } max_concurrent_streams()53 uint32_t max_concurrent_streams() const { return max_concurrent_streams_; } initial_window_size()54 uint32_t initial_window_size() const { return initial_window_size_; } max_frame_size()55 uint32_t max_frame_size() const { return max_frame_size_; } max_header_list_size()56 uint32_t max_header_list_size() const { return max_header_list_size_; } preferred_receive_crypto_message_size()57 uint32_t preferred_receive_crypto_message_size() const { 58 return preferred_receive_crypto_message_size_; 59 } enable_push()60 bool enable_push() const { return enable_push_; } allow_true_binary_metadata()61 bool allow_true_binary_metadata() const { 62 return allow_true_binary_metadata_; 63 } allow_security_frame()64 bool allow_security_frame() const { return allow_security_frame_; } 65 SetHeaderTableSize(uint32_t x)66 void SetHeaderTableSize(uint32_t x) { header_table_size_ = x; } SetMaxConcurrentStreams(uint32_t x)67 void SetMaxConcurrentStreams(uint32_t x) { max_concurrent_streams_ = x; } SetInitialWindowSize(uint32_t x)68 void SetInitialWindowSize(uint32_t x) { 69 initial_window_size_ = std::min(x, max_initial_window_size()); 70 } SetEnablePush(bool x)71 void SetEnablePush(bool x) { enable_push_ = x; } SetMaxHeaderListSize(uint32_t x)72 void SetMaxHeaderListSize(uint32_t x) { 73 max_header_list_size_ = std::min(x, 16777216u); 74 } SetAllowTrueBinaryMetadata(bool x)75 void SetAllowTrueBinaryMetadata(bool x) { allow_true_binary_metadata_ = x; } SetMaxFrameSize(uint32_t x)76 void SetMaxFrameSize(uint32_t x) { 77 max_frame_size_ = Clamp(x, min_max_frame_size(), max_max_frame_size()); 78 } SetPreferredReceiveCryptoMessageSize(uint32_t x)79 void SetPreferredReceiveCryptoMessageSize(uint32_t x) { 80 preferred_receive_crypto_message_size_ = 81 Clamp(x, min_preferred_receive_crypto_message_size(), 82 max_preferred_receive_crypto_message_size()); 83 } SetAllowSecurityFrame(bool x)84 void SetAllowSecurityFrame(bool x) { allow_security_frame_ = x; } 85 header_table_size_name()86 static absl::string_view header_table_size_name() { 87 return "HEADER_TABLE_SIZE"; 88 } max_concurrent_streams_name()89 static absl::string_view max_concurrent_streams_name() { 90 return "MAX_CONCURRENT_STREAMS"; 91 } initial_window_size_name()92 static absl::string_view initial_window_size_name() { 93 return "INITIAL_WINDOW_SIZE"; 94 } max_frame_size_name()95 static absl::string_view max_frame_size_name() { return "MAX_FRAME_SIZE"; } max_header_list_size_name()96 static absl::string_view max_header_list_size_name() { 97 return "MAX_HEADER_LIST_SIZE"; 98 } enable_push_name()99 static absl::string_view enable_push_name() { return "ENABLE_PUSH"; } allow_true_binary_metadata_name()100 static absl::string_view allow_true_binary_metadata_name() { 101 return "GRPC_ALLOW_TRUE_BINARY_METADATA"; 102 } preferred_receive_crypto_message_size_name()103 static absl::string_view preferred_receive_crypto_message_size_name() { 104 return "GRPC_PREFERRED_RECEIVE_MESSAGE_SIZE"; 105 } allow_security_frame_name()106 static absl::string_view allow_security_frame_name() { 107 return "GRPC_ALLOW_SECURITY_FRAME"; 108 } 109 max_initial_window_size()110 static uint32_t max_initial_window_size() { return 2147483647u; } max_max_frame_size()111 static uint32_t max_max_frame_size() { return 16777215u; } min_max_frame_size()112 static uint32_t min_max_frame_size() { return 16384u; } min_preferred_receive_crypto_message_size()113 static uint32_t min_preferred_receive_crypto_message_size() { return 16384u; } max_preferred_receive_crypto_message_size()114 static uint32_t max_preferred_receive_crypto_message_size() { 115 return 2147483647u; 116 } 117 118 static std::string WireIdToName(uint16_t wire_id); 119 120 bool operator==(const Http2Settings& rhs) const { 121 return header_table_size_ == rhs.header_table_size_ && 122 max_concurrent_streams_ == rhs.max_concurrent_streams_ && 123 initial_window_size_ == rhs.initial_window_size_ && 124 max_frame_size_ == rhs.max_frame_size_ && 125 max_header_list_size_ == rhs.max_header_list_size_ && 126 preferred_receive_crypto_message_size_ == 127 rhs.preferred_receive_crypto_message_size_ && 128 enable_push_ == rhs.enable_push_ && 129 allow_true_binary_metadata_ == rhs.allow_true_binary_metadata_ && 130 allow_security_frame_ == rhs.allow_security_frame_; 131 } 132 133 bool operator!=(const Http2Settings& rhs) const { return !operator==(rhs); } 134 135 private: 136 uint32_t header_table_size_ = 4096; 137 uint32_t max_concurrent_streams_ = 4294967295u; 138 uint32_t initial_window_size_ = 65535u; 139 uint32_t max_frame_size_ = 16384u; 140 uint32_t max_header_list_size_ = 16777216u; 141 uint32_t preferred_receive_crypto_message_size_ = 0u; 142 bool enable_push_ = true; 143 bool allow_true_binary_metadata_ = false; 144 bool allow_security_frame_ = false; 145 }; 146 147 class Http2SettingsManager { 148 public: mutable_local()149 Http2Settings& mutable_local() { return local_; } local()150 const Http2Settings& local() const { return local_; } acked()151 const Http2Settings& acked() const { return acked_; } mutable_peer()152 Http2Settings& mutable_peer() { return peer_; } peer()153 const Http2Settings& peer() const { return peer_; } 154 155 absl::optional<Http2SettingsFrame> MaybeSendUpdate(); 156 GRPC_MUST_USE_RESULT bool AckLastSend(); 157 158 private: 159 enum class UpdateState : uint8_t { 160 kFirst, 161 kSending, 162 kIdle, 163 }; 164 UpdateState update_state_ = UpdateState::kFirst; 165 Http2Settings local_; 166 Http2Settings sent_; 167 Http2Settings peer_; 168 Http2Settings acked_; 169 }; 170 171 } // namespace grpc_core 172 173 #endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H 174