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 22 #include <stdint.h> 23 24 #include <cstdint> 25 26 #include "absl/functional/function_ref.h" 27 #include "absl/strings/string_view.h" 28 #include "absl/types/optional.h" 29 30 #include "src/core/ext/transport/chttp2/transport/frame.h" 31 #include "src/core/lib/gpr/useful.h" 32 #include "src/core/lib/transport/http2_errors.h" 33 34 namespace grpc_core { 35 36 class Http2Settings { 37 public: 38 enum : uint16_t { 39 kHeaderTableSizeWireId = 1, 40 kEnablePushWireId = 2, 41 kMaxConcurrentStreamsWireId = 3, 42 kInitialWindowSizeWireId = 4, 43 kMaxFrameSizeWireId = 5, 44 kMaxHeaderListSizeWireId = 6, 45 kGrpcAllowTrueBinaryMetadataWireId = 65027, 46 kGrpcPreferredReceiveCryptoFrameSizeWireId = 65028, 47 }; 48 49 void Diff(bool is_first_send, const Http2Settings& old, 50 absl::FunctionRef<void(uint16_t key, uint32_t value)> cb) const; 51 GRPC_MUST_USE_RESULT grpc_http2_error_code Apply(uint16_t key, 52 uint32_t value); header_table_size()53 uint32_t header_table_size() const { return header_table_size_; } max_concurrent_streams()54 uint32_t max_concurrent_streams() const { return max_concurrent_streams_; } initial_window_size()55 uint32_t initial_window_size() const { return initial_window_size_; } max_frame_size()56 uint32_t max_frame_size() const { return max_frame_size_; } max_header_list_size()57 uint32_t max_header_list_size() const { return max_header_list_size_; } preferred_receive_crypto_message_size()58 uint32_t preferred_receive_crypto_message_size() const { 59 return preferred_receive_crypto_message_size_; 60 } enable_push()61 bool enable_push() const { return enable_push_; } allow_true_binary_metadata()62 bool allow_true_binary_metadata() const { 63 return allow_true_binary_metadata_; 64 } 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 } 84 header_table_size_name()85 static absl::string_view header_table_size_name() { 86 return "HEADER_TABLE_SIZE"; 87 } max_concurrent_streams_name()88 static absl::string_view max_concurrent_streams_name() { 89 return "MAX_CONCURRENT_STREAMS"; 90 } initial_window_size_name()91 static absl::string_view initial_window_size_name() { 92 return "INITIAL_WINDOW_SIZE"; 93 } max_frame_size_name()94 static absl::string_view max_frame_size_name() { return "MAX_FRAME_SIZE"; } max_header_list_size_name()95 static absl::string_view max_header_list_size_name() { 96 return "MAX_HEADER_LIST_SIZE"; 97 } enable_push_name()98 static absl::string_view enable_push_name() { return "ENABLE_PUSH"; } allow_true_binary_metadata_name()99 static absl::string_view allow_true_binary_metadata_name() { 100 return "GRPC_ALLOW_TRUE_BINARY_METADATA"; 101 } preferred_receive_crypto_message_size_name()102 static absl::string_view preferred_receive_crypto_message_size_name() { 103 return "GRPC_PREFERRED_RECEIVE_MESSAGE_SIZE"; 104 } 105 max_initial_window_size()106 static uint32_t max_initial_window_size() { return 2147483647u; } max_max_frame_size()107 static uint32_t max_max_frame_size() { return 16777215u; } min_max_frame_size()108 static uint32_t min_max_frame_size() { return 16384u; } min_preferred_receive_crypto_message_size()109 static uint32_t min_preferred_receive_crypto_message_size() { return 16384u; } max_preferred_receive_crypto_message_size()110 static uint32_t max_preferred_receive_crypto_message_size() { 111 return 2147483647u; 112 } 113 114 static std::string WireIdToName(uint16_t wire_id); 115 116 bool operator==(const Http2Settings& rhs) const { 117 return header_table_size_ == rhs.header_table_size_ && 118 max_concurrent_streams_ == rhs.max_concurrent_streams_ && 119 initial_window_size_ == rhs.initial_window_size_ && 120 max_frame_size_ == rhs.max_frame_size_ && 121 max_header_list_size_ == rhs.max_header_list_size_ && 122 preferred_receive_crypto_message_size_ == 123 rhs.preferred_receive_crypto_message_size_ && 124 enable_push_ == rhs.enable_push_ && 125 allow_true_binary_metadata_ == rhs.allow_true_binary_metadata_; 126 } 127 128 bool operator!=(const Http2Settings& rhs) const { return !operator==(rhs); } 129 130 private: 131 uint32_t header_table_size_ = 4096; 132 uint32_t max_concurrent_streams_ = 4294967295u; 133 uint32_t initial_window_size_ = 65535u; 134 uint32_t max_frame_size_ = 16384u; 135 uint32_t max_header_list_size_ = 16777216u; 136 uint32_t preferred_receive_crypto_message_size_ = 0u; 137 bool enable_push_ = true; 138 bool allow_true_binary_metadata_ = false; 139 }; 140 141 class Http2SettingsManager { 142 public: mutable_local()143 Http2Settings& mutable_local() { return local_; } local()144 const Http2Settings& local() const { return local_; } acked()145 const Http2Settings& acked() const { return acked_; } mutable_peer()146 Http2Settings& mutable_peer() { return peer_; } peer()147 const Http2Settings& peer() const { return peer_; } 148 149 absl::optional<Http2SettingsFrame> MaybeSendUpdate(); 150 GRPC_MUST_USE_RESULT bool AckLastSend(); 151 152 private: 153 enum class UpdateState : uint8_t { 154 kFirst, 155 kSending, 156 kIdle, 157 }; 158 UpdateState update_state_ = UpdateState::kFirst; 159 Http2Settings local_; 160 Http2Settings sent_; 161 Http2Settings peer_; 162 Http2Settings acked_; 163 }; 164 165 } // namespace grpc_core 166 167 #endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HTTP2_SETTINGS_H 168