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