Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2015 gRPC authors. |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 4 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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 |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 10 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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. |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 16 | * |
| 17 | */ |
| 18 | |
Craig Tiller | 9a4dddd | 2016-03-25 17:08:13 -0700 | [diff] [blame] | 19 | #ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_H |
| 20 | #define GRPC_CORE_LIB_TRANSPORT_METADATA_H |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 21 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 22 | #include <grpc/grpc.h> |
Craig Tiller | b37d53e | 2016-10-26 16:16:35 -0700 | [diff] [blame] | 23 | #include <grpc/slice.h> |
ctiller | fb93d19 | 2014-12-15 10:40:05 -0800 | [diff] [blame] | 24 | #include <grpc/support/useful.h> |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 25 | |
Craig Tiller | 87a7e1f | 2016-11-09 09:42:19 -0800 | [diff] [blame] | 26 | #include "src/core/lib/iomgr/exec_ctx.h" |
| 27 | |
ncteisen | 4b58405 | 2017-06-08 16:44:38 -0700 | [diff] [blame^] | 28 | #ifndef NDEBUG |
| 29 | extern grpc_tracer_flag grpc_trace_metadata; |
| 30 | #endif |
| 31 | |
Mark D. Roth | 07cd9c9 | 2016-06-27 10:14:38 -0700 | [diff] [blame] | 32 | #ifdef __cplusplus |
| 33 | extern "C" { |
| 34 | #endif |
| 35 | |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 36 | /* This file provides a mechanism for tracking metadata through the grpc stack. |
| 37 | It's not intended for consumption outside of the library. |
| 38 | |
| 39 | Metadata is tracked in the context of a grpc_mdctx. For the time being there |
| 40 | is one of these per-channel, avoiding cross channel interference with memory |
| 41 | use and lock contention. |
| 42 | |
| 43 | The context tracks unique strings (grpc_mdstr) and pairs of strings |
| 44 | (grpc_mdelem). Any of these objects can be checked for equality by comparing |
| 45 | their pointers. These objects are reference counted. |
| 46 | |
| 47 | grpc_mdelem can additionally store a (non-NULL) user data pointer. This |
| 48 | pointer is intended to be used to cache semantic meaning of a metadata |
| 49 | element. For example, an OAuth token may cache the credentials it represents |
| 50 | and the time at which it expires in the mdelem user data. |
| 51 | |
| 52 | Combining this metadata cache and the hpack compression table allows us to |
| 53 | simply lookup complete preparsed objects quickly, incurring a few atomic |
| 54 | ops per metadata element on the fast path. |
| 55 | |
| 56 | grpc_mdelem instances MAY live longer than their refcount implies, and are |
| 57 | garbage collected periodically, meaning cached data can easily outlive a |
Craig Tiller | 70b080d | 2015-11-19 08:04:48 -0800 | [diff] [blame] | 58 | single request. |
| 59 | |
| 60 | STATIC METADATA: in static_metadata.h we declare a set of static metadata. |
| 61 | These mdelems and mdstrs are available via pre-declared code generated macros |
| 62 | and are available to code anywhere between grpc_init() and grpc_shutdown(). |
| 63 | They are not refcounted, but can be passed to _ref and _unref functions |
| 64 | declared here - in which case those functions are effectively no-ops. */ |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 65 | |
| 66 | /* Forward declarations */ |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 67 | typedef struct grpc_mdelem grpc_mdelem; |
| 68 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 69 | /* if changing this, make identical changes in: |
| 70 | - interned_metadata, allocated_metadata in metadata.c |
| 71 | - grpc_metadata in grpc_types.h */ |
| 72 | typedef struct grpc_mdelem_data { |
| 73 | const grpc_slice key; |
| 74 | const grpc_slice value; |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 75 | /* there is a private part to this in metadata.c */ |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 76 | } grpc_mdelem_data; |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 77 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 78 | /* GRPC_MDELEM_STORAGE_* enum values that can be treated as interned always have |
| 79 | this bit set in their integer value */ |
| 80 | #define GRPC_MDELEM_STORAGE_INTERNED_BIT 1 |
| 81 | |
| 82 | typedef enum { |
| 83 | /* memory pointed to by grpc_mdelem::payload is owned by an external system */ |
| 84 | GRPC_MDELEM_STORAGE_EXTERNAL = 0, |
| 85 | /* memory pointed to by grpc_mdelem::payload is interned by the metadata |
| 86 | system */ |
| 87 | GRPC_MDELEM_STORAGE_INTERNED = GRPC_MDELEM_STORAGE_INTERNED_BIT, |
| 88 | /* memory pointed to by grpc_mdelem::payload is allocated by the metadata |
| 89 | system */ |
| 90 | GRPC_MDELEM_STORAGE_ALLOCATED = 2, |
| 91 | /* memory is in the static metadata table */ |
| 92 | GRPC_MDELEM_STORAGE_STATIC = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT, |
| 93 | } grpc_mdelem_data_storage; |
| 94 | |
Craig Tiller | 5e01e2a | 2017-01-20 18:11:52 -0800 | [diff] [blame] | 95 | struct grpc_mdelem { |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 96 | /* a grpc_mdelem_data* generally, with the two lower bits signalling memory |
| 97 | ownership as per grpc_mdelem_data_storage */ |
| 98 | uintptr_t payload; |
Craig Tiller | 5e01e2a | 2017-01-20 18:11:52 -0800 | [diff] [blame] | 99 | }; |
Craig Tiller | 9ecadce | 2016-11-18 14:52:25 -0800 | [diff] [blame] | 100 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 101 | #define GRPC_MDELEM_DATA(md) \ |
| 102 | ((grpc_mdelem_data *)((md).payload & ~(uintptr_t)3)) |
| 103 | #define GRPC_MDELEM_STORAGE(md) \ |
| 104 | ((grpc_mdelem_data_storage)((md).payload & (uintptr_t)3)) |
| 105 | #define GRPC_MAKE_MDELEM(data, storage) \ |
| 106 | ((grpc_mdelem){((uintptr_t)(data)) | ((uintptr_t)storage)}) |
| 107 | #define GRPC_MDELEM_IS_INTERNED(md) \ |
| 108 | ((grpc_mdelem_data_storage)((md).payload & \ |
| 109 | (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT)) |
Craig Tiller | 5e01e2a | 2017-01-20 18:11:52 -0800 | [diff] [blame] | 110 | |
Julien Boeuf | 75c9b6f | 2015-05-29 13:12:12 -0700 | [diff] [blame] | 111 | /* Unrefs the slices. */ |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 112 | grpc_mdelem grpc_mdelem_from_slices(grpc_exec_ctx *exec_ctx, grpc_slice key, |
| 113 | grpc_slice value); |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 114 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 115 | /* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata |
| 116 | object as backing storage (so lifetimes should align) */ |
| 117 | grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_exec_ctx *exec_ctx, |
| 118 | grpc_metadata *metadata); |
| 119 | |
| 120 | /* Does not unref the slices; if a new non-interned mdelem is needed, allocates |
| 121 | one if compatible_external_backing_store is NULL, or uses |
| 122 | compatible_external_backing_store if it is non-NULL (in which case it's the |
| 123 | users responsibility to ensure that it outlives usage) */ |
| 124 | grpc_mdelem grpc_mdelem_create( |
| 125 | grpc_exec_ctx *exec_ctx, grpc_slice key, grpc_slice value, |
| 126 | grpc_mdelem_data *compatible_external_backing_store); |
| 127 | |
| 128 | bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b); |
| 129 | |
| 130 | size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem elem); |
yang-g | cb7a802 | 2016-03-30 14:58:53 -0700 | [diff] [blame] | 131 | |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 132 | /* Mutator and accessor for grpc_mdelem user data. The destructor function |
| 133 | is used as a type tag and is checked during user_data fetch. */ |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 134 | void *grpc_mdelem_get_user_data(grpc_mdelem md, |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 135 | void (*if_destroy_func)(void *)); |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 136 | void *grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void *), |
Craig Tiller | 738e6db | 2016-11-15 09:29:44 -0800 | [diff] [blame] | 137 | void *user_data); |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 138 | |
ncteisen | 4b58405 | 2017-06-08 16:44:38 -0700 | [diff] [blame^] | 139 | #ifndef NDEBUG |
Craig Tiller | 1a65a23 | 2015-07-06 10:22:32 -0700 | [diff] [blame] | 140 | #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__) |
Craig Tiller | a59c16c | 2016-10-31 07:25:01 -0700 | [diff] [blame] | 141 | #define GRPC_MDELEM_UNREF(exec_ctx, s) \ |
| 142 | grpc_mdelem_unref((exec_ctx), (s), __FILE__, __LINE__) |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 143 | grpc_mdelem grpc_mdelem_ref(grpc_mdelem md, const char *file, int line); |
| 144 | void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md, |
Craig Tiller | a59c16c | 2016-10-31 07:25:01 -0700 | [diff] [blame] | 145 | const char *file, int line); |
Craig Tiller | 1a65a23 | 2015-07-06 10:22:32 -0700 | [diff] [blame] | 146 | #else |
Craig Tiller | 1a65a23 | 2015-07-06 10:22:32 -0700 | [diff] [blame] | 147 | #define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s)) |
Craig Tiller | a59c16c | 2016-10-31 07:25:01 -0700 | [diff] [blame] | 148 | #define GRPC_MDELEM_UNREF(exec_ctx, s) grpc_mdelem_unref((exec_ctx), (s)) |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 149 | grpc_mdelem grpc_mdelem_ref(grpc_mdelem md); |
| 150 | void grpc_mdelem_unref(grpc_exec_ctx *exec_ctx, grpc_mdelem md); |
Craig Tiller | 1a65a23 | 2015-07-06 10:22:32 -0700 | [diff] [blame] | 151 | #endif |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 152 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 153 | #define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key) |
| 154 | #define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value) |
Craig Tiller | 0160de9 | 2016-11-18 08:46:46 -0800 | [diff] [blame] | 155 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 156 | #define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL) |
| 157 | #define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL) |
Craig Tiller | 0160de9 | 2016-11-18 08:46:46 -0800 | [diff] [blame] | 158 | |
Mark D. Roth | c2de452 | 2016-04-29 10:25:27 -0700 | [diff] [blame] | 159 | /* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */ |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 160 | #define GRPC_MDELEM_LENGTH(e) \ |
| 161 | (GRPC_SLICE_LENGTH(GRPC_MDKEY((e))) + GRPC_SLICE_LENGTH(GRPC_MDVALUE((e))) + \ |
| 162 | 32) |
murgatroid99 | c3910ca | 2016-01-06 13:14:23 -0800 | [diff] [blame] | 163 | |
ctiller | fb93d19 | 2014-12-15 10:40:05 -0800 | [diff] [blame] | 164 | #define GRPC_MDSTR_KV_HASH(k_hash, v_hash) (GPR_ROTL((k_hash), 2) ^ (v_hash)) |
| 165 | |
Craig Tiller | 0e72ede | 2015-11-19 07:48:53 -0800 | [diff] [blame] | 166 | void grpc_mdctx_global_init(void); |
Craig Tiller | a59c16c | 2016-10-31 07:25:01 -0700 | [diff] [blame] | 167 | void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx); |
Craig Tiller | 0e72ede | 2015-11-19 07:48:53 -0800 | [diff] [blame] | 168 | |
Mark D. Roth | 07cd9c9 | 2016-06-27 10:14:38 -0700 | [diff] [blame] | 169 | #ifdef __cplusplus |
| 170 | } |
| 171 | #endif |
| 172 | |
Craig Tiller | 9a4dddd | 2016-03-25 17:08:13 -0700 | [diff] [blame] | 173 | #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */ |