Merge pull request #12298 from markdroth/default_metadata_fix
Detect default metadata using the callout list.
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index 80eb51f..711938b 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -154,17 +154,8 @@
}
// Returns true if initial_metadata contains only default headers.
-//
-// TODO(roth): The fact that we hard-code these particular headers here
-// is fairly ugly. Need some better way to know which headers are
-// default, maybe via a bit in the static metadata table?
static bool is_default_initial_metadata(grpc_metadata_batch *initial_metadata) {
- int num_default_fields =
- (initial_metadata->idx.named.status != NULL) +
- (initial_metadata->idx.named.content_type != NULL) +
- (initial_metadata->idx.named.grpc_encoding != NULL) +
- (initial_metadata->idx.named.grpc_accept_encoding != NULL);
- return (size_t)num_default_fields == initial_metadata->list.count;
+ return initial_metadata->list.default_count == initial_metadata->list.count;
}
grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c
index 8f24b85..a077052 100644
--- a/src/core/lib/transport/metadata_batch.c
+++ b/src/core/lib/transport/metadata_batch.c
@@ -105,6 +105,7 @@
return GRPC_ERROR_NONE;
}
if (batch->idx.array[idx] == NULL) {
+ if (grpc_static_callout_is_default[idx]) ++batch->list.default_count;
batch->idx.array[idx] = storage;
return GRPC_ERROR_NONE;
}
@@ -120,6 +121,7 @@
if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
return;
}
+ if (grpc_static_callout_is_default[idx]) --batch->list.default_count;
GPR_ASSERT(batch->idx.array[idx] != NULL);
batch->idx.array[idx] = NULL;
}
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
index 1b11a3e..57d298c 100644
--- a/src/core/lib/transport/metadata_batch.h
+++ b/src/core/lib/transport/metadata_batch.h
@@ -41,6 +41,7 @@
typedef struct grpc_mdelem_list {
size_t count;
+ size_t default_count; // Number of default keys.
grpc_linked_mdelem *head;
grpc_linked_mdelem *tail;
} grpc_mdelem_list;
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index 28f05d5..b20d94a 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -823,6 +823,31 @@
{.refcount = &grpc_static_metadata_refcounts[97],
.data.refcounted = {g_bytes + 1040, 13}}},
};
+bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT] = {
+ true, // :path
+ true, // :method
+ true, // :status
+ true, // :authority
+ true, // :scheme
+ true, // te
+ true, // grpc-message
+ true, // grpc-status
+ true, // grpc-payload-bin
+ true, // grpc-encoding
+ true, // grpc-accept-encoding
+ true, // grpc-server-stats-bin
+ true, // grpc-tags-bin
+ true, // grpc-trace-bin
+ true, // content-type
+ true, // content-encoding
+ true, // accept-encoding
+ true, // grpc-internal-encoding-request
+ true, // grpc-internal-stream-encoding-request
+ true, // user-agent
+ true, // host
+ true, // lb-token
+};
+
const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 76, 77, 78,
79, 80, 81, 82};
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index 93ab90d..f03a9d2 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -571,6 +571,8 @@
GRPC_BATCH_CALLOUTS_COUNT) \
: GRPC_BATCH_CALLOUTS_COUNT)
+extern bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT];
+
extern const uint8_t grpc_static_accept_encoding_metadata[8];
#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \
(GRPC_MAKE_MDELEM( \
diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py
index e56c627..6ee8a7c 100755
--- a/tools/codegen/core/gen_static_metadata.py
+++ b/tools/codegen/core/gen_static_metadata.py
@@ -132,29 +132,33 @@
('www-authenticate', ''),
]
+# Entries marked with is_default=True are ignored when counting
+# non-default initial metadata that prevents the chttp2 server from
+# sending a Trailers-Only response.
METADATA_BATCH_CALLOUTS = [
- ':path',
- ':method',
- ':status',
- ':authority',
- ':scheme',
- 'te',
- 'grpc-message',
- 'grpc-status',
- 'grpc-payload-bin',
- 'grpc-encoding',
- 'grpc-accept-encoding',
- 'grpc-server-stats-bin',
- 'grpc-tags-bin',
- 'grpc-trace-bin',
- 'content-type',
- 'content-encoding',
- 'accept-encoding',
- 'grpc-internal-encoding-request',
- 'grpc-internal-stream-encoding-request',
- 'user-agent',
- 'host',
- 'lb-token',
+ # (name, is_default)
+ (':path', True),
+ (':method', True),
+ (':status', True),
+ (':authority', True),
+ (':scheme', True),
+ ('te', True),
+ ('grpc-message', True),
+ ('grpc-status', True),
+ ('grpc-payload-bin', True),
+ ('grpc-encoding', True),
+ ('grpc-accept-encoding', True),
+ ('grpc-server-stats-bin', True),
+ ('grpc-tags-bin', True),
+ ('grpc-trace-bin', True),
+ ('content-type', True),
+ ('content-encoding', True),
+ ('accept-encoding', True),
+ ('grpc-internal-encoding-request', True),
+ ('grpc-internal-stream-encoding-request', True),
+ ('user-agent', True),
+ ('host', True),
+ ('lb-token', True),
]
COMPRESSION_ALGORITHMS = [
@@ -235,7 +239,7 @@
static_userdata = {}
# put metadata batch callouts first, to make the check of if a static metadata
# string is a callout trivial
-for elem in METADATA_BATCH_CALLOUTS:
+for elem, _ in METADATA_BATCH_CALLOUTS:
if elem not in all_strs:
all_strs.append(elem)
for elem in CONFIG:
@@ -372,7 +376,7 @@
# validate configuration
-for elem in METADATA_BATCH_CALLOUTS:
+for elem, _ in METADATA_BATCH_CALLOUTS:
assert elem in all_strs
print >> H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
@@ -540,7 +544,7 @@
print >> C, '};'
print >> H, 'typedef enum {'
-for elem in METADATA_BATCH_CALLOUTS:
+for elem, _ in METADATA_BATCH_CALLOUTS:
print >> H, ' %s,' % mangle(elem, 'batch').upper()
print >> H, ' GRPC_BATCH_CALLOUTS_COUNT'
print >> H, '} grpc_metadata_batch_callouts_index;'
@@ -548,7 +552,7 @@
print >> H, 'typedef union {'
print >> H, ' struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];'
print >> H, ' struct {'
-for elem in METADATA_BATCH_CALLOUTS:
+for elem, _ in METADATA_BATCH_CALLOUTS:
print >> H, ' struct grpc_linked_mdelem *%s;' % mangle(elem, '').lower()
print >> H, ' } named;'
print >> H, '} grpc_metadata_batch_callouts;'
@@ -556,6 +560,14 @@
print >> H, '#define GRPC_BATCH_INDEX_OF(slice) \\'
print >> H, ' (GRPC_IS_STATIC_METADATA_STRING((slice)) ? (grpc_metadata_batch_callouts_index)GPR_CLAMP(GRPC_STATIC_METADATA_INDEX((slice)), 0, GRPC_BATCH_CALLOUTS_COUNT) : GRPC_BATCH_CALLOUTS_COUNT)'
print >> H
+print >> H, ('extern bool grpc_static_callout_is_default['
+ 'GRPC_BATCH_CALLOUTS_COUNT];')
+print >> H
+print >> C, 'bool grpc_static_callout_is_default[GRPC_BATCH_CALLOUTS_COUNT] = {'
+for elem, is_default in METADATA_BATCH_CALLOUTS:
+ print >> C, ' %s, // %s' % (str(is_default).lower(), elem)
+print >> C, '};'
+print >> C
print >> H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (
1 << len(COMPRESSION_ALGORITHMS))