1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_INFO_H
16 #define GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_INFO_H
17
18 #include <grpc/support/port_platform.h>
19
20 #include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
21 #include "src/core/lib/channel/call_tracer.h"
22 #include "src/core/lib/channel/channel_args.h"
23 #include "src/core/lib/transport/metadata_batch.h"
24
25 namespace grpc_core {
26
27 #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
28 #define DEFAULT_MAX_HEADER_LIST_SIZE_SOFT_LIMIT (8 * 1024)
29
GetSoftLimitFromChannelArgs(const ChannelArgs & args)30 inline uint32_t GetSoftLimitFromChannelArgs(const ChannelArgs& args) {
31 const int soft_limit = args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1);
32 if (soft_limit < 0) {
33 // Set soft limit to 0.8 * hard limit if this is larger than
34 // `DEFAULT_MAX_HEADER_LIST_SIZE_SOFT_LIMIT` and
35 // `GRPC_ARG_MAX_METADATA_SIZE` is not set.
36 return std::max(
37 DEFAULT_MAX_HEADER_LIST_SIZE_SOFT_LIMIT,
38 static_cast<int>(
39 0.8 *
40 args.GetInt(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE).value_or(-1)));
41 } else {
42 return soft_limit;
43 }
44 }
45
GetHardLimitFromChannelArgs(const ChannelArgs & args)46 inline uint32_t GetHardLimitFromChannelArgs(const ChannelArgs& args) {
47 int hard_limit =
48 args.GetInt(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE).value_or(-1);
49 if (hard_limit >= 0) {
50 return hard_limit;
51 } else {
52 // Set value to 1.25 * soft limit if this is larger than
53 // `DEFAULT_MAX_HEADER_LIST_SIZE` and
54 // `GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE` is not set.
55 const int soft_limit = args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1);
56 const int value = (soft_limit >= 0 && soft_limit < (INT_MAX / 1.25))
57 ? static_cast<int>(soft_limit * 1.25)
58 : soft_limit;
59 return std::max(value, DEFAULT_MAX_HEADER_LIST_SIZE);
60 }
61 }
62
63 class MetadataSizesAnnotation
64 : public CallTracerAnnotationInterface::Annotation {
65 public:
MetadataSizesAnnotation(grpc_metadata_batch * metadata_buffer,uint64_t soft_limit,uint64_t hard_limit)66 MetadataSizesAnnotation(grpc_metadata_batch* metadata_buffer,
67 uint64_t soft_limit, uint64_t hard_limit)
68 : CallTracerAnnotationInterface::Annotation(
69 CallTracerAnnotationInterface::AnnotationType::kMetadataSizes),
70 metadata_buffer_(metadata_buffer),
71 soft_limit_(soft_limit),
72 hard_limit_(hard_limit) {}
73
74 std::string ToString() const override;
75
76 private:
77 class MetadataSizeEncoder;
78 grpc_metadata_batch* metadata_buffer_;
79 uint64_t soft_limit_;
80 uint64_t hard_limit_;
81 };
82
83 } // namespace grpc_core
84
85 #endif // GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_INFO_H