1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #ifndef GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
20 #define GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
21
22 #include <grpc/impl/compression_types.h>
23 #include <grpc/status.h>
24 #include <grpc/support/port_platform.h>
25 #include <stdlib.h>
26
27 #include <cstdint>
28 #include <string>
29 #include <type_traits>
30 #include <utility>
31
32 #include "absl/container/inlined_vector.h"
33 #include "absl/functional/function_ref.h"
34 #include "absl/log/check.h"
35 #include "absl/meta/type_traits.h"
36 #include "absl/strings/numbers.h"
37 #include "absl/strings/string_view.h"
38 #include "absl/types/optional.h"
39 #include "src/core/lib/compression/compression_internal.h"
40 #include "src/core/lib/experiments/experiments.h"
41 #include "src/core/lib/promise/poll.h"
42 #include "src/core/lib/slice/slice.h"
43 #include "src/core/lib/transport/custom_metadata.h"
44 #include "src/core/lib/transport/metadata_compression_traits.h"
45 #include "src/core/lib/transport/parsed_metadata.h"
46 #include "src/core/lib/transport/simple_slice_based_metadata.h"
47 #include "src/core/util/chunked_vector.h"
48 #include "src/core/util/if_list.h"
49 #include "src/core/util/packed_table.h"
50 #include "src/core/util/time.h"
51 #include "src/core/util/type_list.h"
52
53 namespace grpc_core {
54
55 ///////////////////////////////////////////////////////////////////////////////
56 // Metadata traits
57
58 // Given a metadata key and a value, return the encoded size.
59 // Defaults to calling the key's Encode() method and then calculating the size
60 // of that, but can be overridden for specific keys if there's a better way of
61 // doing this.
62 // May return 0 if the size is unknown/unknowable.
63 template <typename Key>
EncodedSizeOfKey(Key,const typename Key::ValueType & value)64 size_t EncodedSizeOfKey(Key, const typename Key::ValueType& value) {
65 return Key::Encode(value).size();
66 }
67
68 // grpc-timeout metadata trait.
69 // ValueType is defined as Timestamp - an absolute timestamp (i.e. a
70 // deadline!), that is converted to a duration by transports before being
71 // sent.
72 // TODO(ctiller): Move this elsewhere. During the transition we need to be able
73 // to name this in MetadataMap, but ultimately once the transition is done we
74 // should not need to.
75 struct GrpcTimeoutMetadata {
76 static constexpr bool kRepeatable = false;
77 static constexpr bool kTransferOnTrailersOnly = false;
78 using ValueType = Timestamp;
79 using MementoType = Duration;
80 using CompressionTraits = TimeoutCompressor;
keyGrpcTimeoutMetadata81 static absl::string_view key() { return "grpc-timeout"; }
82 static MementoType ParseMemento(Slice value,
83 bool will_keep_past_request_lifetime,
84 MetadataParseErrorFn on_error);
85 static ValueType MementoToValue(MementoType timeout);
86 static Slice Encode(ValueType x);
DisplayValueGrpcTimeoutMetadata87 static std::string DisplayValue(ValueType x) { return x.ToString(); }
DisplayMementoGrpcTimeoutMetadata88 static std::string DisplayMemento(MementoType x) { return x.ToString(); }
89 };
90
91 // TE metadata trait.
92 struct TeMetadata {
93 static constexpr bool kRepeatable = false;
94 static constexpr bool kTransferOnTrailersOnly = false;
95 // HTTP2 says that TE can either be empty or "trailers".
96 // Empty means this trait is not included, "trailers" means kTrailers, and
97 // kInvalid is used to remember an invalid value.
98 enum ValueType : uint8_t {
99 kTrailers,
100 kInvalid,
101 };
102 using MementoType = ValueType;
103 using CompressionTraits = KnownValueCompressor<ValueType, kTrailers>;
keyTeMetadata104 static absl::string_view key() { return "te"; }
105 static MementoType ParseMemento(Slice value,
106 bool will_keep_past_request_lifetime,
107 MetadataParseErrorFn on_error);
MementoToValueTeMetadata108 static ValueType MementoToValue(MementoType te) { return te; }
EncodeTeMetadata109 static StaticSlice Encode(ValueType x) {
110 CHECK(x == kTrailers);
111 return StaticSlice::FromStaticString("trailers");
112 }
113 static const char* DisplayValue(ValueType te);
DisplayMementoTeMetadata114 static const char* DisplayMemento(MementoType te) { return DisplayValue(te); }
115 };
116
EncodedSizeOfKey(TeMetadata,TeMetadata::ValueType x)117 inline size_t EncodedSizeOfKey(TeMetadata, TeMetadata::ValueType x) {
118 return x == TeMetadata::kTrailers ? 8 : 0;
119 }
120
121 // content-type metadata trait.
122 struct ContentTypeMetadata {
123 static constexpr bool kRepeatable = false;
124 static constexpr bool kTransferOnTrailersOnly = true;
125 // gRPC says that content-type can be application/grpc[;something]
126 // Core has only ever verified the prefix.
127 // IF we want to start verifying more, we can expand this type.
128 enum ValueType : uint8_t {
129 kApplicationGrpc,
130 kEmpty,
131 kInvalid,
132 };
133 using MementoType = ValueType;
134 using CompressionTraits = KnownValueCompressor<ValueType, kApplicationGrpc>;
keyContentTypeMetadata135 static absl::string_view key() { return "content-type"; }
136 static MementoType ParseMemento(Slice value,
137 bool will_keep_past_request_lifetime,
138 MetadataParseErrorFn on_error);
MementoToValueContentTypeMetadata139 static ValueType MementoToValue(MementoType content_type) {
140 return content_type;
141 }
142
143 static StaticSlice Encode(ValueType x);
144 static const char* DisplayValue(ValueType content_type);
DisplayMementoContentTypeMetadata145 static const char* DisplayMemento(ValueType content_type) {
146 return DisplayValue(content_type);
147 }
148 };
149
150 // scheme metadata trait.
151 struct HttpSchemeMetadata {
152 static constexpr bool kRepeatable = false;
153 static constexpr bool kTransferOnTrailersOnly = false;
154 enum ValueType : uint8_t {
155 kHttp,
156 kHttps,
157 kInvalid,
158 };
159 using MementoType = ValueType;
160 using CompressionTraits = HttpSchemeCompressor;
keyHttpSchemeMetadata161 static absl::string_view key() { return ":scheme"; }
ParseMementoHttpSchemeMetadata162 static MementoType ParseMemento(Slice value, bool,
163 MetadataParseErrorFn on_error) {
164 return Parse(value.as_string_view(), on_error);
165 }
166 static ValueType Parse(absl::string_view value,
167 MetadataParseErrorFn on_error);
MementoToValueHttpSchemeMetadata168 static ValueType MementoToValue(MementoType content_type) {
169 return content_type;
170 }
171 static StaticSlice Encode(ValueType x);
172 static const char* DisplayValue(ValueType content_type);
DisplayMementoHttpSchemeMetadata173 static const char* DisplayMemento(MementoType content_type) {
174 return DisplayValue(content_type);
175 }
176 };
177
178 size_t EncodedSizeOfKey(HttpSchemeMetadata, HttpSchemeMetadata::ValueType x);
179
180 // method metadata trait.
181 struct HttpMethodMetadata {
182 static constexpr bool kRepeatable = false;
183 static constexpr bool kTransferOnTrailersOnly = false;
184 enum ValueType : uint8_t {
185 kPost,
186 kGet,
187 kPut,
188 kInvalid,
189 };
190 using MementoType = ValueType;
191 using CompressionTraits = HttpMethodCompressor;
keyHttpMethodMetadata192 static absl::string_view key() { return ":method"; }
193 static MementoType ParseMemento(Slice value,
194 bool will_keep_past_request_lifetime,
195 MetadataParseErrorFn on_error);
MementoToValueHttpMethodMetadata196 static ValueType MementoToValue(MementoType content_type) {
197 return content_type;
198 }
199 static StaticSlice Encode(ValueType x);
200 static const char* DisplayValue(ValueType content_type);
DisplayMementoHttpMethodMetadata201 static const char* DisplayMemento(MementoType content_type) {
202 return DisplayValue(content_type);
203 }
204 };
205
206 // Base type for metadata pertaining to a single compression algorithm
207 // (e.g., "grpc-encoding").
208 struct CompressionAlgorithmBasedMetadata {
209 using ValueType = grpc_compression_algorithm;
210 using MementoType = ValueType;
211 static MementoType ParseMemento(Slice value,
212 bool will_keep_past_request_lifetime,
213 MetadataParseErrorFn on_error);
MementoToValueCompressionAlgorithmBasedMetadata214 static ValueType MementoToValue(MementoType x) { return x; }
EncodeCompressionAlgorithmBasedMetadata215 static Slice Encode(ValueType x) {
216 CHECK(x != GRPC_COMPRESS_ALGORITHMS_COUNT);
217 return Slice::FromStaticString(CompressionAlgorithmAsString(x));
218 }
DisplayValueCompressionAlgorithmBasedMetadata219 static const char* DisplayValue(ValueType x) {
220 if (const char* p = CompressionAlgorithmAsString(x)) {
221 return p;
222 } else {
223 return "<discarded-invalid-value>";
224 }
225 }
DisplayMementoCompressionAlgorithmBasedMetadata226 static const char* DisplayMemento(MementoType x) { return DisplayValue(x); }
227 };
228
229 // grpc-encoding metadata trait.
230 struct GrpcEncodingMetadata : public CompressionAlgorithmBasedMetadata {
231 static constexpr bool kRepeatable = false;
232 static constexpr bool kTransferOnTrailersOnly = false;
233 using CompressionTraits =
234 SmallIntegralValuesCompressor<GRPC_COMPRESS_ALGORITHMS_COUNT>;
keyGrpcEncodingMetadata235 static absl::string_view key() { return "grpc-encoding"; }
236 };
237
238 // grpc-internal-encoding-request metadata trait.
239 struct GrpcInternalEncodingRequest : public CompressionAlgorithmBasedMetadata {
240 static constexpr bool kRepeatable = false;
241 static constexpr bool kTransferOnTrailersOnly = false;
242 using CompressionTraits = NoCompressionCompressor;
keyGrpcInternalEncodingRequest243 static absl::string_view key() { return "grpc-internal-encoding-request"; }
244 };
245
246 // grpc-accept-encoding metadata trait.
247 struct GrpcAcceptEncodingMetadata {
248 static constexpr bool kRepeatable = false;
249 static constexpr bool kTransferOnTrailersOnly = false;
keyGrpcAcceptEncodingMetadata250 static absl::string_view key() { return "grpc-accept-encoding"; }
251 using ValueType = CompressionAlgorithmSet;
252 using MementoType = ValueType;
253 using CompressionTraits = StableValueCompressor;
ParseMementoGrpcAcceptEncodingMetadata254 static MementoType ParseMemento(Slice value, bool, MetadataParseErrorFn) {
255 return CompressionAlgorithmSet::FromString(value.as_string_view());
256 }
MementoToValueGrpcAcceptEncodingMetadata257 static ValueType MementoToValue(MementoType x) { return x; }
EncodeGrpcAcceptEncodingMetadata258 static Slice Encode(ValueType x) { return x.ToSlice(); }
DisplayValueGrpcAcceptEncodingMetadata259 static absl::string_view DisplayValue(ValueType x) { return x.ToString(); }
DisplayMementoGrpcAcceptEncodingMetadata260 static absl::string_view DisplayMemento(MementoType x) {
261 return DisplayValue(x);
262 }
263 };
264
265 // user-agent metadata trait.
266 struct UserAgentMetadata : public SimpleSliceBasedMetadata {
267 static constexpr bool kRepeatable = false;
268 static constexpr bool kTransferOnTrailersOnly = false;
269 using CompressionTraits = StableValueCompressor;
keyUserAgentMetadata270 static absl::string_view key() { return "user-agent"; }
271 };
272
273 // grpc-message metadata trait.
274 struct GrpcMessageMetadata : public SimpleSliceBasedMetadata {
275 static constexpr bool kRepeatable = false;
276 static constexpr bool kTransferOnTrailersOnly = false;
277 using CompressionTraits = NoCompressionCompressor;
keyGrpcMessageMetadata278 static absl::string_view key() { return "grpc-message"; }
279 };
280
281 // host metadata trait.
282 struct HostMetadata : public SimpleSliceBasedMetadata {
283 static constexpr bool kRepeatable = false;
284 static constexpr bool kTransferOnTrailersOnly = false;
285 using CompressionTraits = NoCompressionCompressor;
keyHostMetadata286 static absl::string_view key() { return "host"; }
287 };
288
289 // endpoint-load-metrics-bin metadata trait.
290 struct EndpointLoadMetricsBinMetadata : public SimpleSliceBasedMetadata {
291 static constexpr bool kRepeatable = false;
292 static constexpr bool kTransferOnTrailersOnly = false;
293 using CompressionTraits = NoCompressionCompressor;
keyEndpointLoadMetricsBinMetadata294 static absl::string_view key() { return "endpoint-load-metrics-bin"; }
295 };
296
297 // grpc-server-stats-bin metadata trait.
298 struct GrpcServerStatsBinMetadata : public SimpleSliceBasedMetadata {
299 static constexpr bool kRepeatable = false;
300 static constexpr bool kTransferOnTrailersOnly = false;
301 using CompressionTraits = NoCompressionCompressor;
keyGrpcServerStatsBinMetadata302 static absl::string_view key() { return "grpc-server-stats-bin"; }
303 };
304
305 // grpc-trace-bin metadata trait.
306 struct GrpcTraceBinMetadata : public SimpleSliceBasedMetadata {
307 static constexpr bool kRepeatable = false;
308 static constexpr bool kTransferOnTrailersOnly = false;
309 using CompressionTraits = FrequentKeyWithNoValueCompressionCompressor;
keyGrpcTraceBinMetadata310 static absl::string_view key() { return "grpc-trace-bin"; }
311 };
312
313 // grpc-tags-bin metadata trait.
314 struct GrpcTagsBinMetadata : public SimpleSliceBasedMetadata {
315 static constexpr bool kRepeatable = false;
316 static constexpr bool kTransferOnTrailersOnly = false;
317 using CompressionTraits = FrequentKeyWithNoValueCompressionCompressor;
keyGrpcTagsBinMetadata318 static absl::string_view key() { return "grpc-tags-bin"; }
319 };
320
321 // XEnvoyPeerMetadata
322 struct XEnvoyPeerMetadata : public SimpleSliceBasedMetadata {
323 static constexpr bool kRepeatable = false;
324 static constexpr bool kTransferOnTrailersOnly = true;
325 using CompressionTraits = StableValueCompressor;
keyXEnvoyPeerMetadata326 static absl::string_view key() { return "x-envoy-peer-metadata"; }
327 };
328
329 // :authority metadata trait.
330 struct HttpAuthorityMetadata : public SimpleSliceBasedMetadata {
331 static constexpr bool kRepeatable = false;
332 static constexpr bool kTransferOnTrailersOnly = false;
333 using CompressionTraits = SmallSetOfValuesCompressor;
keyHttpAuthorityMetadata334 static absl::string_view key() { return ":authority"; }
335 };
336
337 // :path metadata trait.
338 struct HttpPathMetadata : public SimpleSliceBasedMetadata {
339 static constexpr bool kRepeatable = false;
340 static constexpr bool kTransferOnTrailersOnly = false;
341 using CompressionTraits = SmallSetOfValuesCompressor;
keyHttpPathMetadata342 static absl::string_view key() { return ":path"; }
343 };
344
345 // We separate SimpleIntBasedMetadata into two pieces: one that does not
346 // depend on the invalid value, and one that does. This allows the compiler to
347 // easily see the functions that are shared, and helps reduce code bloat here.
348 template <typename Int>
349 struct SimpleIntBasedMetadataBase {
350 using ValueType = Int;
351 using MementoType = Int;
MementoToValueSimpleIntBasedMetadataBase352 static ValueType MementoToValue(MementoType value) { return value; }
EncodeSimpleIntBasedMetadataBase353 static Slice Encode(ValueType x) { return Slice::FromInt64(x); }
DisplayValueSimpleIntBasedMetadataBase354 static Int DisplayValue(ValueType x) { return x; }
DisplayMementoSimpleIntBasedMetadataBase355 static Int DisplayMemento(MementoType x) { return x; }
356 };
357
358 template <typename Int, Int kInvalidValue>
359 struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> {
invalid_valueSimpleIntBasedMetadata360 static constexpr Int invalid_value() { return kInvalidValue; }
ParseMementoSimpleIntBasedMetadata361 static Int ParseMemento(Slice value, bool, MetadataParseErrorFn on_error) {
362 Int out;
363 if (!absl::SimpleAtoi(value.as_string_view(), &out)) {
364 on_error("not an integer", value);
365 out = kInvalidValue;
366 }
367 return out;
368 }
369 };
370
371 // grpc-status metadata trait.
372 struct GrpcStatusMetadata
373 : public SimpleIntBasedMetadata<grpc_status_code, GRPC_STATUS_UNKNOWN> {
374 static constexpr bool kRepeatable = false;
375 static constexpr bool kTransferOnTrailersOnly = false;
376 using CompressionTraits = SmallIntegralValuesCompressor<16>;
keyGrpcStatusMetadata377 static absl::string_view key() { return "grpc-status"; }
378 };
379
380 // grpc-previous-rpc-attempts metadata trait.
381 struct GrpcPreviousRpcAttemptsMetadata
382 : public SimpleIntBasedMetadata<uint32_t, 0> {
383 static constexpr bool kRepeatable = false;
384 static constexpr bool kTransferOnTrailersOnly = false;
385 using CompressionTraits = NoCompressionCompressor;
keyGrpcPreviousRpcAttemptsMetadata386 static absl::string_view key() { return "grpc-previous-rpc-attempts"; }
387 };
388
389 // grpc-retry-pushback-ms metadata trait.
390 struct GrpcRetryPushbackMsMetadata {
391 static constexpr bool kRepeatable = false;
392 static constexpr bool kTransferOnTrailersOnly = false;
keyGrpcRetryPushbackMsMetadata393 static absl::string_view key() { return "grpc-retry-pushback-ms"; }
394 using ValueType = Duration;
395 using MementoType = Duration;
396 using CompressionTraits = NoCompressionCompressor;
MementoToValueGrpcRetryPushbackMsMetadata397 static ValueType MementoToValue(MementoType x) { return x; }
EncodeGrpcRetryPushbackMsMetadata398 static Slice Encode(Duration x) { return Slice::FromInt64(x.millis()); }
DisplayValueGrpcRetryPushbackMsMetadata399 static int64_t DisplayValue(Duration x) { return x.millis(); }
DisplayMementoGrpcRetryPushbackMsMetadata400 static int64_t DisplayMemento(Duration x) { return DisplayValue(x); }
401 static Duration ParseMemento(Slice value,
402 bool will_keep_past_request_lifetime,
403 MetadataParseErrorFn on_error);
404 };
405
406 // :status metadata trait.
407 // TODO(ctiller): consider moving to uint16_t
408 struct HttpStatusMetadata : public SimpleIntBasedMetadata<uint32_t, 0> {
409 static constexpr bool kRepeatable = false;
410 static constexpr bool kTransferOnTrailersOnly = true;
411 using CompressionTraits = HttpStatusCompressor;
keyHttpStatusMetadata412 static absl::string_view key() { return ":status"; }
413 };
414
415 // "secret" metadata trait used to pass load balancing token between filters.
416 // This should not be exposed outside of gRPC core.
417 class GrpcLbClientStats;
418
419 struct GrpcLbClientStatsMetadata {
420 static constexpr bool kRepeatable = false;
421 static constexpr bool kTransferOnTrailersOnly = false;
keyGrpcLbClientStatsMetadata422 static absl::string_view key() { return "grpclb_client_stats"; }
423 using ValueType = GrpcLbClientStats*;
424 using MementoType = ValueType;
425 using CompressionTraits = NoCompressionCompressor;
MementoToValueGrpcLbClientStatsMetadata426 static ValueType MementoToValue(MementoType value) { return value; }
EncodeGrpcLbClientStatsMetadata427 static Slice Encode(ValueType) { abort(); }
DisplayValueGrpcLbClientStatsMetadata428 static const char* DisplayValue(ValueType) { return "<internal-lb-stats>"; }
DisplayMementoGrpcLbClientStatsMetadata429 static const char* DisplayMemento(MementoType) {
430 return "<internal-lb-stats>";
431 }
ParseMementoGrpcLbClientStatsMetadata432 static MementoType ParseMemento(Slice, bool, MetadataParseErrorFn error) {
433 error("not a valid value for grpclb_client_stats", Slice());
434 return nullptr;
435 }
436 };
437
EncodedSizeOfKey(GrpcLbClientStatsMetadata,GrpcLbClientStatsMetadata::ValueType)438 inline size_t EncodedSizeOfKey(GrpcLbClientStatsMetadata,
439 GrpcLbClientStatsMetadata::ValueType) {
440 return 0;
441 }
442
443 // lb-token metadata
444 struct LbTokenMetadata : public SimpleSliceBasedMetadata {
445 static constexpr bool kRepeatable = false;
446 static constexpr bool kTransferOnTrailersOnly = false;
447 using CompressionTraits = NoCompressionCompressor;
keyLbTokenMetadata448 static absl::string_view key() { return "lb-token"; }
449 };
450
451 // lb-cost-bin metadata
452 struct LbCostBinMetadata {
453 static constexpr bool kRepeatable = true;
454 static constexpr bool kTransferOnTrailersOnly = false;
keyLbCostBinMetadata455 static absl::string_view key() { return "lb-cost-bin"; }
456 struct ValueType {
457 double cost;
458 std::string name;
459 };
460 using MementoType = ValueType;
461 using CompressionTraits = NoCompressionCompressor;
MementoToValueLbCostBinMetadata462 static ValueType MementoToValue(MementoType value) { return value; }
463 static Slice Encode(const ValueType& x);
464 static std::string DisplayValue(ValueType x);
DisplayMementoLbCostBinMetadata465 static std::string DisplayMemento(MementoType x) { return DisplayValue(x); }
466 static MementoType ParseMemento(Slice value,
467 bool will_keep_past_request_lifetime,
468 MetadataParseErrorFn on_error);
469 };
470
471 // traceparent metadata
472 struct W3CTraceParentMetadata : public SimpleSliceBasedMetadata {
473 static constexpr bool kRepeatable = false;
474 static constexpr bool kTransferOnTrailersOnly = false;
475 using CompressionTraits = NoCompressionCompressor;
keyW3CTraceParentMetadata476 static absl::string_view key() { return "traceparent"; }
477 };
478
479 // Annotation added by a transport to note whether a failed request was never
480 // placed on the wire, or never seen by a server.
481 struct GrpcStreamNetworkState {
DebugKeyGrpcStreamNetworkState482 static absl::string_view DebugKey() { return "GrpcStreamNetworkState"; }
483 static constexpr bool kRepeatable = false;
484 static constexpr bool kTransferOnTrailersOnly = false;
485 enum ValueType : uint8_t {
486 kNotSentOnWire,
487 kNotSeenByServer,
488 };
489 static std::string DisplayValue(ValueType x);
490 };
491
492 // Annotation added by a server transport to note the peer making a request.
493 struct PeerString {
DebugKeyPeerString494 static absl::string_view DebugKey() { return "PeerString"; }
495 static constexpr bool kRepeatable = false;
496 using ValueType = Slice;
497 static std::string DisplayValue(const ValueType& x);
498 };
499
500 // Annotation added by various systems to describe the reason for a failure.
501 struct GrpcStatusContext {
DebugKeyGrpcStatusContext502 static absl::string_view DebugKey() { return "GrpcStatusContext"; }
503 static constexpr bool kRepeatable = true;
504 using ValueType = std::string;
505 static const std::string& DisplayValue(const std::string& x);
506 };
507
508 // Annotation added by a transport to note that the status came from the wire.
509 struct GrpcStatusFromWire {
DebugKeyGrpcStatusFromWire510 static absl::string_view DebugKey() { return "GrpcStatusFromWire"; }
511 static constexpr bool kRepeatable = false;
512 using ValueType = bool;
DisplayValueGrpcStatusFromWire513 static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
514 };
515
516 // Annotation to denote that this call qualifies for cancelled=1 for the
517 // RECV_CLOSE_ON_SERVER op
518 struct GrpcCallWasCancelled {
DebugKeyGrpcCallWasCancelled519 static absl::string_view DebugKey() { return "GrpcCallWasCancelled"; }
520 static constexpr bool kRepeatable = false;
521 using ValueType = bool;
DisplayValueGrpcCallWasCancelled522 static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
523 };
524
525 // Annotation added by client surface code to denote wait-for-ready state
526 struct WaitForReady {
527 struct ValueType {
528 bool value = false;
529 bool explicitly_set = false;
530 };
DebugKeyWaitForReady531 static absl::string_view DebugKey() { return "WaitForReady"; }
532 static constexpr bool kRepeatable = false;
533 static std::string DisplayValue(ValueType x);
534 };
535
536 // Annotation added by retry code to indicate a transparent retry.
537 struct IsTransparentRetry {
DebugKeyIsTransparentRetry538 static absl::string_view DebugKey() { return "IsTransparentRetry"; }
539 static constexpr bool kRepeatable = false;
540 using ValueType = bool;
DisplayValueIsTransparentRetry541 static std::string DisplayValue(ValueType x) { return x ? "true" : "false"; }
542 };
543
544 // Annotation added by a transport to note that server trailing metadata
545 // is a Trailers-Only response.
546 struct GrpcTrailersOnly {
DebugKeyGrpcTrailersOnly547 static absl::string_view DebugKey() { return "GrpcTrailersOnly"; }
548 static constexpr bool kRepeatable = false;
549 using ValueType = bool;
DisplayValueGrpcTrailersOnly550 static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
551 };
552
553 // On the client-side, the value is a uintptr_t with a value of 1 if the call
554 // has a registered/known method, or 0, if it's not known. On the server side,
555 // the value is a (ChannelRegisteredMethod*).
556 struct GrpcRegisteredMethod {
DebugKeyGrpcRegisteredMethod557 static absl::string_view DebugKey() { return "GrpcRegisteredMethod"; }
558 static constexpr bool kRepeatable = false;
559 using ValueType = void*;
560 static std::string DisplayValue(void* x);
561 };
562
563 // Annotation added by filters to inform the transport to tarpit this
564 // response: add some random delay to thwart certain kinds of attacks.
565 struct GrpcTarPit {
DebugKeyGrpcTarPit566 static absl::string_view DebugKey() { return "GrpcTarPit"; }
567 static constexpr bool kRepeatable = false;
568 using ValueType = Empty;
DisplayValueGrpcTarPit569 static absl::string_view DisplayValue(Empty) { return "tarpit"; }
570 };
571
572 namespace metadata_detail {
573
574 // Build a key/value formatted debug string.
575 // Output looks like 'key1: value1, key2: value2'
576 // The string is expected to be readable, but not necessarily parsable.
577 class DebugStringBuilder {
578 public:
579 // Add one key/value pair to the output if it is allow listed.
580 // Redact only the value if it is not allow listed.
581 void AddAfterRedaction(absl::string_view key, absl::string_view value);
582
583 // Finalize the output and return the string.
584 // Subsequent Add calls are UB.
TakeOutput()585 std::string TakeOutput() { return std::move(out_); }
586
587 private:
588 bool IsAllowListed(absl::string_view key) const;
589 void Add(absl::string_view key, absl::string_view value);
590 std::string out_;
591 };
592
593 // IsEncodable: Given a trait, determine if that trait is encodable, or is
594 // just a value attached to a MetadataMap. We use the presence of the key()
595 // static method to determine if a trait is encodable or not - encodable
596 // traits have string names, and non-encodable traits do not.
597 template <typename Trait, typename Ignored = void>
598 struct IsEncodableTrait {
599 static const bool value = false;
600 };
601
602 template <typename Trait>
603 struct IsEncodableTrait<Trait, absl::void_t<decltype(Trait::key())>> {
604 static const bool value = true;
605 };
606
607 template <typename MustBeVoid, typename... Traits>
608 struct EncodableTraits;
609
610 template <typename Trait, typename... Traits>
611 struct EncodableTraits<absl::enable_if_t<IsEncodableTrait<Trait>::value, void>,
612 Trait, Traits...> {
613 using List =
614 typename EncodableTraits<void,
615 Traits...>::List::template PushFront<Trait>;
616 };
617
618 template <typename Trait, typename... Traits>
619 struct EncodableTraits<absl::enable_if_t<!IsEncodableTrait<Trait>::value, void>,
620 Trait, Traits...> {
621 using List = typename EncodableTraits<void, Traits...>::List;
622 };
623
624 template <>
625 struct EncodableTraits<void> {
626 using List = Typelist<>;
627 };
628
629 template <typename Trait>
630 struct EncodableNameLookupKeyComparison {
631 bool operator()(absl::string_view key) { return key == Trait::key(); }
632 };
633
634 template <typename Trait, typename Op>
635 struct EncodableNameLookupOnFound {
636 auto operator()(Op* op) { return op->Found(Trait()); }
637 };
638
639 template <typename... Traits>
640 struct EncodableNameLookup {
641 template <typename Op>
642 static auto Lookup(absl::string_view key, Op* op) {
643 return IfList(
644 key, op, [key](Op* op) { return op->NotFound(key); },
645 EncodableNameLookupKeyComparison<Traits>()...,
646 EncodableNameLookupOnFound<Traits, Op>()...);
647 }
648 };
649
650 template <typename... Traits>
651 using NameLookup = typename EncodableTraits<
652 void, Traits...>::List::template Instantiate<EncodableNameLookup>;
653
654 // Helper to take a slice to a memento to a value.
655 // By splitting this part out we can scale code size as the number of
656 // (memento, value) types, rather than as the number of traits.
657 template <typename ParseMementoFn, typename MementoToValueFn>
658 struct ParseValue {
659 template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value>
660 static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value,
661 MetadataParseErrorFn on_error)
662 -> decltype(memento_to_value(parse_memento(std::move(*value), false,
663 on_error))) {
664 return memento_to_value(parse_memento(std::move(*value), false, on_error));
665 }
666 };
667
668 // This is an "Op" type for NameLookup.
669 // Used for MetadataMap::Parse, its Found/NotFound methods turn a slice into a
670 // ParsedMetadata object.
671 template <typename Container>
672 class ParseHelper {
673 public:
674 ParseHelper(Slice value, bool will_keep_past_request_lifetime,
675 MetadataParseErrorFn on_error, size_t transport_size)
676 : value_(std::move(value)),
677 will_keep_past_request_lifetime_(will_keep_past_request_lifetime),
678 on_error_(on_error),
679 transport_size_(transport_size) {}
680
681 template <typename Trait>
682 GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) {
683 return ParsedMetadata<Container>(
684 trait,
685 ParseValueToMemento<typename Trait::MementoType, Trait::ParseMemento>(),
686 static_cast<uint32_t>(transport_size_));
687 }
688
689 GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> NotFound(
690 absl::string_view key) {
691 return ParsedMetadata<Container>(
692 typename ParsedMetadata<Container>::FromSlicePair{},
693 Slice::FromCopiedString(key),
694 will_keep_past_request_lifetime_ ? value_.TakeUniquelyOwned()
695 : std::move(value_),
696 transport_size_);
697 }
698
699 private:
700 template <typename T, T (*parse_memento)(Slice, bool, MetadataParseErrorFn)>
701 GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() {
702 return parse_memento(std::move(value_), will_keep_past_request_lifetime_,
703 on_error_);
704 }
705
706 Slice value_;
707 const bool will_keep_past_request_lifetime_;
708 MetadataParseErrorFn on_error_;
709 const size_t transport_size_;
710 };
711
712 // This is an "Op" type for NameLookup.
713 // Used for MetadataMap::Append, its Found/NotFound methods turn a slice into
714 // a value and add it to a container.
715 template <typename Container>
716 class AppendHelper {
717 public:
718 AppendHelper(Container* container, Slice value, MetadataParseErrorFn on_error)
719 : container_(container), value_(std::move(value)), on_error_(on_error) {}
720
721 template <typename Trait>
722 GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
723 container_->Set(
724 trait, ParseValue<decltype(Trait::ParseMemento),
725 decltype(Trait::MementoToValue)>::
726 template Parse<Trait::ParseMemento, Trait::MementoToValue>(
727 &value_, on_error_));
728 }
729
730 GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
731 container_->unknown_.Append(key, std::move(value_));
732 }
733
734 private:
735 Container* const container_;
736 Slice value_;
737 MetadataParseErrorFn on_error_;
738 };
739
740 // This is an "Op" type for NameLookup.
741 // Used for MetadataMap::Remove, its Found/NotFound methods remove a key from
742 // the container.
743 template <typename Container>
744 class RemoveHelper {
745 public:
746 explicit RemoveHelper(Container* container) : container_(container) {}
747
748 template <typename Trait>
749 GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
750 container_->Remove(trait);
751 }
752
753 GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
754 container_->unknown_.Remove(key);
755 }
756
757 private:
758 Container* const container_;
759 };
760
761 // This is an "Op" type for NameLookup.
762 // Used for MetadataMap::GetStringValue, its Found/NotFound methods generated
763 // a string value from the container.
764 template <typename Container>
765 class GetStringValueHelper {
766 public:
767 explicit GetStringValueHelper(const Container* container,
768 std::string* backing)
769 : container_(container), backing_(backing) {}
770
771 template <typename Trait>
772 GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
773 Trait::kRepeatable == false &&
774 std::is_same<Slice, typename Trait::ValueType>::value,
775 absl::optional<absl::string_view>>
776 Found(Trait) {
777 const auto* value = container_->get_pointer(Trait());
778 if (value == nullptr) return absl::nullopt;
779 return value->as_string_view();
780 }
781
782 template <typename Trait>
783 GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
784 Trait::kRepeatable == true &&
785 !std::is_same<Slice, typename Trait::ValueType>::value,
786 absl::optional<absl::string_view>>
787 Found(Trait) {
788 const auto* value = container_->get_pointer(Trait());
789 if (value == nullptr) return absl::nullopt;
790 backing_->clear();
791 for (const auto& v : *value) {
792 if (!backing_->empty()) backing_->push_back(',');
793 auto new_segment = Trait::Encode(v);
794 backing_->append(new_segment.begin(), new_segment.end());
795 }
796 return *backing_;
797 }
798
799 template <typename Trait>
800 GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
801 Trait::kRepeatable == false &&
802 !std::is_same<Slice, typename Trait::ValueType>::value,
803 absl::optional<absl::string_view>>
804 Found(Trait) {
805 const auto* value = container_->get_pointer(Trait());
806 if (value == nullptr) return absl::nullopt;
807 *backing_ = std::string(Trait::Encode(*value).as_string_view());
808 return *backing_;
809 }
810
811 GPR_ATTRIBUTE_NOINLINE absl::optional<absl::string_view> NotFound(
812 absl::string_view key) {
813 return container_->unknown_.GetStringValue(key, backing_);
814 }
815
816 private:
817 const Container* const container_;
818 std::string* backing_;
819 };
820
821 // Sink for key value logs
822 using LogFn = absl::FunctionRef<void(absl::string_view, absl::string_view)>;
823
824 template <typename T>
825 struct AdaptDisplayValueToLog {
826 static std::string ToString(const T& value) { return std::to_string(value); }
827 };
828
829 template <>
830 struct AdaptDisplayValueToLog<std::string> {
831 static std::string ToString(const std::string& value) { return value; }
832 };
833
834 template <>
835 struct AdaptDisplayValueToLog<const std::string&> {
836 static std::string ToString(const std::string& value) { return value; }
837 };
838
839 template <>
840 struct AdaptDisplayValueToLog<absl::string_view> {
841 static std::string ToString(absl::string_view value) {
842 return std::string(value);
843 }
844 };
845
846 template <>
847 struct AdaptDisplayValueToLog<Slice> {
848 static std::string ToString(Slice value) {
849 return std::string(value.as_string_view());
850 }
851 };
852
853 template <>
854 struct AdaptDisplayValueToLog<const char*> {
855 static std::string ToString(const char* value) { return std::string(value); }
856 };
857
858 template <>
859 struct AdaptDisplayValueToLog<StaticSlice> {
860 static absl::string_view ToString(StaticSlice value) {
861 return value.as_string_view();
862 }
863 };
864
865 template <typename T, typename U, typename V>
866 GPR_ATTRIBUTE_NOINLINE void LogKeyValueTo(absl::string_view key, const T& value,
867 V (*display_value)(U), LogFn log_fn) {
868 log_fn(key, AdaptDisplayValueToLog<V>::ToString(display_value(value)));
869 }
870
871 // Generate a strong type for metadata values per trait.
872 template <typename Which, typename Ignored = void>
873 struct Value;
874
875 template <typename Which>
876 struct Value<Which, absl::enable_if_t<Which::kRepeatable == false &&
877 IsEncodableTrait<Which>::value,
878 void>> {
879 Value() = default;
880 explicit Value(const typename Which::ValueType& value) : value(value) {}
881 explicit Value(typename Which::ValueType&& value)
882 : value(std::forward<typename Which::ValueType>(value)) {}
883 Value(const Value&) = delete;
884 Value& operator=(const Value&) = delete;
885 Value(Value&&) noexcept = default;
886 Value& operator=(Value&& other) noexcept {
887 value = std::move(other.value);
888 return *this;
889 }
890 template <typename Encoder>
891 void EncodeTo(Encoder* encoder) const {
892 encoder->Encode(Which(), value);
893 }
894 template <typename Encoder>
895 void VisitWith(Encoder* encoder) const {
896 return EncodeTo(encoder);
897 }
898 void LogTo(LogFn log_fn) const {
899 LogKeyValueTo(Which::key(), value, Which::DisplayValue, log_fn);
900 }
901 using StorageType = typename Which::ValueType;
902 GPR_NO_UNIQUE_ADDRESS StorageType value;
903 };
904
905 template <typename Which>
906 struct Value<Which, absl::enable_if_t<Which::kRepeatable == false &&
907 !IsEncodableTrait<Which>::value,
908 void>> {
909 Value() = default;
910 explicit Value(const typename Which::ValueType& value) : value(value) {}
911 explicit Value(typename Which::ValueType&& value)
912 : value(std::forward<typename Which::ValueType>(value)) {}
913 Value(const Value&) = delete;
914 Value& operator=(const Value&) = delete;
915 Value(Value&&) noexcept = default;
916 Value& operator=(Value&& other) noexcept {
917 value = std::move(other.value);
918 return *this;
919 }
920 template <typename Encoder>
921 void EncodeTo(Encoder*) const {}
922 template <typename Encoder>
923 void VisitWith(Encoder* encoder) const {
924 encoder->Encode(Which(), value);
925 }
926 void LogTo(LogFn log_fn) const {
927 LogKeyValueTo(Which::DebugKey(), value, Which::DisplayValue, log_fn);
928 }
929 using StorageType = typename Which::ValueType;
930 GPR_NO_UNIQUE_ADDRESS StorageType value;
931 };
932
933 template <typename Which>
934 struct Value<Which, absl::enable_if_t<Which::kRepeatable == true &&
935 IsEncodableTrait<Which>::value,
936 void>> {
937 Value() = default;
938 explicit Value(const typename Which::ValueType& value) {
939 this->value.push_back(value);
940 }
941 explicit Value(typename Which::ValueType&& value) {
942 this->value.emplace_back(std::forward<typename Which::ValueType>(value));
943 }
944 Value(const Value&) = delete;
945 Value& operator=(const Value&) = delete;
946 Value(Value&& other) noexcept : value(std::move(other.value)) {}
947 Value& operator=(Value&& other) noexcept {
948 value = std::move(other.value);
949 return *this;
950 }
951 template <typename Encoder>
952 void EncodeTo(Encoder* encoder) const {
953 for (const auto& v : value) {
954 encoder->Encode(Which(), v);
955 }
956 }
957 template <typename Encoder>
958 void VisitWith(Encoder* encoder) const {
959 return EncodeTo(encoder);
960 }
961 void LogTo(LogFn log_fn) const {
962 for (const auto& v : value) {
963 LogKeyValueTo(Which::key(), v, Which::Encode, log_fn);
964 }
965 }
966 using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
967 StorageType value;
968 };
969
970 template <typename Which>
971 struct Value<Which, absl::enable_if_t<Which::kRepeatable == true &&
972 !IsEncodableTrait<Which>::value,
973 void>> {
974 Value() = default;
975 explicit Value(const typename Which::ValueType& value) {
976 this->value.push_back(value);
977 }
978 explicit Value(typename Which::ValueType&& value) {
979 this->value.emplace_back(std::forward<typename Which::ValueType>(value));
980 }
981 Value(const Value&) = delete;
982 Value& operator=(const Value&) = delete;
983 Value(Value&& other) noexcept : value(std::move(other.value)) {}
984 Value& operator=(Value&& other) noexcept {
985 value = std::move(other.value);
986 return *this;
987 }
988 template <typename Encoder>
989 void EncodeTo(Encoder*) const {}
990 template <typename Encoder>
991 void VisitWith(Encoder* encoder) const {
992 for (const auto& v : value) {
993 encoder->Encode(Which(), v);
994 }
995 }
996 void LogTo(LogFn log_fn) const {
997 for (const auto& v : value) {
998 LogKeyValueTo(Which::DebugKey(), v, Which::DisplayValue, log_fn);
999 }
1000 }
1001 using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
1002 StorageType value;
1003 };
1004
1005 // Encoder to copy some metadata
1006 template <typename Output>
1007 class CopySink {
1008 public:
1009 explicit CopySink(Output* dst) : dst_(dst) {}
1010
1011 template <class T, class V>
1012 void Encode(T trait, V value) {
1013 dst_->Set(trait, value);
1014 }
1015
1016 template <class T>
1017 void Encode(T trait, const Slice& value) {
1018 dst_->Set(trait, std::move(value.AsOwned()));
1019 }
1020
1021 void Encode(const Slice& key, const Slice& value) {
1022 dst_->unknown_.Append(key.as_string_view(), value.Ref());
1023 }
1024
1025 private:
1026 Output* dst_;
1027 };
1028
1029 // Callable for the ForEach in Encode() -- for each value, call the
1030 // appropriate encoder method.
1031 template <typename Encoder>
1032 struct EncodeWrapper {
1033 Encoder* encoder;
1034 template <typename Which>
1035 void operator()(const Value<Which>& which) {
1036 which.EncodeTo(encoder);
1037 }
1038 };
1039
1040 // Callable for the table ForEach in ForEach() -- for each value, call the
1041 // appropriate visitor method.
1042 template <typename Encoder>
1043 struct ForEachWrapper {
1044 Encoder* encoder;
1045 template <typename Which>
1046 void operator()(const Value<Which>& which) {
1047 which.VisitWith(encoder);
1048 }
1049 };
1050
1051 // Callable for the ForEach in Log()
1052 struct LogWrapper {
1053 LogFn log_fn;
1054 template <typename Which>
1055 void operator()(const Value<Which>& which) {
1056 which.LogTo(log_fn);
1057 }
1058 };
1059
1060 // Callable for the table FilterIn -- for each value, call the
1061 // appropriate filter method to determine of the value should be kept or
1062 // removed.
1063 template <typename Filterer>
1064 struct FilterWrapper {
1065 Filterer filter_fn;
1066
1067 template <typename Which,
1068 absl::enable_if_t<IsEncodableTrait<Which>::value, bool> = true>
1069 bool operator()(const Value<Which>& /*which*/) {
1070 return filter_fn(Which());
1071 }
1072
1073 template <typename Which,
1074 absl::enable_if_t<!IsEncodableTrait<Which>::value, bool> = true>
1075 bool operator()(const Value<Which>& /*which*/) {
1076 return true;
1077 }
1078 };
1079
1080 // Encoder to compute TransportSize
1081 class TransportSizeEncoder {
1082 public:
1083 void Encode(const Slice& key, const Slice& value) {
1084 size_ += key.length() + value.length() + 32;
1085 }
1086
1087 template <typename Which>
1088 void Encode(Which, const typename Which::ValueType& value) {
1089 Add(Which(), value);
1090 }
1091
1092 void Encode(ContentTypeMetadata,
1093 const typename ContentTypeMetadata::ValueType& value) {
1094 if (value == ContentTypeMetadata::kInvalid) return;
1095 Add(ContentTypeMetadata(), value);
1096 }
1097
1098 size_t size() const { return size_; }
1099
1100 private:
1101 template <typename Which>
1102 void Add(Which, const typename Which::ValueType& value) {
1103 size_ += Which::key().length() + Which::Encode(value).length() + 32;
1104 }
1105
1106 uint32_t size_ = 0;
1107 };
1108
1109 // Handle unknown (non-trait-based) fields in the metadata map.
1110 class UnknownMap {
1111 public:
1112 using BackingType = std::vector<std::pair<Slice, Slice>>;
1113
1114 void Append(absl::string_view key, Slice value);
1115 void Remove(absl::string_view key);
1116 absl::optional<absl::string_view> GetStringValue(absl::string_view key,
1117 std::string* backing) const;
1118
1119 BackingType::const_iterator begin() const { return unknown_.cbegin(); }
1120 BackingType::const_iterator end() const { return unknown_.cend(); }
1121
1122 template <typename Filterer>
1123 void Filter(Filterer* filter_fn) {
1124 unknown_.erase(
1125 std::remove_if(unknown_.begin(), unknown_.end(),
1126 [&](auto& pair) {
1127 return !(*filter_fn)(pair.first.as_string_view());
1128 }),
1129 unknown_.end());
1130 }
1131
1132 bool empty() const { return unknown_.empty(); }
1133 size_t size() const { return unknown_.size(); }
1134 void Clear() { unknown_.clear(); }
1135
1136 private:
1137 // Backing store for added metadata.
1138 BackingType unknown_;
1139 };
1140
1141 // Given a factory template Factory, construct a type that derives from
1142 // Factory<MetadataTrait, MetadataTrait::CompressionTraits> for all
1143 // MetadataTraits. Useful for transports in defining the stateful parts of their
1144 // compression algorithm.
1145 template <template <typename, typename> class Factory,
1146 typename... MetadataTraits>
1147 struct StatefulCompressor;
1148
1149 template <template <typename, typename> class Factory, typename MetadataTrait,
1150 bool kEncodable = IsEncodableTrait<MetadataTrait>::value>
1151 struct SpecificStatefulCompressor;
1152
1153 template <template <typename, typename> class Factory, typename MetadataTrait>
1154 struct SpecificStatefulCompressor<Factory, MetadataTrait, true>
1155 : public Factory<MetadataTrait, typename MetadataTrait::CompressionTraits> {
1156 };
1157
1158 template <template <typename, typename> class Factory, typename MetadataTrait>
1159 struct SpecificStatefulCompressor<Factory, MetadataTrait, false> {};
1160
1161 template <template <typename, typename> class Factory, typename MetadataTrait,
1162 typename... MetadataTraits>
1163 struct StatefulCompressor<Factory, MetadataTrait, MetadataTraits...>
1164 : public SpecificStatefulCompressor<Factory, MetadataTrait>,
1165 public StatefulCompressor<Factory, MetadataTraits...> {};
1166
1167 template <template <typename, typename> class Factory>
1168 struct StatefulCompressor<Factory> {};
1169
1170 } // namespace metadata_detail
1171
1172 // Helper function for encoders
1173 // Given a metadata trait, convert the value to a slice.
1174 template <typename Which>
1175 absl::enable_if_t<std::is_same<typename Which::ValueType, Slice>::value,
1176 const Slice&>
1177 MetadataValueAsSlice(const Slice& slice) {
1178 return slice;
1179 }
1180
1181 template <typename Which>
1182 absl::enable_if_t<!std::is_same<typename Which::ValueType, Slice>::value, Slice>
1183 MetadataValueAsSlice(typename Which::ValueType value) {
1184 return Slice(Which::Encode(value));
1185 }
1186
1187 // MetadataMap encodes the mapping of metadata keys to metadata values.
1188 //
1189 // MetadataMap takes a derived class and list of traits. Each of these trait
1190 // objects defines one metadata field that is used by core, and so should have
1191 // more specialized handling than just using the generic APIs.
1192 //
1193 // MetadataMap is the backing type for some derived type via the curiously
1194 // recursive template pattern. This is because many types consumed by
1195 // MetadataMap require the container type to operate on, and many of those
1196 // types are instantiated one per trait. A naive implementation without the
1197 // Derived type would, for traits A,B,C, then instantiate for some
1198 // T<Container, Trait>:
1199 // - T<MetadataMap<A,B,C>, A>,
1200 // - T<MetadataMap<A,B,C>, B>,
1201 // - T<MetadataMap<A,B,C>, C>.
1202 // Since these types ultimately need to be recorded in the .dynstr segment
1203 // for dynamic linkers (if gRPC is linked as a static library) this would
1204 // create O(N^2) bytes of symbols even in stripped libraries. To avoid this
1205 // we use the derived type (e.g. grpc_metadata_batch right now) to capture
1206 // the container type, and we would write T<grpc_metadata_batch, A>, etc...
1207 // Note that now the container type uses a number of bytes that is independent
1208 // of the number of traits, and so we return to a linear symbol table growth
1209 // function.
1210 //
1211 // Each trait object has one of two possible signatures, depending on whether
1212 // that traits field is encodable or not.
1213 // Non-encodable traits are carried in a MetadataMap, but are never passed to
1214 // the application nor serialized to wire.
1215 //
1216 // Encodable traits have the following signature:
1217 // // Traits for the "grpc-xyz" metadata field:
1218 // struct GrpcXyzMetadata {
1219 // // Can this metadata field be repeated?
1220 // static constexpr bool kRepeatable = ...;
1221 // // Should this metadata be transferred from server headers to trailers on
1222 // // Trailers-Only response?
1223 // static constexpr bool kTransferOnTrailersOnly = ...;
1224 // // The type that's stored on MetadataBatch
1225 // using ValueType = ...;
1226 // // The type that's stored in compression/decompression tables
1227 // using MementoType = ...;
1228 // // The string key for this metadata type (for transports that require it)
1229 // static absl::string_view key() { return "grpc-xyz"; }
1230 // // Parse a memento from a slice
1231 // // Takes ownership of value
1232 // // If will_keep_past_request_lifetime is true, expect that the returned
1233 // // memento will be kept for a long time, and so try not to keep a ref to
1234 // // the input slice.
1235 // // Calls fn in the case of an error that should be reported to the user
1236 // static MementoType ParseMemento(
1237 // Slice value,
1238 // bool will_keep_past_request_lifetime,
1239 // MementoParseErrorFn fn) {
1240 // ...
1241 // }
1242 // // Convert a memento to a value
1243 // static ValueType MementoToValue(MementoType memento) { ... }
1244 // // Convert a value to its canonical text wire format (the format that
1245 // // ParseMemento will accept!)
1246 // static Slice Encode(const ValueType& value);
1247 // // Convert a value to something that can be passed to StrCat and
1248 // displayed
1249 // // for debugging
1250 // static SomeStrCatableType DisplayValue(ValueType value) { ... }
1251 // static SomeStrCatableType DisplayMemento(MementoType value) { ... }
1252 // };
1253 //
1254 // Non-encodable traits are determined by missing the key() method, and have
1255 // the following signature (and by convention omit the Metadata part of the
1256 // type name):
1257 // // Traits for the GrpcXyz field:
1258 // struct GrpcXyz {
1259 // // The string key that should be used for debug dumps - should not be a
1260 // // valid http2 key (ie all lower case)
1261 // static absl::string_view DebugKey() { return "GRPC_XYZ"; }
1262 // // Can this metadata field be repeated?
1263 // static constexpr bool kRepeatable = ...;
1264 // // The type that's stored on MetadataBatch
1265 // using ValueType = ...;
1266 // // Convert a value to something that can be passed to StrCat and
1267 // displayed
1268 // // for debugging
1269 // static SomeStrCatableType DisplayValue(ValueType value) { ... }
1270 // };
1271 //
1272 // About parsing and mementos:
1273 //
1274 // Many gRPC transports exchange metadata as key/value strings, but also allow
1275 // for a more efficient representation as a single integer. We can use this
1276 // integer representation to avoid reparsing too, by storing the parsed value
1277 // in the compression table. This is what mementos are used for.
1278 //
1279 // A trait offers the capability to turn a slice into a memento via
1280 // ParseMemento. This is exposed to users of MetadataMap via the Parse()
1281 // method, that returns a ParsedMetadata object. That ParsedMetadata object
1282 // can in turn be used to set the same value on many different MetadataMaps
1283 // without having to reparse.
1284 //
1285 // Implementation wise, ParsedMetadata is a type erased wrapper around
1286 // MementoType. When we set a value on MetadataMap, we first turn that memento
1287 // into a value. For most types, this is going to be a no-op, but for example
1288 // for grpc-timeout we make the memento the timeout expressed on the wire, but
1289 // we make the value the timestamp of when the timeout will expire (i.e. the
1290 // deadline).
1291 template <class Derived, typename... Traits>
1292 class MetadataMap {
1293 public:
1294 MetadataMap() = default;
1295 ~MetadataMap();
1296
1297 // Given a compressor factory - template taking <MetadataTrait,
1298 // CompressionTrait>, StatefulCompressor<Factory> provides a type
1299 // derived from all Encodable traits in this MetadataMap.
1300 // This can be used by transports to delegate compression to the appropriate
1301 // compression algorithm.
1302 template <template <typename, typename> class Factory>
1303 using StatefulCompressor =
1304 metadata_detail::StatefulCompressor<Factory, Traits...>;
1305
1306 MetadataMap(const MetadataMap&) = delete;
1307 MetadataMap& operator=(const MetadataMap&) = delete;
1308 MetadataMap(MetadataMap&&) noexcept;
1309 // We never create MetadataMap directly, instead we create Derived, but we
1310 // want to be able to move it without redeclaring this.
1311 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1312 Derived& operator=(MetadataMap&&) noexcept;
1313
1314 // Encode this metadata map into some encoder.
1315 // For each field that is set in the MetadataMap, call
1316 // encoder->Encode.
1317 //
1318 // For fields for which we have traits, this will be a method with
1319 // the signature:
1320 // void Encode(TraitsType, typename TraitsType::ValueType value);
1321 // For fields for which we do not have traits, this will be a method
1322 // with the signature:
1323 // void Encode(string_view key, Slice value);
1324 template <typename Encoder>
1325 void Encode(Encoder* encoder) const {
1326 table_.template ForEachIn<metadata_detail::EncodeWrapper<Encoder>,
1327 Value<Traits>...>(
1328 metadata_detail::EncodeWrapper<Encoder>{encoder});
1329 for (const auto& unk : unknown_) {
1330 encoder->Encode(unk.first, unk.second);
1331 }
1332 }
1333
1334 // Like Encode, but also visit the non-encodable fields.
1335 template <typename Encoder>
1336 void ForEach(Encoder* encoder) const {
1337 table_.ForEach(metadata_detail::ForEachWrapper<Encoder>{encoder});
1338 for (const auto& unk : unknown_) {
1339 encoder->Encode(unk.first, unk.second);
1340 }
1341 }
1342
1343 // Similar to Encode, but targeted at logging: for each metadatum,
1344 // call f(key, value) as absl::string_views.
1345 void Log(metadata_detail::LogFn log_fn) const {
1346 table_.ForEach(metadata_detail::LogWrapper{log_fn});
1347 for (const auto& unk : unknown_) {
1348 log_fn(unk.first.as_string_view(), unk.second.as_string_view());
1349 }
1350 }
1351
1352 // Filter the metadata map.
1353 // Iterates over all encodable and unknown headers and calls the filter_fn
1354 // for each of them. If the function returns true, the header is kept.
1355 template <typename Filterer>
1356 void Filter(Filterer filter_fn) {
1357 table_.template FilterIn<metadata_detail::FilterWrapper<Filterer>,
1358 Value<Traits>...>(
1359 metadata_detail::FilterWrapper<Filterer>{filter_fn});
1360 unknown_.Filter<Filterer>(&filter_fn);
1361 }
1362
1363 std::string DebugString() const {
1364 metadata_detail::DebugStringBuilder builder;
1365 Log([&builder](absl::string_view key, absl::string_view value) {
1366 builder.AddAfterRedaction(key, value);
1367 });
1368 return builder.TakeOutput();
1369 }
1370
1371 template <typename Sink>
1372 friend void AbslStringify(Sink& sink, const MetadataMap& map) {
1373 sink.Append(map.DebugString());
1374 }
1375
1376 // Get the pointer to the value of some known metadata.
1377 // Returns nullptr if the metadata is not present.
1378 // Causes a compilation error if Which is not an element of Traits.
1379 template <typename Which>
1380 const typename metadata_detail::Value<Which>::StorageType* get_pointer(
1381 Which) const {
1382 if (auto* p = table_.template get<Value<Which>>()) return &p->value;
1383 return nullptr;
1384 }
1385
1386 // Get the pointer to the value of some known metadata.
1387 // Returns nullptr if the metadata is not present.
1388 // Causes a compilation error if Which is not an element of Traits.
1389 template <typename Which>
1390 typename metadata_detail::Value<Which>::StorageType* get_pointer(Which) {
1391 if (auto* p = table_.template get<Value<Which>>()) return &p->value;
1392 return nullptr;
1393 }
1394
1395 // Get the pointer to the value of some known metadata.
1396 // Adds the default value for the metadata is not present.
1397 // Causes a compilation error if Which is not an element of Traits.
1398 template <typename Which>
1399 typename metadata_detail::Value<Which>::StorageType* GetOrCreatePointer(
1400 Which) {
1401 return &table_.template get_or_create<Value<Which>>()->value;
1402 }
1403
1404 // Get the value of some known metadata.
1405 // Returns nullopt if the metadata is not present.
1406 // Causes a compilation error if Which is not an element of Traits.
1407 template <typename Which>
1408 absl::optional<typename Which::ValueType> get(Which) const {
1409 if (auto* p = table_.template get<Value<Which>>()) return p->value;
1410 return absl::nullopt;
1411 }
1412
1413 // Set the value of some known metadata.
1414 // Returns a pointer to the new value.
1415 template <typename Which, typename... Args>
1416 absl::enable_if_t<Which::kRepeatable == false, void> Set(Which,
1417 Args&&... args) {
1418 table_.template set<Value<Which>>(std::forward<Args>(args)...);
1419 }
1420 template <typename Which, typename... Args>
1421 absl::enable_if_t<Which::kRepeatable == true, void> Set(Which,
1422 Args&&... args) {
1423 GetOrCreatePointer(Which())->emplace_back(std::forward<Args>(args)...);
1424 }
1425
1426 // Remove a specific piece of known metadata.
1427 template <typename Which>
1428 void Remove(Which) {
1429 table_.template clear<Value<Which>>();
1430 }
1431
1432 // Remove some metadata by name
1433 void Remove(absl::string_view key) {
1434 metadata_detail::RemoveHelper<Derived> helper(static_cast<Derived*>(this));
1435 metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
1436 }
1437
1438 void Remove(const char* key) { Remove(absl::string_view(key)); }
1439
1440 // Retrieve some metadata by name
1441 absl::optional<absl::string_view> GetStringValue(absl::string_view name,
1442 std::string* buffer) const {
1443 metadata_detail::GetStringValueHelper<Derived> helper(
1444 static_cast<const Derived*>(this), buffer);
1445 return metadata_detail::NameLookup<Traits...>::Lookup(name, &helper);
1446 }
1447
1448 // Extract a piece of known metadata.
1449 // Returns nullopt if the metadata was not present, or the value if it was.
1450 // The same as:
1451 // auto value = m.get(T());
1452 // m.Remove(T());
1453 template <typename Which>
1454 absl::enable_if_t<Which::kRepeatable == false,
1455 absl::optional<typename Which::ValueType>>
1456 Take(Which which) {
1457 if (auto* p = get_pointer(which)) {
1458 absl::optional<typename Which::ValueType> value(std::move(*p));
1459 Remove(which);
1460 return value;
1461 }
1462 return {};
1463 }
1464
1465 // Extract repeated known metadata.
1466 // Returns an empty vector if the metadata was not present.
1467 template <typename Which>
1468 absl::enable_if_t<Which::kRepeatable == true,
1469 typename metadata_detail::Value<Which>::StorageType>
1470 Take(Which which) {
1471 if (auto* p = get_pointer(which)) {
1472 typename Value<Which>::StorageType value = std::move(*p);
1473 Remove(which);
1474 return value;
1475 }
1476 return {};
1477 }
1478
1479 // Parse metadata from a key/value pair, and return an object representing
1480 // that result.
1481 static ParsedMetadata<Derived> Parse(absl::string_view key, Slice value,
1482 bool will_keep_past_request_lifetime,
1483 uint32_t transport_size,
1484 MetadataParseErrorFn on_error) {
1485 metadata_detail::ParseHelper<Derived> helper(
1486 value.TakeOwned(), will_keep_past_request_lifetime, on_error,
1487 transport_size);
1488 return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
1489 }
1490
1491 // Set a value from a parsed metadata object.
1492 void Set(const ParsedMetadata<Derived>& m) {
1493 m.SetOnContainer(static_cast<Derived*>(this));
1494 }
1495
1496 // Append a key/value pair - takes ownership of value
1497 void Append(absl::string_view key, Slice value,
1498 MetadataParseErrorFn on_error) {
1499 metadata_detail::AppendHelper<Derived> helper(static_cast<Derived*>(this),
1500 value.TakeOwned(), on_error);
1501 metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
1502 }
1503
1504 void Clear();
1505 size_t TransportSize() const;
1506 Derived Copy() const;
1507 bool empty() const { return table_.empty() && unknown_.empty(); }
1508 size_t count() const { return table_.count() + unknown_.size(); }
1509
1510 private:
1511 friend class metadata_detail::AppendHelper<Derived>;
1512 friend class metadata_detail::GetStringValueHelper<Derived>;
1513 friend class metadata_detail::RemoveHelper<Derived>;
1514 friend class metadata_detail::CopySink<Derived>;
1515 friend class ParsedMetadata<Derived>;
1516
1517 template <typename Which>
1518 using Value = metadata_detail::Value<Which>;
1519
1520 // Table of known metadata types.
1521 PackedTable<Value<Traits>...> table_;
1522 metadata_detail::UnknownMap unknown_;
1523 };
1524
1525 // Ok/not-ok check for metadata maps that contain GrpcStatusMetadata, so that
1526 // they can be used as result types for TrySeq.
1527 template <typename Derived, typename... Args>
1528 inline bool IsStatusOk(const MetadataMap<Derived, Args...>& m) {
1529 return m.get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
1530 GRPC_STATUS_OK;
1531 }
1532
1533 template <typename Derived, typename... Traits>
1534 MetadataMap<Derived, Traits...>::MetadataMap(MetadataMap&& other) noexcept
1535 : table_(std::move(other.table_)), unknown_(std::move(other.unknown_)) {}
1536
1537 // We never create MetadataMap directly, instead we create Derived, but we
1538 // want to be able to move it without redeclaring this.
1539 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1540 template <typename Derived, typename... Traits>
1541 Derived& MetadataMap<Derived, Traits...>::operator=(
1542 MetadataMap&& other) noexcept {
1543 table_ = std::move(other.table_);
1544 unknown_ = std::move(other.unknown_);
1545 return static_cast<Derived&>(*this);
1546 }
1547
1548 template <typename Derived, typename... Traits>
1549 MetadataMap<Derived, Traits...>::~MetadataMap() = default;
1550
1551 template <typename Derived, typename... Traits>
1552 void MetadataMap<Derived, Traits...>::Clear() {
1553 table_.ClearAll();
1554 unknown_.Clear();
1555 }
1556
1557 template <typename Derived, typename... Traits>
1558 size_t MetadataMap<Derived, Traits...>::TransportSize() const {
1559 metadata_detail::TransportSizeEncoder enc;
1560 Encode(&enc);
1561 return enc.size();
1562 }
1563
1564 template <typename Derived, typename... Traits>
1565 Derived MetadataMap<Derived, Traits...>::Copy() const {
1566 Derived out;
1567 metadata_detail::CopySink<Derived> sink(&out);
1568 ForEach(&sink);
1569 return out;
1570 }
1571
1572 } // namespace grpc_core
1573
1574 struct grpc_metadata_batch;
1575
1576 using grpc_metadata_batch_base = grpc_core::MetadataMap<
1577 grpc_metadata_batch,
1578 // Colon prefixed headers first
1579 grpc_core::HttpPathMetadata, grpc_core::HttpAuthorityMetadata,
1580 grpc_core::HttpMethodMetadata, grpc_core::HttpStatusMetadata,
1581 grpc_core::HttpSchemeMetadata,
1582 // Non-colon prefixed headers begin here
1583 grpc_core::ContentTypeMetadata, grpc_core::TeMetadata,
1584 grpc_core::GrpcEncodingMetadata, grpc_core::GrpcInternalEncodingRequest,
1585 grpc_core::GrpcAcceptEncodingMetadata, grpc_core::GrpcStatusMetadata,
1586 grpc_core::GrpcTimeoutMetadata, grpc_core::GrpcPreviousRpcAttemptsMetadata,
1587 grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::UserAgentMetadata,
1588 grpc_core::GrpcMessageMetadata, grpc_core::HostMetadata,
1589 grpc_core::EndpointLoadMetricsBinMetadata,
1590 grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata,
1591 grpc_core::GrpcTagsBinMetadata, grpc_core::GrpcLbClientStatsMetadata,
1592 grpc_core::LbCostBinMetadata, grpc_core::LbTokenMetadata,
1593 grpc_core::XEnvoyPeerMetadata, grpc_core::W3CTraceParentMetadata,
1594 // Non-encodable things
1595 grpc_core::GrpcStreamNetworkState, grpc_core::PeerString,
1596 grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire,
1597 grpc_core::GrpcCallWasCancelled, grpc_core::WaitForReady,
1598 grpc_core::IsTransparentRetry, grpc_core::GrpcTrailersOnly,
1599 grpc_core::GrpcTarPit,
1600 grpc_core::GrpcRegisteredMethod GRPC_CUSTOM_CLIENT_METADATA
1601 GRPC_CUSTOM_SERVER_METADATA>;
1602
1603 struct grpc_metadata_batch : public grpc_metadata_batch_base {
1604 using grpc_metadata_batch_base::grpc_metadata_batch_base;
1605 };
1606
1607 #endif // GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
1608