Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / src / core / lib / transport / metadata_batch.h
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_CORE_LIB_TRANSPORT_METADATA_BATCH_H
20 #define GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
21
22 #include <grpc/support/port_platform.h>
23
24 #include <stdbool.h>
25
26 #include "absl/types/optional.h"
27
28 #include <grpc/grpc.h>
29 #include <grpc/slice.h>
30 #include <grpc/support/time.h>
31
32 #include "src/core/lib/iomgr/exec_ctx.h"
33 #include "src/core/lib/transport/metadata.h"
34 #include "src/core/lib/transport/static_metadata.h"
35
36 typedef struct grpc_linked_mdelem {
37   grpc_linked_mdelem() {}
38
39   grpc_mdelem md;
40   struct grpc_linked_mdelem* next = nullptr;
41   struct grpc_linked_mdelem* prev = nullptr;
42   void* reserved;
43 } grpc_linked_mdelem;
44
45 typedef struct grpc_mdelem_list {
46   size_t count;
47   size_t default_count;  // Number of default keys.
48   grpc_linked_mdelem* head;
49   grpc_linked_mdelem* tail;
50 } grpc_mdelem_list;
51
52 typedef struct grpc_metadata_batch {
53   /** Metadata elements in this batch */
54   grpc_mdelem_list list;
55   grpc_metadata_batch_callouts idx;
56   /** Used to calculate grpc-timeout at the point of sending,
57       or GRPC_MILLIS_INF_FUTURE if this batch does not need to send a
58       grpc-timeout */
59   grpc_millis deadline;
60
61   template <typename Encoder>
62   void Encode(Encoder* encoder) const {
63     for (auto* l = list.head; l; l = l->next) {
64       encoder->Encode(l->md);
65     }
66     if (deadline != GRPC_MILLIS_INF_FUTURE) encoder->EncodeDeadline(deadline);
67   }
68 } grpc_metadata_batch;
69
70 void grpc_metadata_batch_init(grpc_metadata_batch* batch);
71 void grpc_metadata_batch_destroy(grpc_metadata_batch* batch);
72 void grpc_metadata_batch_clear(grpc_metadata_batch* batch);
73 bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch);
74
75 /* Returns the transport size of the batch. */
76 size_t grpc_metadata_batch_size(grpc_metadata_batch* batch);
77
78 /** Remove \a storage from the batch, unreffing the mdelem contained */
79 void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
80                                 grpc_linked_mdelem* storage);
81 void grpc_metadata_batch_remove(grpc_metadata_batch* batch,
82                                 grpc_metadata_batch_callouts_index idx);
83
84 /** Substitute a new mdelem for an old value */
85 grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch,
86                                                  grpc_linked_mdelem* storage,
87                                                  grpc_mdelem new_mdelem);
88
89 void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage,
90                                    const grpc_slice& value);
91
92 /** Returns metadata value(s) for the specified key.
93     If the key is not present in the batch, returns absl::nullopt.
94     If the key is present exactly once in the batch, returns a string_view of
95     that value.
96     If the key is present more than once in the batch, constructs a
97     comma-concatenated string of all values in concatenated_value and returns a
98     string_view of that string. */
99 absl::optional<absl::string_view> grpc_metadata_batch_get_value(
100     grpc_metadata_batch* batch, absl::string_view target_key,
101     std::string* concatenated_value);
102
103 /** Add \a storage to the beginning of \a batch. storage->md is
104     assumed to be valid.
105     \a storage is owned by the caller and must survive for the
106     lifetime of batch. This usually means it should be around
107     for the lifetime of the call. */
108 grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch,
109                                                 grpc_linked_mdelem* storage)
110     GRPC_MUST_USE_RESULT;
111 grpc_error_handle grpc_metadata_batch_link_head(
112     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
113     grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT;
114
115 /** Add \a storage to the end of \a batch. storage->md is
116     assumed to be valid.
117     \a storage is owned by the caller and must survive for the
118     lifetime of batch. This usually means it should be around
119     for the lifetime of the call. */
120 grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch,
121                                                 grpc_linked_mdelem* storage)
122     GRPC_MUST_USE_RESULT;
123 grpc_error_handle grpc_metadata_batch_link_tail(
124     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
125     grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT;
126
127 /** Add \a elem_to_add as the first element in \a batch, using
128     \a storage as backing storage for the linked list element.
129     \a storage is owned by the caller and must survive for the
130     lifetime of batch. This usually means it should be around
131     for the lifetime of the call.
132     Takes ownership of \a elem_to_add */
133 grpc_error_handle grpc_metadata_batch_add_head(
134     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
135     grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
136
137 // TODO(arjunroy, roth): Remove redundant methods.
138 // add/link_head/tail are almost identical.
139 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
140     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
141     grpc_metadata_batch_callouts_index idx) {
142   return grpc_metadata_batch_link_head(batch, storage, idx);
143 }
144
145 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head(
146     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
147     grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) {
148   GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
149   storage->md = elem_to_add;
150   return grpc_metadata_batch_add_head(batch, storage, idx);
151 }
152
153 /** Add \a elem_to_add as the last element in \a batch, using
154     \a storage as backing storage for the linked list element.
155     \a storage is owned by the caller and must survive for the
156     lifetime of batch. This usually means it should be around
157     for the lifetime of the call.
158     Takes ownership of \a elem_to_add */
159 grpc_error_handle grpc_metadata_batch_add_tail(
160     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
161     grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT;
162
163 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
164     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
165     grpc_metadata_batch_callouts_index idx) {
166   return grpc_metadata_batch_link_tail(batch, storage, idx);
167 }
168
169 inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail(
170     grpc_metadata_batch* batch, grpc_linked_mdelem* storage,
171     grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) {
172   GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add));
173   storage->md = elem_to_add;
174   return grpc_metadata_batch_add_tail(batch, storage, idx);
175 }
176
177 grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src,
178                                           grpc_mdelem md);
179
180 struct grpc_filtered_mdelem {
181   grpc_error_handle error;
182   grpc_mdelem md;
183 };
184 #define GRPC_FILTERED_ERROR(error) \
185   { (error), GRPC_MDNULL }
186 #define GRPC_FILTERED_MDELEM(md) \
187   { GRPC_ERROR_NONE, (md) }
188 #define GRPC_FILTERED_REMOVE() \
189   { GRPC_ERROR_NONE, GRPC_MDNULL }
190
191 typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)(
192     void* user_data, grpc_mdelem elem);
193 grpc_error_handle grpc_metadata_batch_filter(
194     grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func,
195     void* user_data, const char* composite_error_string) GRPC_MUST_USE_RESULT;
196
197 #ifndef NDEBUG
198 void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch);
199 #else
200 #define grpc_metadata_batch_assert_ok(batch) \
201   do {                                       \
202   } while (0)
203 #endif
204
205 /// Copies \a src to \a dst.  \a storage must point to an array of
206 /// \a grpc_linked_mdelem structs of at least the same size as \a src.
207 ///
208 /// For each mdelem in \a src, if the mdelem is of storage types
209 /// GRPC_MDELEM_STORAGE_INTERNED or GRPC_MDELEM_STORAGE_ALLOCATED,
210 /// refs the original mdelem for the copy.  Otherwise, makes a new
211 /// mdelem that will hold its own refs to the key and value slices.
212 ///
213 /// Currently used only in the retry code.
214 void grpc_metadata_batch_copy(grpc_metadata_batch* src,
215                               grpc_metadata_batch* dst,
216                               grpc_linked_mdelem* storage);
217
218 void grpc_metadata_batch_move(grpc_metadata_batch* src,
219                               grpc_metadata_batch* dst);
220
221 #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */